Skip to content

Hands On IoT MitM (Part 1)

This is the third article in the Hunter Hacking Project.

In How To Quickly Setup A Wireless MitM Proxy, I discussed how to setup a "Man In The Middle" (MitM) proxy using Kali Linux, but what is a man-in-the-middle proxy? What are they used for?

In this article we'll explore MitM proxies using Kali Linux and an Adafruit Feather M0 WiFi module.

The Basics

A man-in-the-middle (MITM) proxy is an application or device that intercepts communication between two parties and can eavesdrop, modify, or block data transmission.

man-in-the-middle-attack.png

In the early days of the internet, before the Let's Encrypt revolution, it was ridiculously easy to insert yourself in between one computer and another: Cain and Abel, ettercap, etherape...

Mainly for lulz, but probably for some nefarious stuff, as well.

Nowadays, unless you're "leet", it's basically impossible to "sniff" a random TLS-secured connection, unless... you have root on one of the devices.

To better understand things, we're going to examine a few scenarios.

Our intention is to understand what is required to intercept traffic between an ATWINC1500-based IoT device and an AWS IoT MQTT endpoint:

  1. Basic SSL Connection

    By establishing a basic SSL connection, we confirm that our network is configured correctly to allow the microcontroller (uC) to connect to google.com over port 443. We also confirm that the Root Cert Store on the uC contains a Root CA certificate which trusts Google's certificate****.

  2. MitM'd SSL Connection

    Establishing an SSL connection through mitmproxy allows us to understand what happens when an SSL connection is man-in-the-middle'd. Learning how to get things working helps us understand the role that the Root Cert Store plays in the ATWINC1500.

  3. Basic MQTTS Connection

    This scenario allows us to understand how to get AWS IoT configured as an MQTT endpoint. In addition, we learn how how to write TLS certificates to the ATWINC1500.

  4. MitM'd MQTTS Connection

    This final scenario allows us to understand how insert a... ...

For all of these tests, we'll be using an Adafruit Feather M0 module.


1. Basic SSL Connection

The Arduino WiFi101 Library includes the WifiSSLClient example, which simply connects to an access point and retrieves the google.com homepages and prints it to the serial terminal.

Pasted image 20230321155605.png

We can use this example out-of-the-box, with one change. Add the following to your setup():

