Skip to content

Instantly share code, notes, and snippets.

@juhakivekas
Created January 29, 2018 06:12
Show Gist options
  • Save juhakivekas/66bebbd963c193417bb25d1a936c99c2 to your computer and use it in GitHub Desktop.
Save juhakivekas/66bebbd963c193417bb25d1a936c99c2 to your computer and use it in GitHub Desktop.
A mitmproxy script for pre- and postprocessing of http messages for ZAP and Burp
### MITMPROXY FORMATTER TEMPLATE
# This script is meant to be run in a proxy chain to enable scanning with security tools such
# as Burp and ZAP. Common use cases for this type of scripts are fixing annoying encodings,
# packings, re-signing client-signed requests, and requests with hashes of some parameters.
# The script needs to run in two chained instances of mitmproxy, with ZAP chained in the middle,
#
# client -> mitmdump(preprocess):8081 -> ZAP:8080 -> mitmdump(postprocess):8082 -> server
#
# mitmdump -p 8081 --insecure -b 127.0.0.1 -s 'packer.py --pre' -U https://127.0.0.1:8080
# mitmdump -p 8082 --insecure -b 127.0.0.1 -s 'packer.py --post'
#
# Ideally the edited requests sent by the unpacker are such that they are easy to work with and
# able to be scanned using existing scanning vectors/variants. The packer then has to restore
# the message into a format such that the server can accept it successfully. This way the
# temporary unpacking and packing should not interfere with the client or the server while still
# enabling work to be done without tools being crippled.
import argparse
import urllib.parse
class Preprocess:
def __init__(self):
return
def request(self, flow):
# scope this script only to certain requests
if not '/api' in flow.request.url:
return
#do any preprocessing
#in this example the JSON bodies of messages were sent with the content-type of
#application/x-www-form-urlencoded, so we need to fix this before scanners work
flow.request.text = urllib.parse.unquote(flow.request.text)
flow.request.headers['Content-Type'] = 'application/json'
# add a temporary marker to the message
flow.request.headers['X-Mitmproxy'] = 'edited'
def response(self, flow):
#editing responses is sometimes helpful too
return
class Postprocess:
def __init__(self):
return
def request(self, flow):
# only run packer on marked requests
if not 'X-Mitmproxy' in flow.request.headers:
return
#do any postprocessing
flow.request.text = urllib.parse.quote(flow.request.text)
flow.request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
# delete the marker header
del(flow.request.headers['X-Mitmproxy'])
def response(self, flow):
#editing responses is sometimes helpful too
return
def start():
parser = argparse.ArgumentParser()
parser.add_argument('--post', action='store_true')
parser.add_argument('--pre', action='store_true')
args = parser.parse_args()
if args.post:
return Postprocess()
if args.pre:
return Preprocess()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment