Kontrolliertes Labor für Schwachstellenforschung und -reproduktion für CVE-2020-14343 in PyYAML
Dieses Projekt demonstriert CVE-2020-14343 in einer kontrollierten und isolierten Docker-Umgebung.
Das Lab enthält zwei Umgebungen:
yaml.safe_load()Das Lab demonstriert den vollständigen Lebenszyklus der Schwachstelle:
Die in diesem Lab verwendete Reproduktionsnutzlast ist absichtlich harmlos und gibt lediglich einen Testmarker aus.
| Eigenschaft | Details |
|---|
| CVE | CVE-2020-14343 |
| Produkt | PyYAML |
| Betroffene Versionen | Versionen vor 5.4 |
| Korrigierte Version | 5.4 |
| Schwachstellentyp | Unzureichende Eingabevalidierung (CWE-20) |
| Schweregrad | Kritisch |
| Angriffsfläche | YAML-Eingabe, die mit verwundbarer Ladefunktionalität verarbeitet wird |
Die Schwachstelle tritt auf, wenn nicht vertrauenswürdige YAML-Eingabe mit verwundbarer PyYAML-Ladefunktionalität verarbeitet wird.
PyYAML-Versionen vor 5.4 erlaubten speziell präparierte YAML-Tags, einschließlich Python-spezifischer Tags wie:
!!python/object/new
um Objektkonstruktionsfunktionalität zu erreichen, wenn FullLoader verwendet wurde.
Ein bösartiges YAML-Dokument kann daher eine unbeabsichtigte Ausführung von Python-Code verursachen.
Das Problem stand im Zusammenhang mit einer unvollständigen Korrektur einer früheren PyYAML-Schwachstelle.
PyYAML 5.4 behob CVE-2020-14343, indem beliebige Python-Tags zu UnsafeLoader verschoben wurden.
Für Anwendungen, die nicht vertrauenswürdiges YAML verarbeiten, verwendet dieses Lab außerdem yaml.safe_load() als sicheren Ladeansatz.
Das Lab enthält zwei isolierte Docker-Dienste:
Host Machine
|
+------------+------------+
| |
v v
Vulnerable App Patched App
localhost:5000 localhost:5001
| |
PyYAML 5.3.1 PyYAML 5.4
FullLoader SafeLoader
| |
v v
Payload executes Payload rejected
| Dienst | Host-Port | Container-Port | PyYAML | Zweck |
|---|---|---|---|---|
| vulnerable | 5000 | 5000 | 5.3.1 | Verwundbare Umgebung |
| patched | 5001 | 5000 | 5.4 | Behobene Umgebung |
cve-2020-14343-lab/
│
├── vulnerable/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── patched/
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
│
├── exploit/
│ └── reproduce.py
│
├── detection/
│ └── detect.py
│
├── docker-compose.yml
└── README.md
| Datei/Verzeichnis | Zweck |
|---|---|
vulnerable/app.py | Flask-Anwendung mit verwundbarem YAML-Laden |
vulnerable/Dockerfile | Erstellt das verwundbare Docker-Image |
vulnerable/requirements.txt | Legt PyYAML auf 5.3.1 fest |
patched/app.py | Flask-Anwendung mit sicherem YAML-Laden |
patched/Dockerfile | Erstellt das gepatchte Docker-Image |
patched/requirements.txt | Legt PyYAML auf 5.4 fest |
exploit/reproduce.py | Reproduziert die Schwachstelle mit einer kontrollierten Nutzlast |
detection/detect.py | Überprüft die PyYAML-Version innerhalb eines Docker-Containers |
docker-compose.yml | Erstellt und startet beide Umgebungen |
Die folgende Software ist erforderlich:
Docker Desktop muss laufen, bevor das Lab gestartet wird.
Die verwundbare Anwendung wird absichtlich nur auf dem lokalen Rechner über Docker-Portzuordnungen bereitgestellt.
Führen Sie aus dem Projektstammverzeichnis aus:
docker compose up --build -d
Führen Sie aus:
docker compose ps
Beide Dienste sollten Up anzeigen.
Öffnen Sie:
http://127.0.0.1:5000
Erwartete Antwort:
{
"message": "CVE-2020-14343 vulnerable YAML parser"
}
Öffnen Sie:
http://127.0.0.1:5001
Erwartete Antwort:
{
"message": "CVE-2020-14343 patched YAML parser"
}
docker compose up -d
docker compose down
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
Die verwundbare Anwendung stellt einen /parse-Endpunkt bereit, der YAML-Eingabe akzeptiert.
Die verwundbare Umgebung verwendet:
yaml.FullLoaderDas Reproduktionsskript befindet sich unter:
exploit/reproduce.py
Die verwundbare Anwendung ist verfügbar unter:
http://127.0.0.1:5000/parse
Führen Sie aus:
python exploit/reproduce.py
Das Skript sendet eine kontrollierte YAML-Nutzlast, die ein Python-spezifisches YAML-Tag enthält.
In der verwundbaren Umgebung wird die Nutzlast akzeptiert und die Anwendung gibt eine HTTP-200-Antwort zurück.
Der kontrollierte Testmarker:
CVE-2020-14343-TEST
wird innerhalb des Containers der verwundbaren Anwendung ausgeführt.
Die Ausführung kann überprüft werden mit:
docker logs cve-vulnerable
Die erwartete Log-Ausgabe enthält:
CVE-2020-14343-TEST
Dies demonstriert Codeausführung durch das verwundbare YAML-Ladeverhalten.
Die Reproduktionsnutzlast ist absichtlich harmlos. Sie gibt lediglich einen Testmarker aus und verändert nicht das Hostsystem, greift nicht auf Anmeldedaten zu, greift nicht auf sensible Daten zu, interagiert nicht mit externen Systemen und führt keine destruktiven Aktionen aus.
Das Erkennungsskript befindet sich unter:
detection/detect.py
Das Skript überprüft die im angegebenen Docker-Container installierte PyYAML-Version.
Die korrigierte Version ist:
5.4
Führen Sie aus:
python detection/detect.py cve-vulnerable
Erwartetes Ergebnis:
PyYAML installed version: 5.3.1
Fixed version: 5.4
STATUS: VULNERABLE
Reason: PyYAML version is older than 5.4.
Führen Sie aus:
python detection/detect.py cve-patched
Erwartetes Ergebnis:
PyYAML installed version: 5.4
Fixed version: 5.4
STATUS: PATCHED
Reason: PyYAML version is 5.4 or newer.
Docker Container
|
v
docker exec
|
v
Import PyYAML
|
v
Read yaml.__version__
|
v
Compare with 5.4
|
+----------------------+
| |
< 5.4 >= 5.4
| |
v v
VULNERABLE PATCHED
Das Skript fragt die installierte PyYAML-Version vom Zielcontainer ab.
Die verwundbare Umgebung verwendet:
PyYAML==5.3.1
Die gepatchte Umgebung verwendet:
PyYAML==5.4
Die gepatchte Anwendung verwendet außerdem:
yaml.safe_load(yaml_input)
anstelle von:
yaml.load(yaml_input, Loader=yaml.FullLoader)
yaml.safe_load(), wenn die Anwendung nur standardmäßige YAML-Datentypen benötigt.Dieselbe Exploit-Nutzlast wird gegen die gepatchte Anwendung getestet.
Die gepatchte Anwendung läuft auf:
http://127.0.0.1:5001/parse
Führen Sie aus:
python exploit/reproduce.py http://127.0.0.1:5001/parse
Beobachtetes Ergebnis in diesem Lab:
HTTP Status: 400
Server Response:
{"message":"could not determine a constructor for the tag 'tag:yaml.org,2002:python/object/new:tuple' ...","status":"error"}
Das Python-spezifische YAML-Tag wird von der gepatchten Anwendung abgelehnt.
Der kontrollierte Testmarker wird in der gepatchten Anwendung nicht ausgeführt.
| Test | Verwundbare Umgebung | Gepatchte Umgebung |
|---|---|---|
| PyYAML-Version | 5.3.1 | 5.4 |
| Erkennung | VULNERABLE | PATCHED |
| Exploit-Anfrage | HTTP 200 | HTTP 400 |
| Python-spezifisches YAML-Tag | Akzeptiert | Abgelehnt |
| Ausführung des Testmarkers | In Container-Logs beobachtet | Nicht ausgeführt |
Stellen Sie sicher, dass Docker Desktop läuft, und überprüfen Sie:
docker version
Überprüfen Sie:
docker ps -a
Entfernen Sie alte Container, falls erforderlich:
docker rm cve-vulnerable cve-patched
Dann:
docker compose up --build -d
docker compose ps
docker logs cve-vulnerable
docker logs cve-patched
docker compose up --build -d
Für einen sauberen Neubau:
docker compose build --no-cache
docker compose up -d
Dieses Projekt ist ein kontrolliertes Proof-of-Concept-Lab und stellt keine Produktionsbereitstellung dar.
Zu den Einschränkungen gehören:
Die folgenden Nachweise sollten für die Projekteinreichung erfasst werden:
STATUS: VULNERABLE.CVE-2020-14343-TEST in den Docker-Logs.STATUS: PATCHED.Screenshots können gespeichert werden in:
screenshots/
Der gesamte Reproduktionscode und die Dokumentation in diesem Repository wurden speziell für dieses Lab entwickelt.
Dieses Lab demonstriert CVE-2020-14343 von der Identifizierung bis zur Behebung.
Die verwundbare Umgebung verwendet PyYAML 5.3.1 und demonstriert kontrollierte Codeausführung durch eine präparierte YAML-Nutzlast.
Das Erkennungsskript identifiziert die verwundbare Abhängigkeitsversion.
Die behobene Umgebung aktualisiert PyYAML auf 5.4 und verwendet yaml.safe_load() zur Verarbeitung nicht vertrauenswürdigen YAMLs.
Dieselbe Reproduktionsnutzlast wird dann von der gepatchten Anwendung abgelehnt, was Vorher-Nachher-Nachweise für die Behebung liefert.
Die gesamte Umgebung kann mit Docker Compose reproduziert werden.