This shows you the differences between two versions of the page.
|
iothings:laboratoare:2025:lab8 [2025/11/15 13:12] dan.tudose [Takeaway] |
iothings:laboratoare:2025:lab8 [2025/11/15 13:31] (current) dan.tudose [Lab 8. Security in IoT] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Lab 8. Security in IoT ====== | + | ====== Lab 8. IoT Security and Attacks ====== |
| ===== Breaking an insecure IoT sensor over HTTP ===== | ===== Breaking an insecure IoT sensor over HTTP ===== | ||
| Line 393: | Line 393: | ||
| * think about where and how to store keys on the device securely | * think about where and how to store keys on the device securely | ||
| + | ===== Trusted Certificates ===== | ||
| + | At a high level, to stop MITM you need the ESP32 to trust only a specific certificate (or CA) and to check that the server it’s talking to presents that particular certificate. | ||
| + | |||
| + | That means we can't relay anymore on setInsecure() and load a CA / server cert into the firmware instead. We will the use ''WiFiClientSecure'' verify it. | ||
| + | |||
| + | ==== Generate a CA ==== | ||
| + | |||
| + | Instead of a random self-signed server cert, you create a tiny lab CA and have it sign your server cert. On the server machine delete the old ''server.crt'' and ''server.key'' and generate the following: | ||
| + | |||
| + | <code bash> | ||
| + | # 1) Create CA key + cert | ||
| + | openssl genrsa -out ca.key 2048 | ||
| + | openssl req -x509 -new -key ca.key -out ca.crt -days 365 -subj "/CN=IoT Lab CA" | ||
| + | |||
| + | # 2) Create server key + CSR | ||
| + | openssl genrsa -out server.key 2048 | ||
| + | openssl req -new -key server.key -out server.csr -subj "/CN=iot-lab.local" | ||
| + | |||
| + | # 3) Sign server cert with CA | ||
| + | openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Now you have the following files: | ||
| + | * ''ca.crt'' – trust anchor you’ll embed in the ESP32 | ||
| + | * ''server.key'' + ''server.crt'' – used by Flask | ||
| + | * CN of server cert is ''iot-lab.local'' (hostname you’ll use in the URL) | ||
| + | |||
| + | Run Flask again: | ||
| + | <code bash> | ||
| + | python secure_server.py # same as before, just point it to server.crt/server.key | ||
| + | </code> | ||
| + | |||
| + | ==== Modify the Firmware to Add the Certificate ==== | ||
| + | |||
| + | Get the new modified code from [[iothings:laboratoare:2025_code:lab8_3|here]] and paste the contents of the ''ca.crt'' file into the main.cpp file. | ||
| + | |||
| + | Notice we are using a domain name instead of an IP address for the server and we are not relying anymore on ''setInsecure()'', rather we're using HTTPS with CA cert verification. | ||
| + | |||
| + | ==== Replay the MITM Attack ==== | ||
| + | |||
| + | Try to repeat your ARP poisoning + mitmproxy trick with this setup. ARP poisoning still works: packets still flow ESP32 → attacker → server, but when mitmproxy shows its own cert to the ESP32, WiFiClientSecure aborts the handshake. That is because the cert is not signed by your lab CA. Your HTTP POST never happens; your code will see a connection / TLS error. | ||
| + | |||
| + | In brief: | ||
| + | * With ''setInsecure()'', MITM can see JSON + MAC and divert, alter or even drop packets entirely. | ||
| + | * With ''setCACert()'' + correct hostname, MITM can still route traffic (DoS is possible), but they cannot terminate TLS in the middle; they get reduced to a dumb packet forwarder or DoS attacker. | ||