Python SSL Mitm Proxy and More

Sat, 14 Feb 2009 17:54:19 GMT

Lately I've been busy with putting together a python module which allows me to create man-in-the-middle (MITM) HTTP Proxies with a programmer-friendly extension interface and support for SSL. This kind of proxies can be used for many things ranging from creating your own tampering proxies to hijacking network traffic via a transparent proxy connection.

[/files/2009/02/httpservers.py](/files/2009/02/httpservers.py)

I am quite pleased with the end result! Although my proxy hasn't been heavily tested, I find the code lot better when compared to Dave Aitel's SpikeProxy (sorry Dave :)) and extending/adding functionalities is actually piece of cake.

I need to mention that the code is heavily inspired by various source codes found on the Internet via Google. Actually all SSL MITM Proxy code for python available today are absolute crap. Codez are either broken or you need to be a rocket scientist in order to understand them. Nevertheless, these sources proved to be quite helpful when I was stuck. And I was stuck many times.

My module also contains stubs for creating all kinds of HTTP servers. It follows a simple design pattern introduced by Python's built-in SocketServer, therefore the code is very pythonic. I need to mention that I used monkey patching only once and it can be removed as it is unimportant. So overall, the module should be pretty clean although there is a room for improvement.

Have a look at the code and if you can contribute with fixes and improvements that will be great. Just let me know.

MikeMike
Nice tool. I have a couple of corrections. I would have emailed them, but I couldn't find your email. Now you have mine though so we should get in contact. Line 488: SSL.SysCallError should be OpenSSL.SSL.SysCallError I was getting a SysCallError exception on reads, so I added "or OpenSSL.SSL.SysCallError" to line 276. The do_GET function on line 161 was having problems with certain web sites. I think it has something to do with the if hasattr(self.server, 'chainedHandler") block from the other do_GET function elsewhere in the code. When I copied that code from the other do_GET to the do_GET on line 161 it worked for every site I tried it on. Email me so I know how to get a hold of you later if I find more bugs, ok?
pdppdp
Hi Mike, Thanks for letting me know. It will be great if we can polish this module as much as possible as I see that there is a lot of interest in a technology like this one and no one is providing it at the moment. I personally need it for several projects of mine. Regarding your comment on HTTPServerWrapper class. This code is essential in order to make SSL sniffing work. It basically transmits information about the path which needs to be accessed from the SSL endpoint the browser tries to connect to via the proxy. Anyway, I will email you so we can keep in touch.
AnonymousAnonymous
Good stuff. If i wanted to write some basic tests for this, how would I go about doing it? I think it'd be useful. I was thinking something along the lines of, say, having a Paramiko-driven app try and connect to https://gmail.com using some dummy username and password we create, and seeing if it can intercept the information properly (?) Just a thought. I don't have enough netsec experience to contribute directly, but i do have python experience enough (and with scripting paramiko) to do this i think. At the very least, setting up some unit tests should help me figure out how the python networkign stuff works better. Again, good stuff! I'll be keeping tabs on this definitely.
pdppdp
The file is self-descriptive. It will be great if someone can spend some time cleaning up the code an also to make sure that everything works ok.
schangschang
Mike, could you share the fixed code with us ? I have been trying to fix it myself. It kind of works but it always takes like 1 or 2 minutes before I get an answer to my POST... thanks
pdppdp
schang, I have been a bit busy lately but I do have some patches that needs to be merged and I will do so as soon as I get some free time.
Eric BlairEric Blair
I don't use Python, but clicked to see "SSL Mitm Proxy." It might be easier to write this as a general (CGI) script that could be developed on your local box without a web server. I could script it using a Bourne shell script ;-) but I would probably use my favorite, Tcl. From the command-line, you can use "openssl s_client", and s_server and generate a certificate: http://www.securityfocus.com/infocus/1486 http://www.vanemery.com/Linux/Apache/openSSL.html Anyway, I put up a page regarding SSL termination: http://grandscheme.org/gs.cgi?How-secure-is-https.html Since a browser will complain about certificate mismatches, I was wondering how you were expecting your code to be useful as part of a "transparent SSL proxy." You made no mention of certificates.
pdppdp
good stuff. the reason I wrote this proxy is to create a new HTTP tampering tool which I am comfortable with. but yes, you can use the code for MITM attacks but you have to make a couple of changes. I think that recently there was a presentation which discussed MITM-like attacks for SSL. worth googling it!
Christian MartorellaChristian Martorella
Hi pdp, we created a proxy https in python, for our tool ProxyStrike, you can check it here: http://www.edge-security.com/proxystrike.php We faced the same problem as you, at time we wrote the tool the only available proxy in http was the one in spikeProxy. By the way we updated the tool and now you can easily implement plugins. -CMM
pdppdp
cool, thanks! is this tool written in python as well?
eduardoeduardo
Hi, I would like to try your mitm proxy for ssl, but i have not been able to make it work with windows, could you help me provide a step by step? feel free to contact me by email thanks
darbdarb
Any chance of using this to effectively block Skype's use of https, while allowing the rest of https traffic alone?
SubbuSubbu
I'm seeing a bug in this proxy, I will investigate a fix, but wanted to let you know. The issue is this: I clear all the cookies in a browser. Then I fire up the proxy and browse some websites, and then look at what cookies are set in my browser, I don't see some cookies that I expect to be set. When I do the exact same thing (clear cookies, _ exact websites), I can see the cookies being set in the browser. So my inference is that the proxy is somehow eating up the cookies in the response. These sites are http, not https, so that is also not the issue. Any pointers for investigation?
pdppdp
darb, not sure! you have to check.