TLDR: you can use mitmproxy to modify stuff before it sent to Burp Proxy. Instruction below.
Recently we were asked to asses a oldschool Java client server application. After configuring BurpSuite as a proxy and trusting the CA cert, we noticed the client communication still gave an error. It turned out the client and server used zlib to compress communication. The client could not accept plaintext responses. But the plaintext data was easier to work with. So we needed a way to decompress incoming requests and compress responses just before they were sent to the client-application.
This could probably be done by employing a Burp extension but I have never built one and it feels like its a lot of work. Some googling resulted in an extension called “JDser-DComp“, but the extension was only available as source. And it wasnt 100% what we wanted
So essentially we need to do the following:
- decompress the zlib packed request body that is sent by the client using mitmproxy
- remove the accept-encoding header from the request using mitmproxy
- forward the request to BurpSuite
- edit/modify etc the request in BurpSuite
- compress the response received from the server back to zlib-format using mitmproxy
Setting up:
First we need to add the mitmproxy CA certificate to OpenWebStart (Java). And point its proxy to localhost 8080. Next we need to make sure Burp proxy runs at a different port, i choose 8081. Run mitm proxy using the following command:
mitmproxy --mode upstream:http://127.0.0.1:8081 --ssl-insecure -s ./header.py
This forces mitmproxy to use burp as an upstream proxy, and trust its certificates. Its probably possible to add the Burp CA certificate to mitmproxy but this works just fine. The headers.py script modifies the incoming traffic and response traffic so we can use it in plaintext and the client still receives a compressed message. The header.py content:
import zlib
class AddHeader:
def response(self, flow):
flow.response.content=zlib.compress(flow.response.content)
#flow.response.headers["Content-Encoding"] = "zlib"
def request(self, flow):
flow.request.headers.pop("Accept-Encoding", None)
if(flow.request.headers.get("Content-Encoding") == "zlib"):
flow.request.headers.pop("Content-Encoding", None)
flow.request.content = zlib.decompress(flow.request.content)
flow.request.headers["Content-Length"] = len(flow.request.content)
addons = [AddHeader()]
We had some issues modifying the response content-encoding header which resulted in errors. There is probably something happening after we compress and change the header. My guess is that mitmproxy tries to evaluate and change things based on, for example the content-encoding.
Got a useful tip from Rick Verdoes (Hackify) he uses a Burp extension “Python Scripter” that allows you to execute python code on each request and response. Havent tried it myself but it seems like a viable alternative.
Thanks @t_oh for help with the python debugging 🙂