TL;DR
91 Prozent aller Unternehmen verzeichneten 2024 mindestens einen API-Sicherheitsvorfall - die OWASP API Security Top 10 (2023) dokumentiert die Ursachen. Die gefährlichste Schwachstelle ist Broken Object Level Authorization (BOLA): APIs prüfen nicht, ob der authentifizierte Nutzer auf das angeforderte Datenobjekt zugreifen darf, sodass Angreifer mit Burp Suite fremde Bestellungen oder Profile abrufen. Weitere kritische Angriffsvektoren sind JWT Algorithm Confusion, Mass Assignment sowie fehlende Rate Limits auf Login-Endpunkten. Der Artikel zeigt anhand von Python/FastAPI-Codebeispielen, wie Sie Berechtigungsprüfungen, Token-Validierung und API-Gateway-Härtung korrekt implementieren.
Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 52).
Inhaltsverzeichnis (5 Abschnitte)
APIs sind das Nervensystem moderner Applikationen - und seit Jahren das bevorzugte Angriffsziel. 91% aller Unternehmen hatten 2024 mindestens einen API-Sicherheitsvorfall (Salt Security State of API Security, 2024). Die OWASP API Security Top 10 listet die häufigsten Schwachstellen - viele davon sind verblüffend einfach und in erschreckend vielen Produktions-APIs zu finden.
OWASP API Security Top 10 (2023)
OWASP API Security Top 10:
API1: Broken Object Level Authorization (BOLA):
→ Häufigste und gefährlichste API-Schwachstelle
→ API verwendet User-kontrollierte IDs ohne Berechtigungsprüfung
Vulnerable Code (Python/FastAPI):
@app.get("/orders/{order_id}")
def get_order(order_id: int, user: User = Depends(get_current_user)):
order = db.get_order(order_id)
return order # ← FEHLER: prüft nicht ob user.id == order.user_id!
Angriff: GET /api/orders/1337 → sieht Bestellung eines anderen Users!
Tool: Burp Suite → IDs systematisch durchprobieren (IDOR-Test)
Fix:
@app.get("/orders/{order_id}")
def get_order(order_id: int, user: User = Depends(get_current_user)):
order = db.get_order(order_id)
if order.user_id != user.id: # ← Eigentümerprüfung!
raise HTTPException(status_code=403)
return order
API2: Broken Authentication:
→ Schwache oder fehlende Authentifizierung
→ Tokens im URL (statt Header), keine Token-Rotation, keine Rate Limits
Beispiele:
GET /api/reset?token=abc123 # Token im URL = Logs leakage!
JWT mit algorithm=none # Keine Signatur-Prüfung!
Kein Rate Limiting auf Login-Endpoint → Brute Force möglich
API3: Broken Object Property Level Authorization:
→ Mass Assignment: API akzeptiert mehr Felder als erlaubt
→ Excessive Data Exposure: API gibt mehr zurück als nötig
Mass Assignment Beispiel:
PATCH /api/user/profile
{"name": "Max", "role": "admin"} # role sollte User nicht setzen können!
Excessive Data Exposure:
GET /api/user/123 gibt zurück:
{"id": 123, "name": "Max", "email": "...",
"password_hash": "...", "ssn": "...", "is_admin": false}
→ Hash und SSN sollten nie in API-Response!
API4: Unrestricted Resource Consumption:
→ Kein Rate Limiting → DoS, Account Enumeration, Brute Force
→ Keine Größenbegrenzung für Uploads → Storage-Exhaustion
→ Keine Timeout-Limits → Slow HTTP Attacks
API5: Broken Function Level Authorization:
→ Administrative Endpoints ohne Auth erreichbar
→ Unterschied User-/Admin-API nicht durchgesetzt
Beispiel:
POST /api/admin/users → sollte Admin-Auth erfordern
Aber: normale JWT-Token reichen aus!
API6: Unrestricted Access to Sensitive Business Flows:
→ Keine Begrenzung für Business-Flows (Bestellungen, Vouchers)
→ Promo-Code 10000x einlösen weil kein Rate Limit
API7: Server Side Request Forgery (SSRF):
→ API macht HTTP-Anfragen an User-kontrollierte URLs
→ Angreifer lässt Server interne Ressourcen fetchen
API8: Security Misconfiguration:
→ CORS zu permissiv: Access-Control-Allow-Origin: *
→ Debug-Endpoints in Produktion aktiv
→ Verbose Error Messages → Stack Traces leaken
API9: Improper Inventory Management:
→ Vergessene API-Versionen (v1 ist unsicher, v2 sicher → v1 noch aktiv!)
→ Shadow APIs: undokumentierte Endpunkte
→ Test/Beta-APIs in Produktion
API10: Unsafe Consumption of APIs:
→ Blindes Vertrauen in Drittanbieter-APIs
→ SQL Injection durch Daten aus externen APIs
Authentifizierung und Autorisierung sicher implementieren
JWT Best Practices:
Unsichere JWT-Implementierung:
1. Algorithm Confusion Attack:
Angreifer ändert Header: {"alg": "none", "typ": "JWT"}
→ Sign mit leerem Secret → Server akzeptiert!
Fix (Python/PyJWT):
jwt.decode(token, public_key,
algorithms=["RS256"], # Explizit! Niemals algorithms=None!
options={"verify_exp": True})
2. Schwache Secrets:
# SCHLECHT: vorhersehbares Secret
SECRET_KEY = "mysecret" oder "secret123"
# GUT: kryptographisch zufällig, mind. 256 Bit
SECRET_KEY = secrets.token_hex(32) # 256-Bit-Zufallsstring
3. Fehlende Claims-Validierung:
# SCHLECHT: nur Signatur prüfen
payload = jwt.decode(token, secret, algorithms=["HS256"])
# GUT: alle kritischen Claims prüfen
payload = jwt.decode(
token, secret,
algorithms=["HS256"],
options={
"require": ["exp", "iat", "sub", "iss"],
"verify_exp": True,
"verify_iat": True,
},
issuer="https://auth.example.com"
)
4. Token im localStorage (XSS-Risiko):
# SCHLECHT:
localStorage.setItem('token', jwt_token) # XSS → Token gestohlen!
# GUT: HttpOnly Cookie
response.set_cookie(
"access_token", jwt_token,
httponly=True, # JavaScript kann nicht lesen
secure=True, # Nur HTTPS
samesite="Strict", # CSRF-Schutz
max_age=3600
)
OAuth2 / OpenID Connect Best Practices:
→ PKCE (Proof Key for Code Exchange) für alle Public Clients
→ State-Parameter gegen CSRF bei Authorization Code Flow
→ Token-Rotation: Refresh Tokens nach Nutzung invalidieren
→ Short-lived Access Tokens: max. 15 Minuten
→ Token-Revocation-Endpoint implementieren
Rate Limiting und Input Validation
Rate Limiting implementieren:
nginx rate limiting:
# Globale Rate-Limit-Zone
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# Auf API-Endpunkten anwenden:
location /api/login {
limit_req zone=api burst=5 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
location /api/ {
limit_req zone=api burst=20;
proxy_pass http://backend;
}
Python (FastAPI mit slowapi):
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.post("/api/login")
@limiter.limit("5/minute") # 5 Login-Versuche pro Minute
async def login(request: Request, credentials: LoginCredentials):
...
@app.get("/api/search")
@limiter.limit("30/minute") # Mehr für Suchanfragen
async def search(request: Request, q: str):
...
Input Validation - Schemas erzwingen:
Python (Pydantic):
from pydantic import BaseModel, EmailStr, field_validator
from typing import Optional
class UpdateUserRequest(BaseModel):
name: str
email: EmailStr
# Explizit: kein 'role' Feld! → Mass Assignment verhindert
# Pydantic ignoriert unbekannte Felder automatisch wenn model_config
@field_validator('name')
@classmethod
def name_must_be_valid(cls, v: str) -> str:
if len(v) < 2 or len(v) > 100:
raise ValueError('Name muss 2-100 Zeichen haben')
# Keine HTML/Script-Tags erlauben
if '<' in v or '>' in v:
raise ValueError('Ungültige Zeichen im Namen')
return v.strip()
TypeScript (Zod):
import { z } from 'zod';
const UpdateUserSchema = z.object({
name: z.string().min(2).max(100).regex(/^[a-zA-ZäöüÄÖÜß\s-]+$/),
email: z.string().email(),
// Keine 'role', 'isAdmin' etc. → Mass Assignment verhindert!
});
// In Route Handler:
const data = UpdateUserSchema.parse(req.body); // wirft bei ungültigen Daten
API Gateway und Security Headers
API Gateway als Sicherheitsschicht:
Kong Gateway (Open Source):
# Rate Limiting Plugin:
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=rate-limiting" \
--data "config.minute=60" \
--data "config.policy=local"
# Key Authentication:
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=key-auth"
# JWT Plugin:
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=jwt" \
--data "config.claims_to_verify=exp,nbf"
# CORS Plugin:
curl -X POST http://localhost:8001/services/my-api/plugins \
--data "name=cors" \
--data "config.origins=https://app.example.com" \
--data "config.methods=GET,POST,PUT,DELETE" \
--data "config.credentials=true"
HTTP Security Headers für APIs:
Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Cache-Control: no-store
Pragma: no-cache
CORS korrekt konfigurieren:
# SCHLECHT (zu permissiv):
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true # Diese Kombination VERBOTEN!
# GUT (spezifische Origins):
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true # nur wenn origin spezifisch!
API Versioning und Deprecation:
→ Niemals alte API-Versionen ohne Auth-Check erreichbar lassen
→ Deprecation-Header bei alten Versionen:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: </api/v2/endpoint>; rel="successor-version"
→ Monitoring: Alert wenn v1-Endpunkte noch aufgerufen werden
API-Penetrationstest Checkliste
API-Sicherheits-Testplan:
Reconnaissance:
□ API-Dokumentation: Swagger/OpenAPI spec verfügbar?
□ API-Versionen: v1, v2, beta, dev Endpunkte?
□ JavaScript-Bundle analysieren: geleakte API-Endpunkte?
□ HTTP-Archive (HAR) aus Browser-DevTools exportieren
Authentifizierung:
□ Endpoints ohne Auth erreichbar? (401 auf alle prüfen)
□ JWT-Algorithm-Confusion testen
□ Token-Gültigkeitsdauer: zu lang?
□ Refresh-Token-Rotation korrekt implementiert?
□ Brute Force auf Login: Rate Limiting aktiv?
Authorization (BOLA/IDOR):
□ Für jede ressourcenbezogene API: ID austauschen
GET /api/orders/100 → GET /api/orders/101 (andere User?)
□ Horizontale: User A sieht Daten User B
□ Vertikale: User-Token für Admin-Endpoint
Mass Assignment:
□ Zusätzliche Felder in PATCH/PUT/POST mitsenden
{"name": "Max", "role": "admin", "is_verified": true}
□ Werden unerlaubte Felder akzeptiert?
Rate Limiting:
□ Login: 100+ Requests → Account-Lockout?
□ Password Reset: Enumeration möglich?
□ OTP-Eingabe: Brute-Force-Schutz?
Tools:
Burp Suite: Intercept, Repeater, Intruder für API-Tests
OWASP ZAP: Automatischer API-Scan (OpenAPI-Import)
ffuf: Fuzzing für versteckte Endpunkte
jwt_tool: JWT-Analyse und -Manipulation
httpie: Komfortables API-Testing auf CLI
API-Sicherheit ist keine einmalige Aufgabe, sondern ein kontinuierlicher Prozess. AWARE7 führt spezialisierte API-Penetrationstests durch - von der manuellen BOLA-Suche bis zum automatisierten Continuous-Testing in CI/CD.
Nächster Schritt
Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel — unverbindlich und kostenlos.
Kostenlos · 30 Minuten · Unverbindlich