void setup() {
  WiFi.setPins(8, 7, 4, 2);
... 

After uploading the sketch to you should see the following:

Pasted image 20230321161513.png

Troubleshooting

Didn't work?

Try adding the google.com certificate to your ATWINC1500 by following the instructions here: ATWINC1500 IoT Module Deep-Dive (Part 1)#Uploading SSL Root Certificates.


2. MitM'd SSL Connection

Now let's run the same example through a transparent proxy, using mitmproxy.

I'm going to setup my proxy, using the instructions here: How To Quickly Setup A Wireless MitM Proxy#Start Transparent MitM Proxy)

Upload Sketch

Update the WifiSSLClient sketch so that it connects to your proxy and re-run the sketch:

Pasted image 20230321171146.png

Hrm...

Checking the mitmproxy logs we see the following:

192.168.1.22:60689: client connect
192.168.1.22:60689: server connect 17.248.180.49:443
192.168.1.22:60689: Client TLS handshake failed. Client and mitmproxy cannot agree on a TLS version to use. You may need to adjust mitmproxy's tls_version_client_min option.
192.168.1.22:60689: client disconnect
192.168.1.22:60689: server disconnect 17.248.180.49:443
192.168.1.3:62014: client connect
192.168.1.3:62014: server connect 142.250.68.68:443
192.168.1.3:62014: Client TLS handshake failed. The client disconnected during the handshake. If this happens consistently for www.google.com, this may indicate that the client does not trust the proxy's certificate.
192.168.1.3:62014: client disconnect
192.168.1.3:62014: server disconnect 142.250.68.68:443
...

This line is of particular interest:

Client TLS handshake failed. The client disconnected during the handshake. If this happens consistently for www.google.com, this may indicate that the client does not trust the proxy's certificate.

mitmproxy is hinting that something similar to this is happening within the microcontroller's network stack causing the connection to be aborted:

Pasted image 20230324184127.png

If you recall from How To Quickly Setup A Wireless MitM Proxy, the above error occurs when we haven't installed the mitmproxy root certificate.

Let's test this hypothesis by installing the mitmproxy root certificate.

Installing mitmproxy Root Certificate

1. Upload Serial Bridge

First, we need to install the peddamat/SerialBridge so atwinc1500_fwtool.exe can talk directly to the ATWINC1500 module over USB.

2. Obtain Certificate

You'll need a copy of the mitmproxy certificate, which you can grab by connecting to bumper_mitm on your phone and downloading the cert in .cer format.

Place the certificate in a directory named "certs".

$ tree
.
├── Interm
...
├── atwinc1500_fwtool.exe
├── atwinc1500_fwtool.pdb
└── certs
    └── mitmproxy-ca-cert.cer

3. Write Certificate

To reduce any confounding variables, let's first erase both stores on our ATWINC1500.

$ atwinc1500_fwtool.exe erase --root

Erasing device...
Root Certificate Store Updated Successfully On: Flash

Confirming:

$ atwinc1500_fwtool.exe read

Dumping Root Cert Store contents...
Root Certificate Store Loaded Successfully From: Flash
- Found 0 entries!
...

Now we let's add the cert to the Root Cert Store:

$ atwinc1500_fwtool.exe update --root --ca_dir certs

Root Certificate Store Loaded Successfully From: Flash

>>>Found Certificate:
>>>     mitmproxy
Root Certificate Store Updated Successfully On: Flash

Confirming:

$ atwinc1500_fwtool.exe read

Dumping Root Cert Store contents...
Root Certificate Store Loaded Successfully From: Flash
- Found 1 entries!
  Name Hash (SHA1): 14 65 65 22 40 7A D1 30 64 06 9E 87 AD BB C5 31 7D 37 94 FF   Certificate 1: RSA
  <2023-03-19 20:00:22> to <2033-03-18 20:00:22>

Re-Upload Sketch

Re-uploading the Sketch and checking the serial monitor yields in:

Pasted image 20230323034716.png BOOM!!!

Troubleshooting

Trouble connecting to your Adafruit Feather M0?

Check to make sure your VMWare Player isn't intercepting the USB device connection request:

Pasted image 20230321171217.png


3. Basic MQTTS Connection

Now that we have a handle of the basics, let's model something more realistic, a scenario where our Adafruit Feather M0 is an IoT device which communicates with an AWS IoT MQTT endpoint.

Before we get started, it's worth spending a moment talking about mutual TLS.

TODO: Tighten up verbiage

Mutual TLS (mTLS) differs from the TLS we've previously done, in that it's a protocol that allows a mutual exchange of keys during session initiation.

What this means is that the "IoT Device" has its own unique public/private key pair, which essentially serves as a username and password when it connects to AWS IoT.

This means...

AWS IoT Setup

First, you'll need to create an AWS account by heading over to: aws.amazon.com

Next, scroll down and click the "Connect an IoT device" link under "Build a solution".

Pasted image 20230323051616.png

This will bring up a "Prepare your device" wizard:

Pasted image 20230323051904.png

Scroll down and click Next:

Pasted image 20230323052017.png

Under "Thing properties" enter "feathermitm":

Pasted image 20230323052205.png

and click Next:

Pasted image 20230323052308.png

Select "Python" and click Next:

Pasted image 20230323054804.png

Click Download connection kit and click Next:

Pasted image 20230323054910.png

Finish by clicking View thing:

Pasted image 20230323053002.png


Testing

Connection Kit

Unzip connect_device_package.zip:

$ tree
.
├── feathermitm-Policy
├── feathermitm.cert.pem
├── feathermitm.private.key
├── feathermitm.public.key
└── start.sh

and run start.sh in a WSL terminal:

$ ./start.sh
...
Running pub/sub sample application...
Connecting to xxx.amazonaws.com with client ID 'basicPubSub'...
Connected!
Subscribing to topic 'sdk/test/python'...
Subscribed with QoS.AT_LEAST_ONCE
Sending messages until program killed
Publishing message to topic 'sdk/test/python': Hello World! [1]
Received message from topic 'sdk/test/python': b'"Hello World! [1]"'

We can see the messages show up in the "MQTT test client" section:

Pasted image 20230323054417.png


MQTT Explorer

Since we're going to be in MQTT-world for a while, it's worth getting a hang of MQTT Explorer, a tool which lets us pub and sub MQTT endpoints:

Pasted image 20230323060157.png

Grab the connection settings from start.sh, populate the host name and port, and then click Advanced:

start.sh
#!/usr/bin/env bash
...
# run pub/sub sample app using certificates downloaded in package
printf "\nRunning pub/sub sample application...\n"
python3 aws-iot-device-sdk-python-v2/samples/pubsub.py --endpoint xxx.iot.amazonaws.com --ca_file root-CA.crt --cert feathermitm.cert.pem --key feathermitm.private.key --client_id basicPubSub --topic sdk/test/python --count 0

Set the "MQTT Client ID" to "basicPubSub" and click Certificates:

Pasted image 20230323060415.png

Populate the entries with the contents of the connect_device_package folder as shown, and click Back (twice):

Pasted image 20230323060516.png

NOW CLICK SAVE!!!

Then click on "MQTT test client" in the AWS IoT sidebar, enter sdk/test/python in the Topic filter, and click Subscribe:

Pasted image 20230323061209.png

Back in MQTT Explorer, click "Connect", enter "sdk/test/python" in the Topic, add a message and click Publish:

{
  "message": "Hello from MQTT Explorer!"
}

Pasted image 20230323061012.png

Back in "MQTT test client", you should see your message!

Pasted image 20230323061238.png


IoT Device Setup

Now that we've setup and tested our AWS IoT gateway, let's prepare our "IoT device".

Unlike mitmproxy, IOXY requires some certificate configuration work to get things working.

Write Certificates

For the mTLS handshake to work, we're going to need to upload the private key and cert to the ATWINC1500 TLS Server Store and Amazon's RootCA cert to its Root Cert Store.

Start by renaming root-CA.crt to root-CA.cer:

Pasted image 20230323093544.png

Then upload the device's private key and certificate to the TLS Server Store:

Update TLS Server Store
$ atwinc1500_fwtool.exe update \
    --tls \
    --key connect_device_package\feathermitm.private.key \
    --cert connect_device_package\feathermitm.cert.pem

TLS Certificate Store Loaded Successfully From: Flash
TLS Certificate Store Updated Successfully On: Flash

Now upload the Amazon Root CA certificate to the Root Cert Store:

Update Root Cert Store
$ atwinc1500_fwtool.exe update --root --ca_dir connect_device_package

Root Certificate Store Loaded Successfully From: Flash

>>>Found Certificate:
>>>     Amazon Root CA 1
Root Certificate Store Updated Successfully On: Flash

Verifying:

$ atwinc1500_fwtool.exe read

Dumping TLS Store contents...
TLS Certificate Store Loaded Successfully From: Flash
Found 3 entries...
- RSA Certificate Chain File List
  NAME                                             SIZE TYPE         INFO
  PRIV_62a1f32e421df7f65e2290155189f76dbd6953bd    1208 PRIVATE KEY
  CERT_62a1f32e421df7f65e2290155189f76dbd6953bd     861 CERTIFICATE  AWS IoT Certificate
- Private Key Details:
  Modulus (N) :(00B7440C)(256)
        A9 34 C5 DD 7F 50 C2 23 90 AA 85 5B DA EC 23 80
        09 AB E7 B8 1E 1F 66 1C 37 9E 3A 28 BB 9D 07 6C
        AE D9 50 5C 45 D8 F1 5A 09 4A 44 A1 56 1F A6 41
        4C B4 20 2D D9 0F 78 68 E7 6E 11 61 94 54 70 13
        DF A0 86 38 BC 0F 9E 09 B0 04 39 53 F2 29 35 BF
        8E FA 19 97 86 40 74 3C 20 79 B9 0F 2A 1E 7A 01
        F5 55 C2 BB CE F6 7A AA 14 48 BB 77 92 AB 0E 6D
        C2 FE 6C 62 F6 DD 76 90 63 40 C8 58 2F 4F D6 B1
        87 09 CF C7 40 34 24 E7 26 C1 BB 29 F5 45 C1 7D
        75 4D 79 4A C0 F7 78 FA EA 7F 3F 44 DA F8 BE D0
        17 3D 9E FF 0C BF F9 B6 C4 06 5F 12 88 7C C2 9F
        B8 82 D3 E2 21 A9 73 72 AC 09 9B 2B 4F 91 8A 2D
        E6 5F A0 83 73 82 56 5D 4E 6C 85 A9 43 87 74 81
        2A B3 47 D5 E2 18 F8 39 FC 66 1A 5B D2 C4 06 24
        CC 4C 0E BF 49 2A 90 3D 0F 47 12 16 52 F0 5E B7
        4A 3E F4 76 02 6E 64 C0 16 0B 14 A7 93 90 58 99

- TLS Certificate Details:
    Subject <AWS IoT Certificate>
    Issuer  < >
    <2023-03-23 12:47:18> to <2049-12-31 23:59:59>

Dumping Root Cert Store contents...
Root Certificate Store Loaded Successfully From: Flash
Found 1 entries:
1) RSA Certificate: 5/26/2015 [00:00:00] to 1/17/2038 [00:00:00]
   Name Hash (SHA1): A8 66 80 C4 56 27 2E AF E3 A7 CE 2E 49 D1 31 DC 65 BB B1 ED

