MitMing SSL/TLS Connections
There are many reasons for one to intercept SSL/TLS connections. For companies it's the base for Data Loss Prevention (DLP) programs, for pentesters it's to understand and attack an application and for me, it's a way to implement a new feature on Gauntlet that will allow users to add custom headers to scanners' requests.
With custom headers you will be able to override an existing header or add a new one. There are many reasons that users may want to do this, such as:
- Add authentication headers (Basic or JWT for example)
- Add an extra header to track all requests performed by Gauntlet
- Add an additional headers that is necessary for the application to work
That said, how could we do this?
- We could rely on each scanner to add a custom header .. if the scanners support such feature, which is unlikely
- Add one layer on top of scanner requests that will intercept them and modify, which sounds much more plausible
To intercept those requests we can use a proxy, a program specifically built to intercept requests and responses, such as squid. But squid is focused on content filtering and caching rather than request/response manipulation, but can do it to a certain extent, e.g., add headers.
The problem is that squid doesn't support SSL interceptation out of the box. You need to recompile it with certain flags. That said I was looking for the source on the official website, and for my surprise I also identified that the squid version available on Ubuntu package repository is much lower than the latest version (from 3.0 to 3.5).
Ok, I downloaded the latest version, added flags, compiled, started squid passing
https_port 3129 on the configuration file, but this port didn't show up no matter what. Only the
http_port 3128, which is the port to intercept http traffic. I could try again, check flags and everything else, but the documentation on squid, although the software be popular, is very messy compared to documentation on programming languages and APIs. It's weird because squid is popular since a long time ago, but it's still hard to figure out some things.
And then I realized that there is a proxy built specifically to manipulate requests and responses. That's what I was looking for in the first place. That's the mitmproxy. A program built in python.
Only a few commands to let it up and running:
sudo apt-get install python-pip python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev libjpeg8-dev zlib1g-dev sudo pip install mitmproxy mitmdump # mitmproxy actually is an interactive console # mitmdump is basically "mitm capabilities for tcpdump" that comes w/ mitmproxy
And to test:
curl -x http://127.0.0.1:8080 http://some-http-site.com # -x points to the proxy
What about HTTPS sites? There is a catch.
HTTPS connections are encrypted end-to-end, thus the only way to intercept is to generate a certificate on the MITM software that is trusted by a CA present on the requester's device. As we're using the same machine, we have to make our operating system trust the CA cert from mitmproxy.
# run mimtproxy once to generate the file below (mitmproxy-ca-cert.cer) and exit mimtproxy # add cert to trusted certs on your O.S. cp ~/.mitmproxy/mitmproxy-ca-cert.cer /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt /usr/sbin/update-ca-certificates
And it's done. Now we can try HTTPS websites:
curl -x https://127.0.0.1:8080 https://dadario.com.br
Ok, but how to manipulate requests?
We can use just run mitmdump passing a script file, e.g.,
mitmdump -s add_headers.py. The content of
add_headers.py is this:
def request(context, flow): flow.request.headers["newheader"] = "foo"