Wednesday, July 12, 2017

Mo My MIMO

I have a tough time thinking of the Internet of Things as a new technology arena, considering I've worked on all kinds of embedded systems that were connected wirelessly, directly or indirectly, to the Internet. These ranged from eight-bit micro controllers to in-flight entertainment systems for business jets.

Recently I've been futzing around with a couple of IoT devices:

Untitled

the Amazon Web Services IoT Button and

Untitled

the TP-Link Smart Plug Mini. I was inspired by the clever work of my friend, former colleague, and one time college flat mate Paul Moorman who used the IoT Button with a Smart Plug to implement a wireless light switch. Based on prior work by other folks who reverse engineered the Smart Plug (and which he referenced in his article), Paul controlled the Smart Plug by punching a hole in his firewall for the port on the Smart Plug from which it receives commands, 9999, and then writing an AWS Lambda script in Python to talk to it. Pressing the IoT button stimulates the Lambda script in the AWS cloud to send the appropriate message to the Smart Plug to turn the power to any connected device on or off. Pretty cool.

I'd be lying if I didn't admit I was a little envious of Paul's ingenuity.

Ultimately I came up with my own practical application - significantly, as it turned out, one that required no development or firewall changes on my part - of just the Smart Plug: to turn our "cat cam" - an existing web cam in our kitchen near the cats' food bowls - on and off from my iPhone. It was pretty trivial to do. On a recent trip from Denver to Phoenix I was able to turn the cat cam on remotely using the TP-Link Kasa app and then use the webcam's app to peek at our beloved feline overlords (long may they rule).

Here's the thing: I had to punch a hole in my firewall for a port forwarding rule to connect to the cat cam from the webcam app on my phone, resolving the address using dynamic DNS. But I didn't have to punch a hole for the Smart Plug, or use dynamic or any other kind of DNS identifying my home network. What had to be happening is that the Kasa app was connecting to a server in the inter webs, and the Smart Plug was making its own outgoing bidirectional TCP connection through my firewall to a server (perhaps the same one) also on the inter webs.

Untitled

My first stab at reverse engineering this was to dig out my AirPcap NX tool, a USB 2.0 device from Riverbed Technologies that allows you to look at WiFi traffic and, providing you have the WPA pass phrase and catch the wireless end point when it first connects to the WiFI network, decrypt and decode IP packets as they fly through the air. The AirPcap has drivers for Windows and it is recognized by Wireshark.

This pretty much went according to plan until I realized that I was only seeing the traffic from the server on the inter webs to the Smart Plug, not in the other direction. Peering closely at the TCP connection setup responses from the server, I could tell definitively that the Smart Plug was the connection instigator. The Smart Plug was establishing a TCP stream socket to port 50443 on server dev.tplinkcloud.com. That domain name resolved to a server that was hosted in the AWS cloud (and unrelated to the AWS IoT button implementation). I could see packets from the server to the Smart Plug, but not in the other direction.

This put me in a paroxysm of web searching.

What I think was happening (see disclaimer above) is that my home WiFi access point supports 3 x 3 MIMO (multiple input multiple output) WiFi channels: it exploits spatial multiplexing to divide the packet stream into three transmit and three receive WiFi streams, all on the same radio channel, and which are all in the air simultaneously, each being handled by a separate antenna. My AirPcap NX supports at most 2 x 2 MIMO; it simply could not see all the traffic in the air.

I was using the AirPcap on my company laptop, a Lenovo ThinkPad running Windows 7. As part of my research, almost by accident, I came across an article describing the WiFi radios used by Apple, and discovered that my personal MacBook Pro came equipped with a radio capable of 3 x 3 MIMO with the same WiFi channels and technologies as my access point. Even better, the MacOS WiFi drivers natively support "monitor" mode, equivalent to promiscuous mode for Ethernet wired interfaces. And Wireshark for MacOS understood all of this already.

It didn't take very long for me to verify all of this using my MacBook Pro. I had Wireshark on my personal laptop peeking at all of the WiFi traffic between the Smart Plug and the TP-Link server in the Amazon cloud.

Spur WLAM pcapng

I was pretty proud of myself until Paul asked me why I didn't just insert a SharkTap into the Ethernet connection between my cable modem and my access point and Wireshark the traffic from there. A little embaressed, I did that too.

SharkTap Between Cable Modem and Router

For sure that was the simpler solution, but it had the side effect of NATting all the IP addresses on my home network to the one address assigned via DHCP to my access point by my internet service provider. It made the Wireshark traces a little harder to grok, but really no big deal.

Never the less, I'm glad I wasn't as smart of Paul and so didn't think of that solution right off the bat. I now know I have another useful tool in my troubleshooting arsenal, one that came ready made right out of the box.

3 comments:

Fazal Majid said...

Alternatively you could run tcpdump on your router and export the pcap files to your computer for importing into Wireshark.

You probably don't need the SharkTap: most decent managed Ethernet switches also have the ability to mirror a port's traffic to another where you, and they are cheaper, e.g. the Ubiquiti UniFi switch US-8-150W or the ZyXEL GS1900-8HP, both offering PoE in the bargain.

I use a small ShuttleDS57U fanless PC as a router/firewall running OpenBSD, and it is configured to continuously log all packets from IoT devices (basically any device not explicitly whitelisted) using an OpenBSD feature called pflog (essentially the same as a tcpdump packet capture with some metadata as to which PF packet filter rule triggered the logging).

Most IoT devices suffer shocking levels of insecurity. The port 50443 in your case suggests some form of SSL/TLS is at play, but often IoT stacks dispense with actually verifying the certificates, so you can perform a man-in-the-middle attack using something like Charles Proxy to see the actual data being sent. Eventually they will catch on and start securing their SSL at which point we will need to find other ways of reverse-engineering those protocols.

Chip Overclock said...

What shocks me is how little (or no) technical documentation exists for these devices. It's not just a matter of reverse engineering them in order to integrate them into your application or environment. It's also matter of making an informed risk assessment as to how secure (or not) they are. That's how I ended up going down this path.

Wow, I haven't thought about Charles Proxy in years. I've used it, but can't quite remember when and how and why.

Thanks for the comment!

Chip Overclock said...

Ah, find and grep to the rescue: I used Charles Proxy to debug a C++ application I wrote that used Amazon Web Services (AWS) Simple Storage Service (S3): https://github.com/coverclock/com-diag-hayloft .