'Cookie manipulation in Mitmproxy requests and responses
I have problem adding new cookies that are only visible to the client in reverse proxy mode of mitmproxy. There seems to be little documentation or examples that cover cookie manipulation in it.
I want to:
- add cookie to the response that is sent to the client
- intercept the same cookie when the client sends it back, to identify the user, and remove it before it gets sent to the destination server
How can this be accomplished?
Solution 1:[1]
NOTE: I believe for 1. you meant add a cookie to the "request".
You can write a script that implements the request
and response
functions and modifies those objects. Then you can run mitmproxy
with the -s
flag and pass it the path to the script file and that should get you going. See below the main structure of the script (and further below the helper functions).
# USAGE: mitmproxy -s path/to/http_manipulate_cookies.py
from mitmproxy import http
PATH_TO_COOKIES = "./cookies.json" # insert your path to the cookie file here
FILTER_COOKIES = {"userdata", "_ga"} # update this to the specific cookie names you want to remove
# NOTE: we use a set for lookup efficiency
# -- Main interception functionality --
def request(flow: http.HTTPFlow) -> None:
"""Add a specific set of cookies to every request."""
# obtain any cookies from the request
_req_cookies_str = flow.request.headers.get("cookie", "")
req_cookies = parse_cookies(_req_cookies_str)
# add our cookies to the original cookies from the request
all_cookies = req_cookies + load_json_cookies()
# NOTE: by adding it to the end we should overwrite any existing cookies
# of the same name but if you want to be more careful you can iterate over
# the req_cookies and remove the ones you want to overwrite first.
# modify the request with the combined cookies
flow.request.headers["cookie"] = stringify_cookies(all_cookies)
def response(flow: http.HTTPFlow) -> None:
"""Remove a specific cookie from every response."""
set_cookies_str = flow.response.headers.get("set-cookie", "")
# NOTE: use safe attribute access (.get), in some cases there might not be a set-cookie header
if set_cookies_str:
resp_cookies = parse_cookies(set_cookies_str)
# remove the cookie we want to remove
resp_cookies = [c for c in resp_cookies if c["name"] not in FILTER_COOKIES]
# modify the request with the combined cookies
flow.response.headers["set-cookie"] = stringify_cookies(resp_cookies)
An example of the cookie.json
doc would be the following:
[
{
"name": "mycookie",
"value": "somevalue"
},
{
"name": "anothercookie",
"value": "foobarfoobazfoofoobuzz"
}
]
Here are the helper functions I used:
from typing import List, Dict
import json
# -- Helper functions --
def load_json_cookies():
"""
Load a particular json file containing a list of cookies.
"""
with open(PATH_TO_COOKIES, "r") as f:
return json.load(f)
# NOTE: or just hardcode the cookies as [{"name": "", "value": ""}]
def stringify_cookies(cookies: List[Dict]) -> str:
"""
Creates a cookie string from a list of cookie dicts.
"""
return ";".join([f"{c['name']}={c['value']}" for c in cookies])
def parse_cookies(cookie_string: str) -> List[Dict[str, str]]:
"""
Parses a cookie string into a list of cookie dicts.
"""
cookies = []
for c in cookie_string.split(";"):
c = c.strip()
if c:
k, v = c.split("=", 1)
cookies.append({"name": k, "value": v})
return cookies
I submitted this example to mitmproxy as a PR here: https://github.com/mitmproxy/mitmproxy/pull/5278
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | WillMonge |