Costruire un laboratorio di test IoT

Andrea Dainese
22 Luglio 2022
Post cover

Come privati stiamo utilizzando molti dispositivi IoT consumer: quasi qualsiasi apparecchiatura domestica standard può ora essere controllata da remoto tramite un’applicazione specifica installata su uno smartphone.

La domanda è: quanto possiamo fidarci di questi dispositivi IoT? In che modo la nostra sicurezza digitale e la nostra privacy ne sono influenzate?

Per rispondere a queste domande, stiamo costruendo un piccolo e economico laboratorio di test per IoT.

Design

Il design è semplice: vogliamo un dispositivo flessibile (basato su Linux) in grado di intercettare tutto il traffico Ethernet/IP generato dal dispositivo IoT.

Lab network diagram

Il dispositivo Linux fornirà una connessione Internet al dispositivo IoT, eseguendo il dump di tutti i dati e metadati del traffico e intercettando anche il traffico cifrato.

Bill of Material (BOM)

Per il nostro laboratorio stiamo utilizzando:

L’immagine Kali Linux ARM può essere scritta sulla microSD usando Raspberry Pi Imager .

Sto utilizzando un vecchio access point wireless portatile che avevo acquistato anni fa. Immagino che questo modello funzioni ugualmente in modalità “Access Point”.

Primo avvio

Dopo il primo avvio, possiamo iniziare a configurare il nostro Raspberry Pi. Di default SSH è abilitato su Kali Linux:

sudo systemctl start ssh
sudo systemctl enable ssh

Dobbiamo installare alcuni pacchetti richiesti nei passaggi successivi:

sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get autoremove
sudo apt-get install iptables-persistent dnsmasq
sudo mkdir -p /var/log/analysis/zeek/

Infine, potremmo voler regolare la tastiera e il fuso orario:

sudo dpkg-reconfigure keyboard-configuration
sudo timedatectl set-timezone Europe/Rome

Vogliamo disabilitare gli adattatori Bluetooth e Wi-Fi integrati:

sudo echo "dtoverlay=disable-bt" >> /boot/config.txt
sudo echo "dtoverlay=disable-wifi" >> /boot/config.txt

È consigliato un riavvio per applicare tutte le configurazioni precedenti.

Configurazione di rete

Ci aspettiamo che il nostro Pi agisca come un router, quindi dobbiamo configurare due interfacce di rete. La prima è configurata di default con DHCP, la seconda deve essere configurata manualmente:

sudo cat << EOF > /etc/network/interfaces.d/eth0
auto eth0
    allow-hotplug eth0
    iface eth0 inet dhcp
EOF
sudo cat << EOF > /etc/network/interfaces.d/eth1
auto eth1
allow-hotplug eth1
iface eth1 inet static
    address 192.168.0.1
    netmask 255.255.255.0
EOF

Per consentire al Pi di agire come router dobbiamo abilitare l’IP forwarding IPv4. Modificare /etc/sysctl.conf e impostare:

net.ipv4.ip_forward=1

Poi ricaricare le impostazioni sysctl:

sysctl -p

Per rendere Internet raggiungibile dai dispositivi collegati a eth1 dobbiamo abilitare il NAT. Inoltre, vogliamo aggiungere alcune regole per forzare il traffico DNS e registrare le richieste provenienti da eth1:

sudo cat << EOF > /etc/iptables/rules.v4
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING ! -d 192.168.0.1/32 -p udp -m udp --dport 53 -j MARK --set-xmark 0x1/0xffffffff
-A PREROUTING -m mark --mark 0x1 -j LOG --log-prefix "iptables: direct_dns "
-A PREROUTING -m mark --mark 0x1 -j DNAT --to-destination 192.168.0.1
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:Services - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -m state --state NEW -j Services
-A FORWARD -i eth1 -m state --state NEW -j MARK --set-xmark 0x2/0xffffffff
-A FORWARD -m mark --mark 0x2 -j LOG --log-prefix "iptables: new_conn "
-A Services -p tcp -m tcp --dport 22 -j ACCEPT
-A Services -p tcp -m tcp --dport 9090 -j ACCEPT
COMMIT
EOF

Possiamo ricaricare il firewall con:

sudo iptables-restore /etc/iptables/rules.v4

Infine, vogliamo che iptables scriva i log in un file dedicato:

sudo cat << EOF > /etc/rsyslog.d/iptables.conf
:msg, regex, "iptables: " -/var/log/analysis/iptables.log
EOF

Dobbiamo riavviare rsyslog:

sudo systemctl restart rsyslog

Server DNS e DHCP

Per intercettare e tracciare le richieste DNS vogliamo utilizzare DNSMasq: può agire sia come server DNS che DHCP. Assicurarsi che DNSMasq carichi file di configurazione esterni modificando /etc/dnsmasq.conf:

conf-dir=/etc/dnsmasq.d/,*.conf

Configuriamo il DHCP in questo modo:

sudo cat << EOF > /etc/dnsmasq.d/network.conf
interface=eth1
dhcp-range=192.168.0.50,192.168.0.150,24h
EOF

