[HN Gopher] Antigravity.py (2020)
       ___________________________________________________________________
        
       Antigravity.py (2020)
        
       Author : chha
       Score  : 107 points
       Date   : 2021-08-16 13:00 UTC (10 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | Waterluvian wrote:
       | Might not be obvious to all:
       | 
       | This is in the python standard library. So you can open a python
       | REPL and type `import antigravity`
        
       | Xavdidtheshadow wrote:
       | I've long known that `import antigravity` would open the xkcd
       | comic, but I never knew there was also a geohashing function!
       | 
       | That was a favorite activity of mine in high school. On Friday
       | evening, we'd look at the nearest graticule(s) to our town and
       | pick one for a Saturday day trip. Trucking out to a random point
       | on a map is a great way to explore your metro area and see things
       | you never would otherwise.
       | 
       | Heartily recommend trying it out. Looks like the map (linked from
       | the comic) is no longer working:
       | http://carabiner.peeron.com/xkcd/map/map.html
       | 
       | But, with this function, there may yet be hope!
        
       | isp wrote:
       | This looked innocuous at first glance, but this "antigravity"
       | Easter egg has been found to have security implications.
       | 
       | See "Hacking with Environment Variables", which specifically
       | exploits the antigravity module for arbitrary code execution -
       | https://www.elttam.com/blog/env/#content
       | 
       | Previous HN comments:
       | https://news.ycombinator.com/item?id=23828045
        
         | thebeardisred wrote:
         | Related to the idea "innocuous at first glance", that time when
         | folks got cute with the man command:
         | 
         | https://git.savannah.nongnu.org/cgit/man-db.git/commit/src/m...
         | 
         | Turns out it was breaking a users automated tests -
         | https://unix.stackexchange.com/questions/405783/why-does-man...
        
         | chias wrote:
         | I'm unconvinced. "The ability to turn this into arbitrary code
         | execution depends on what other executables are available on
         | the system" is doing a LOT of heavy lifting here.
         | 
         | Remember: you have control over only the environment variables,
         | and you do not have the ability to alter the arguments. In
         | order for this to represent arbitrary code execution, you need
         | for the system to have an executable on it that, when executed
         | with the argument "https://xkcd.com/353/", grants you arbitrary
         | code execution.
         | 
         | So, you have full control over the environment variables, and
         | that's it. How do you turn effectively
         | [binary] "https://xkcd.com/353/"
         | 
         | into arbitrary code execution, where [binary] is an executable
         | already on the machine?
        
           | marcinzm wrote:
           | The next section of the link literally goes into how to
           | achieve all of that using a call to perl.
        
           | isp wrote:
           | There is a proof of concept given, "Figure-4: arbitrary code
           | execution achieved using multiple environment variables
           | against Python 2 and Python 3":                   $ docker
           | run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e
           | 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;'
           | python:2.7.18 python /dev/null         uid=0(root)
           | gid=0(root) groups=0(root)         Invalid -W option ignored:
           | unknown warning category: 'antigravity.x'              $
           | docker run -e 'PYTHONWARNINGS=all:0:antigravity.x:0:0' -e
           | 'BROWSER=perlthanks' -e 'PERL5OPT=-Mbase;print(`id`);exit;'
           | python:3.8.2 python /dev/null         uid=0(root) gid=0(root)
           | groups=0(root)         Invalid -W option ignored: unknown
           | warning category: 'antigravity.x'
        
             | ASalazarMX wrote:
             | TL;DR: 'import antigravity' is fine, but Python can be
             | tricked with environment variables to use Perl as the web
             | browser, which has arbitrary code execution through
             | environment variables.
        
               | shaded-enmity wrote:
               | Defense in depth would disagree that it is fine. I'm
               | pretty sure this vulnerability can go much further if you
               | combine it with, for example, the `https_proxy`
               | environment variable.
        
               | tyingq wrote:
               | And Perl (specifically "perlthanks") was just the first
               | thing they found that worked. Bash had similar problems
               | in the past, and I imagine there's other "installed by
               | default" stuff that can be coaxed into running code in
               | environment variables.
        
               | chias wrote:
               | Interesting, that's pretty cool. Thanks!
        
             | geofft wrote:
             | If you can influence arbitrary environment variables, you
             | _usually_ have a lot more options - you could set
             | PYTHONHOME or PYTHONPATH (influence where Python finds
             | imports), LD_LIBRARY_PATH (influence where shared libraries
             | come from), PATH (influence where the Python command itself
             | comes from), etc. etc.
             | 
             | In this particular case, they happened to be in a situation
             | where they couldn't easily figure out how to create new
             | files but they could set environment variables. From a
             | design perspective, as a reviewer, I would not believe that
             | this makes it _safe_ to have attacker-controlled
             | environment variables, although I admit I wouldn 't know
             | exactly how (and this post is a pretty clever approach to
             | making the attack work).
        
             | btown wrote:
             | And specifically, although it is nowadays uncommon for
             | Python scripts to be run the way old-school WSGI web
             | services were, with a script being fired up for every
             | request and mapping user-controlled query parameters to
             | environment variables, this was at one time actually the
             | motivating example for
             | https://www.python.org/dev/peps/pep-0333/ ! It's a common
             | enough attack pattern that
             | https://capec.mitre.org/data/definitions/77.html exists and
             | specifically cautions applications against trusting
             | environment variables. There are very few places in Python
             | where upon importing a module, an environment variable is
             | trusted and triggered; all of them should be seen as
             | security holes.
        
               | dpwm wrote:
               | Surely this is only a security risk if antigravity is
               | imported?
               | 
               | What cause would there be to import antigravity in a CGI
               | service - or anything other than a terminal in which you
               | could already execute arbitrary code?
               | 
               | I am struggling to understand, even with the proof of
               | concept, how the situation could arise where an attacker
               | could realistically exploit this, based largely on the
               | uselessness of the antigravity module.
        
               | geofft wrote:
               | See the "Making Progress With PYTHONWARNINGS" section in
               | the article posted - setting the environment variable
               | PYTHONWARNINGS to a value mentioning the antigravity
               | module causes it to be imported, even if there's no
               | "import antigravity" statement in the actual source.
        
               | dpwm wrote:
               | Not sure how I missed that - it was even in the proof of
               | concept in the message I replied to. Thanks for the help.
               | 
               | There are multiple failings that don't seem like a big
               | deal taken in isolation:
               | 
               | - The PYTHONWARNINGS and whole Warning Filters system.
               | 
               | - The webbrowser module executing a given executable from
               | an environment variable.
               | 
               | - The antigravity module running webbrowser.open() on
               | import.
               | 
               | All of these sort of seem a bit like sacrificing good
               | taste for convenience. But in combination, in a situation
               | where you don't control the environment variables, they
               | do lead to arbitrary code execution.
               | 
               | In other words, it's not all antigravity's fault, but
               | those side effects on import make this possible.
        
               | kzrdude wrote:
               | You're right about sacrificing good taste for
               | convenience, but since this is an easter egg, it's
               | sacrificing good taste for a laugh, and I think that
               | pushes it over the precipe over into being a bad idea.
        
               | jvanderbot wrote:
               | I left one window open, but what is to guarantee a
               | burgler would use _that_ window??
        
               | dpwm wrote:
               | Absolutely, I agree now that I see it, and these seem
               | like numerous innocent-seeming footguns just waiting for
               | abuse.
               | 
               | Add the not-too-far-fetched-seeming assumption that it's
               | fine to let the Internet define your environment
               | variables, and it's a plausible exploit.
               | 
               | This is why, as another commenter points out, defense in
               | depth is so important.
        
           | [deleted]
        
         | oyf wrote:
         | If you have the ability to set environment variables then it's
         | basically already game over, with or without the existence of
         | the antigravity module.
         | 
         | You could set PATH to change which files are executed in
         | certain scenarios. You could set SSLKEYLOGFILE which logs
         | session keys to an arbitrary file, essentially nullifying
         | TLS/SSL protections. On Linux you can just set PROMPT_COMMAND
         | to whatever you want and it'll be executed any time a bash
         | prompt is printed.
         | 
         | It's an interesting attack vector, but a vulnerability requires
         | impact, and I'm not sure this has very much.
        
         | [deleted]
        
       | glofish wrote:
       | reading the module, I have also learned about the Munroe
       | geohashing:
       | 
       | https://en.wikipedia.org/wiki/Geohashing
       | 
       | and
       | 
       | https://xkcd.com/426/
       | 
       | official website:
       | 
       | https://geohashing.site/geohashing/Main_Page
       | 
       | oddly the geohash function in the antigravity module prints to
       | the screen rather than returning the values ... seems odd to say
       | the least
        
       | szszrk wrote:
       | I chuckled a bit, but it took me a while to realize what code
       | repository it is from. Chuckled again.
        
       | tersers wrote:
       | TIL python has a webbrowser module
        
         | mxuribe wrote:
         | I just learned this myself the other day...
         | 
         | I was looking at the "Automate the Boring Stuff with Python"
         | book by Al Sweigart (which admittedly i have not read cover to
         | cover, but rather use it as a reference) for some help with a
         | little polite scraping, and lo and behold the webbrowser
         | module...See chapter 12:
         | https://automatetheboringstuff.com/2e/chapter12/
         | 
         | I have not played much with it yet, but man, python continues
         | to impress me!
        
         | vascocosta wrote:
         | Me too and I'm a long time Python programmer.
        
         | hansor wrote:
         | Me too... Hilarious!
        
         | jp_sc wrote:
         | But not a texteditor.
         | 
         | You can use this library for that:
         | https://pypi.org/project/texteditor/
         | 
         | (Disclaimer: I'm the author)
        
           | BiteCode_dev wrote:
           | Idle
        
             | ehsankia wrote:
             | You missed the point of what the library does. Similar to
             | webbrowser (which isn't a full browser), all it does is
             | open your default text editor.
        
           | diogenesjunior wrote:
           | There's not really a reason for a built in text editor
        
             | [deleted]
        
             | jp_sc wrote:
             | Is not a built in text editor, is a command to open
             | programmatically your default text editor to edit a file
             | (new or existing).
             | 
             | There are several cases when you would want to do that, for
             | example, think on the git CLI, that opens one so you can
             | write a commit message, etc.
             | 
             | And is not only about using the EDITOR variable, most non-
             | programmers doesn't have one defined or it points to vim or
             | something equally terrible for non technical users.
        
         | boublepop wrote:
         | Back in the day, python was popular because it was a "batteries
         | included" language, which meant I supposedly had almost
         | everything you would need right there in the standard language.
         | These days of cause no one runs python without going on a
         | shopping spree of additional packages on pypi, so it would be
         | less of a big deal if it didn't include a browser lib, or a GUI
         | lib out of the box.
        
         | codetrotter wrote:
         | And it's even using the user preferred browser!
         | 
         | Tried it on my MacBook M1 and it opens Brave which is my main
         | browser.
         | 
         | Wonder if it's using the same mechanism as the macOS open(1)
         | command does for opening URLs. Or maybe even calling the
         | /usr/bin/open binary.
        
           | zirak wrote:
           | From the python source code: https://github.com/python/cpytho
           | n/blob/11749e2dc20ad6a76e9a3...
           | 
           | It seems to be shelling out to osascript, either telling it
           | to OpenURL or open.
        
       | chha wrote:
       | Related: https://xkcd.com/353/
        
         | TuringTest wrote:
         | Well, it _does_ have  "float" in the code, doesn't it?
        
         | [deleted]
        
         | codetrotter wrote:
         | Well yes. From the OP link:
         | webbrowser.open("https://xkcd.com/353/")
        
       | diogenesjunior wrote:
       | I get a type error in line 13 running the code:
       | TypeError: openssl_md5() takes no keyword arguments
        
         | shmageggy wrote:
         | From the docs
         | 
         | > Changed in version 3.9: All hashlib constructors take a
         | keyword-only argument usedforsecurity...
        
           | geofft wrote:
           | To add to this - antigravity is part of the Python standard
           | library, and you want to run the version that's shipped with
           | your version of Python, not the version from the latest
           | development build. Do "python3 -m antigravity".
        
       | chronolitus wrote:
       | A description of what the code does:
       | 
       | First, the line
       | 
       | webbrowser.open("https://xkcd.com/353/")
       | 
       | is obvious, it opens a browser pointing to the relevant XKCD
       | comic, containing a joke which inspired this code.
       | 
       | Then, a geohash function is declared which takes the user's
       | current latitude/longitude, and the current date-time, and
       | returns a target latitude/longitude. According to a previous
       | comic (https://xkcd.com/426/) this corresponds to the game of
       | 'geohashing' where players are supposed to physically travel to
       | arbitrary locations and prove it.
        
         | nwsm wrote:
         | For more context, "geohashing" is a play on geocaching [0].
         | 
         | This is not to be confused with a geohash [1].
         | 
         | [0] https://en.wikipedia.org/wiki/Geocaching
         | 
         | [1] https://en.wikipedia.org/wiki/Geohash
        
       ___________________________________________________________________
       (page generated 2021-08-16 23:01 UTC)