Upload Sketch

The Arduino Cloud Provider Examples Library includes the AWS_IoT_WiFi sketch, which can be used to connect to the AWS IoT Gateway.

Install it by opening the Library Manager and search for "Arduino Cloud":

Now, open the AWS_IoT_WiFi sketch:

Pasted image 20230321175304.png

Alternatively, use the PlatformIO code here: peddamat/AWS_IoT_WiFi

Compiling and uploading the sketch results in:

Pasted image 20230324223401.png

Voila!

You should see this in the "MQTT test client" console:

Pasted image 20230324223523.png


Next Steps

Ok, as usual, things have gone way longer than expected, so we'll leave the grand finale to the next part, here: Hands On IoT MitM (Part 2).


Troubleshooting

Having issues connecting to IOXY from MQTT Explorer?

You can check to see if your firewall is blocking connections between your machine and your WSL container by launching a Python web server on each port, and checking accessibility via a web browser.

[I]  python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [23/Mar/2023 16:23:33] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [23/Mar/2023 16:23:33] code 404, message File not found
127.0.0.1 - - [23/Mar/2023 16:23:33] "GET /favicon.ico HTTP/1.1" 404 -
[I]  python3 -m http.server 8883
Serving HTTP on 0.0.0.0 port 8883 (http://0.0.0.0:8883/) ...
Having issues with the atwinc1500_fwtool update command?

You can debug the atwinc1500_fwtool.exe binary by opening the solution in Visual Studio 2022 and:

Pasted image 20230323020936.png

Pasted image 20230323020835.png

update --key=..\aws-iot-certs\adafeathermqtt.private.key -p12 --cert=..\aws-iot-certs\adafeathermqtt.cert.pem --ca_dir=..\aws-iot-certs\RootCA


Last update: 2023-03-25