Vogliamo inoltrare le richieste DNS a NextDNS. Assicurarsi di usare il proprio CPE, altrimenti non vedrete le richieste DNS nella dashboard di NextDNS:

sudo cat << EOF > /etc/dnsmasq.d/nextdns.conf
port=53
no-resolv
no-hosts
bogus-priv
strict-order
server=45.90.30.0
server=45.90.28.0
add-cpe-id=aaaaaa
EOF

Facciamo in modo che DNSMasq scriva tutte le richieste in un file specifico:

sudo cat << EOF > /etc/dnsmasq.d/logging.conf
# Log di ogni query DNS
log-queries

# Log con informazioni extra sul DHCP
log-dhcp

# Log in un file dedicato
log-facility=/var/log/analysis/dnsmasq.log
EOF

Infine, riavviamo DNSMasq:

sudo systemctl enable dnsmasq
sudo systemctl restart dnsmasq

Cattura completa del traffico

Anche se non sarà semplice analizzare tutti i pacchetti catturati, è utile averli a disposizione per esaminare conversazioni specifiche. Configuriamo un piccolo servizio per catturare tutti i pacchetti in ingresso da eth1:

sudo cat << EOF > /etc/systemd/system/tcpdump.service
[Unit]
After=network.target

[Service]
Restart=always
RestartSec=30
Environment="TCPDUMP_FORMAT=%%Y%%m%%d-%%H:%%M:%%S"
ExecStartPre=/bin/mkdir -p /var/log/analysis
ExecStart=/usr/bin/tcpdump -G 3600 -i eth1 -w "/var/log/analysis/tcpdump-eth1-${TCPDUMP_FORMAT}.pcap"
ExecStop=/bin/kill -s SIGINT $MAINPID

[Install]
WantedBy=multi-user.target
EOF

Dobbiamo abilitare e avviare il nuovo servizio:

sudo systemctl daemon-reload
sudo systemctl enable tcpdump
sudo systemctl start tcpdump

Cattura veloce del traffico (metadati)

Vogliamo installare anche i programmi ausiliari di Zeek:

Abbiamo bisogno di un modo più rapido per capire cosa sta facendo il dispositivo sotto test. Zeek può aiutarci a catturare i metadati del traffico in un formato leggibile. Zeek non è disponibile su Kali Linux per Raspberry Pi, quindi va compilato. Il processo richiede alcune ore:

sudo apt-get install cmake flex bison libpcap-dev libssl-dev python3 python3-dev swig zlib1g-dev
sudo apt-get install python3-git python3-semantic-version exim4
git clone --recursive https://github.com/zeek/zeek
cd zeek
./configure
make
sudo make install

Vogliamo installare anche i programmi ausiliari di Zeek:

cd auxil/zeek-aux
./configure
make
sudo make install

Potremmo voler includere la directory binaria di Zeek nel PATH:

export PATH=/usr/local/zeek/bin:${PATH}

Per configurare Zeek dobbiamo modificare /usr/local/zeek/etc/node.cfg:

[zeek]
type=standalone
host=localhost
interface=eth1

Vogliamo anche che Zeek scriva i log nella stessa directory usata prima. Modificare anche /usr/local/zeek/etc/zeekctl.cfg e impostare:

LogDir = /var/log/analysis/zeek

Infine, siamo pronti ad aggiornare installazione/configurazione di Zeek:

sudo zeekctl install

Possiamo avviare Zeek manualmente o configurare un servizio SystemD:

sudo cat << EOF > /etc/systemd/system/zeek.service
[Unit]
Description=zeek network analysis engine

[Service]
Type=forking
PIDFIle=/var/run/zeek.pid
ExecStart=/usr/local/zeek/bin/zeekctl start
ExecStop=/usr/local/zeek/bin/zeekctl stop

[Install]
WantedBy=multi-user.target
EOF

E abilitarlo all’avvio:

sudo systemctl daemon-reload
sudo systemctl enable zeek
sudo systemctl start zeek

MITM Proxy

Useremo MITM Proxy per analizzare le connessioni HTTP cifrate. Possiamo installarlo con:

sudo apt-get install mitmproxy

Configuriamo MITM Proxy come servizio di sistema:

sudo cat << EOF > /etc/systemd/system/mitmproxy.service
[Unit]
Description=MITMProxy

[Service]
Type=simple
ExecStart=/usr/bin/mitmweb --mode transparent --web-port 9090 --web-host 0.0.0.0 --no-web-open-browser
StandardOutput=file:/var/log/analysis/mitmproxy.log
StandardError=file:/var/log/analysis/mitmproxy.log

[Install]
WantedBy=multi-user.target
EOF

E vogliamo avviarlo all’avvio:

sudo systemctl daemon-reload
sudo systemctl start mitmproxy
sudo systemctl enable mitmproxy

Per intercettare il traffico dobbiamo fare NAT (REDIRECT) delle connessioni HTTP e HTTPS verso la porta usata da MITM Proxy (di default 8080), così il traffico può essere analizzato:

sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -m comment --comment "mitmproxy" -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 -m comment --comment "mitmproxy" -j REDIRECT --to-port 8080

Poiché vogliamo poter attivare e disattivare l’ispezione del traffico con MITM Proxy, possiamo usare un semplice script:

#!/bin/bash

function disable() {
    iptables -t nat -S | grep mitmproxy | cut -d" " -f2- | xargs -rL1 iptables -t nat -D
}

function enable() {
    disable
    iptables -t nat -A PREROUTING -p tcp --dport 80 -m comment --comment "mitmproxy" -j REDIRECT --to-port 8080
    iptables -t nat -A PREROUTING -p tcp --dport 443 -m comment --comment "mitmproxy" -j REDIRECT --to-port 8080
}

case $1 in
    enable)
        enable
        ;;
    disable)
        disable
        ;;
    *)
        echo "Usa $0 enable|disable"
        exit 1
        ;;
esac

Possiamo quindi attivare o disattivare l’intercettazione del traffico con:

sudo /root/mitmproxy.sh enable
sudo /root/mitmproxy.sh disable

L’interfaccia web di MITM Proxy è disponibile di default sulla porta 9090.

MITM Proxy web interface

Intercettazione del traffico

Una volta attivata l’intercettazione del traffico, le connessioni HTTPS vengono suddivise in due parti:

Traffic interception

Il primo diagramma mostra connessioni HTTPS non intercettate: in questo caso, il client riceve un certificato valido firmato da una CA riconosciuta.

Il secondo diagramma mostra connessioni HTTPS intercettate da MITM Proxy: il client riceve un certificato autofirmato e non valido, generato dal server MITM Proxy.

Abbiamo tre scenari possibili:

  1. L’applicazione non valida i certificati → MITM Proxy riesce a intercettare il traffico.
  2. L’applicazione valida i certificati, ma non è configurato il certificate pinning → possiamo installare e fidarci del certificato MITM Proxy.
  3. L’applicazione valida i certificati e usa il certificate pinning → l’intercettazione non funziona.

Nel secondo scenario possiamo abilitare l’intercettazione installando sul dispositivo il certificato di MITM Proxy e impostandolo come attendibile. Dal dispositivo basta aprire http://mitm.it e installare il certificato autofirmato.

mitm.it website

Certificate installer

Nel terzo scenario, l’applicazione si aspetta uno specifico certificato: anche se il certificato MITM Proxy è installato e attendibile, l’app riconosce il tentativo di MITM:

192.168.0.126:34170: Client TLS handshake failed. The client may not trust the proxy's certificate for www.google.com (OpenSSL Error([('SSL routines', 'ssl3_read_bytes', 'sslv3 alert certificate unknown')]))

Rotazione dei log

Per mantenere il sistema pulito configuriamo la rotazione dei log:

sudo cat << EOF > /etc/logrotate.d/analysis
/var/log/analysis/iptables.log {
    daily
    rotate 7
    nocompress
    missingok
    notifempty
    dateext
}
/var/log/analysis/dnsmasq.log {
    daily
    rotate 7
    nocompress
    missingok
    notifempty
    dateext
}
/var/log/analysis/tcpdump {
    daily
    rotate 0
    ifempty
    lastaction
        /usr/bin/find /var/log/analysis/ -name "tcpdump-*" -mtime +7 -delete
    endscript
}
EOF

Le esecuzioni successive di logrotate elimineranno i file obsoleti.

Pulizia dei log

Prima e dopo i test su un dispositivo IoT (e le app collegate), probabilmente vorremo cancellare i vecchi log.

Un breve script può automatizzare questo compito:

sudo cat << EOF > /root/clean.sh
#!/bin/bash

NEXT_DNS_PROFILE=aaaaaa
NEXT_DNS_APIKEY=a8f4e42e896ff37f181e3e8a42a9737e1423d8e7

find /var/log/analysis -type f -exec rm -f {} \;
rm -rf /var/log/analysis/zeek/2*
systemctl restart tcpdump
systemctl restart dnsmasq
systemctl restart rsyslog
systemctl restart mitmproxy

curl -X "DELETE" --header "X-Api-Key: ${NEXT_DNS_APIKEY}" https://api.nextdns.io/profiles/${NEXT_DNS_PROFILE}/logs
EOF

Sostituire i due parametri con i propri dati ed eseguire:

sudo chmod 755 /root/clean.sh
sudo /root/clean.sh

Conclusioni

Abbiamo costruito un piccolo laboratorio economico per testare dispositivi IoT consumer. Gli stessi strumenti, però, possono essere utilizzati in scenari di Threat Hunting o durante attività di analisi di rete (performance, troubleshooting, ecc.). Imparare a usare Linux significa avere sempre a disposizione una cassetta degli attrezzi potente e flessibile per affrontare analisi complesse.

Nei prossimi post vedremo come sfruttare al meglio questa configurazione in casi pratici dedicati.