A2C / ARCADE
4 microgiochi originali
ABLE2CODE / INSERT CURIOSITY

Byte Patrol

Punti 0 · Vite 3
Il gioco richiede un browser con supporto Canvas 2D. I comandi e il punteggio sono riportati anche fuori dal canvas.
Muovi e spara

Frecce o A/D per muoverti. Spazio per sparare. P mette in pausa, Esc chiude. Puoi usare anche i pulsanti sotto il gioco.

Postazione per test web con modulo di login sul portatile e strumenti di analisi sul monitor.
hacking

IDOR: cambia un numero, leggi il documento di un altro

Due account e due documenti in un laboratorio Docker: riproduci una IDOR, aggiungi il controllo del proprietario e verifica gli accessi prima e dopo.

In questo articolo

In breve

  • Un login valido identifica l'utente; l'autorizzazione decide se può accedere a quello specifico documento.
  • Nel laboratorio Alice e Bob hanno un documento ciascuno. La modalità vulnerabile permette di leggere quello altrui cambiando l'ID nella richiesta.
  • La correzione controlla il proprietario sul server prima di restituire i dati. Gli identificatori difficili da indovinare sono una difesa aggiuntiva.
  • Il retest verifica quattro combinazioni: due letture legittime devono continuare a riuscire, due letture incrociate devono fallire senza rivelare il contenuto.

Il documento sbagliato, con il login giusto

Alice entra nel suo archivio e apre il documento 1. Poi cambia quel numero in 2. Il server le restituisce la bozza di Bob. Password corretta, sessione corretta, risultato sbagliato.

Lo riproduciamo esclusivamente nella toy app locale del laboratorio Nmap: due utenti fittizi, due documenti sintetici, rete Docker interna senza porte pubblicate. Dopo aver visto quali servizi rispondono, adesso mettiamo alla prova la decisione che il server prende dentro una richiesta.

Una IDOR, Insecure Direct Object Reference, nasce quando il riferimento a un oggetto controllato dal client permette di raggiungerlo senza un controllo di accesso adeguato. L'identificatore può essere nell'URL o in altri parametri. Nel nostro caso il difetto consente un accesso orizzontale: un utente legge i dati di un altro dello stesso livello. Definizione ed esempi PortSwigger.

Dal vecchio filtro JavaScript alle API

In Hacker Journal n. 267, dicembre 2022, pp. 28–31, Mutillidae mostrava il limite dei controlli eseguiti soltanto nel browser. Quell'esercitazione riguardava SQL injection; qui riutilizziamo il principio del confine di fiducia con un esperimento diverso e originale.

Nascondere un pulsante o far scegliere un documento da un menu non impedisce al client di inviare un altro ID. Le interfacce cambiano, il server continua a dover decidere. Nelle API questo problema rientra nella Broken Object Level Authorization, descritta da OWASP: ogni funzione che usa un riferimento ricevuto dal client deve verificare l'operazione richiesta sull'oggetto. OWASP API1:2023.

Prepara due identità separate

Se hai concluso il primo esercizio, usa la stessa cartella. Altrimenti scarica i sorgenti del laboratorio, estraili e apri pentest-percorso in una shell Linux, macOS o WSL con Docker e Compose disponibili.

mkdir -p evidence
docker compose build strumenti
docker compose pull archivio
lab() { docker compose run --rm --no-deps --user "$(id -u):$(id -g)" strumenti "$@"; }
AUTHZ_MODE=vulnerable docker compose up -d --wait --force-recreate archivio

L'impostazione vulnerabile è esplicita: senza di essa l'app applica già il controllo del proprietario. Il container strumenti raggiunge archivio sulla rete del progetto; non serve installare curl sull'host. La configurazione usa la rete interna di Compose.

Comincia senza autenticazione:

lab curl -sS -w 'HTTP %{http_code}\n' \
  http://archivio:8080/api/documents/1

Nel test del 31 ottobre 2026 la risposta è stata:

{"error": "authentication_required"}
HTTP 401

La barriera del login esiste. Ora crea due sessioni e conservale in file distinti:

lab curl -sS -c /evidence/alice.cookie \
  -H 'Content-Type: application/json' \
  -d '{"username":"alice","password":"alice-lab"}' \
  http://archivio:8080/login

lab curl -sS -c /evidence/bob.cookie \
  -H 'Content-Type: application/json' \
  -d '{"username":"bob","password":"bob-lab"}' \
  http://archivio:8080/login

Le risposte identificano rispettivamente alice e bob. -c scrive i cookie; nelle richieste successive -b li rilegge. I token sono casuali: non sostituire l'username dentro un cookie e non usare un unico file per entrambi gli account.

Quattro richieste, una matrice di permessi

La policy dell'esercizio è semplice: Alice può leggere il documento 1; Bob il documento 2. Nessuno dei due può leggere quello dell'altro. Crea questa funzione per eseguire sempre la stessa verifica:

accessi() {
  lab curl -sS -b /evidence/alice.cookie -w 'HTTP %{http_code}\n' \
    http://archivio:8080/api/documents/1
  lab curl -sS -b /evidence/bob.cookie -w 'HTTP %{http_code}\n' \
    http://archivio:8080/api/documents/2
  lab curl -sS -b /evidence/alice.cookie -w 'HTTP %{http_code}\n' \
    http://archivio:8080/api/documents/2
  lab curl -sS -b /evidence/bob.cookie -w 'HTTP %{http_code}\n' \
    http://archivio:8080/api/documents/1
}
accessi

Le prime due richieste stabiliscono il comportamento legittimo. La terza cambia soltanto l'ID usato da Alice. Output realmente osservato:

{"id": 2, "owner": "bob", "text": "Budget laboratorio: bozza di Bob."}
HTTP 200

Anche Bob riesce a leggere il documento 1. Non abbiamo indovinato password, sottratto sessioni o iniettato SQL. È mancata una domanda nel server: questo oggetto appartiene all'utente autenticato?

Sessione Documento Dovrebbe riuscire? Modalità vulnerabile
Alice 1, di Alice Sì 200, documento 1
Bob 2, di Bob Sì 200, documento 2
Alice 2, di Bob No 200, documento 2
Bob 1, di Alice No 200, documento 1

Questa piccola matrice evita un falso positivo comune: chiamare vulnerabilità la lettura di un contenuto che la policy considera pubblico. Qui i documenti e la regola di proprietà sono definiti nel codice, quindi il confronto è verificabile.

La riga che deve stare sul server

Apri app.py. L'app ricava l'utente dalla sessione, cerca il documento e, in modalità corretta, esegue il controllo prima di serializzarlo:

if doc is None or (self.server.mode == "strict" and doc["owner"] != user):
    self.reply(404, {"error": "not_found"})
    return
self.reply(200, doc)

Attiva quella modalità:

AUTHZ_MODE=strict docker compose up -d --wait --force-recreate archivio

Ripeti entrambi i comandi di login, quindi esegui nuovamente accessi. La ricreazione svuota le sessioni in memoria: se riutilizzassi cookie vecchi, un 401 non dimostrerebbe la correzione dell'IDOR.

Il retest reale ha prodotto 200 per Alice/1 e Bob/2, 404 per Alice/2 e Bob/1. Le richieste incrociate ora restituiscono soltanto:

{"error": "not_found"}
HTTP 404

La stessa risposta viene usata per un documento inesistente. La sicurezza dipende dal mancato invio dei dati; scrivere “accesso negato” nell'interfaccia lasciando il JSON privato nella risposta non sarebbe una correzione.

In un'app reale la regola potrebbe includere organizzazione, ruolo, condivisioni e operazione. Conviene cercare gli oggetti dentro l'insieme che l'utente è autorizzato a usare e applicare la policy a ogni accesso. Un UUID rende meno prevedibile il riferimento, ma non sostituisce questi controlli. Indicazioni OWASP per prevenire IDOR.

Il test deve sopravvivere alla demo

Il pacchetto contiene test HTTP eseguibili con Python 3 sull'host:

python3 -B -m unittest -v test_app.py

Aprono listener temporanei solo su 127.0.0.1 e verificano accessi propri e incrociati, login, logout, sessione falsa e impostazione sicura predefinita. I quattro test sono stati eseguiti con successo. Non dimostrano la sicurezza generale di questa toy app: password nel codice, HTTP e dati in memoria sono semplificazioni del laboratorio.

Se trasformi il caso in un report, allega identità usata, documento richiesto, policy attesa, risposta osservata e retest. Mostra il minimo contenuto necessario: qui sono bozze inventate. La stessa disciplina su un test autorizzato evita di raccogliere dati che non servono alla prova.

Il limite dell'esperimento è la sola lettura di questi due oggetti. Un servizio più ampio richiederebbe casi separati per aggiornamento, cancellazione, esportazione e accesso tra organizzazioni. Anche una richiesta che contiene una lista di ID deve applicare i controlli a ogni elemento: il successo della lettura singola non dimostra il comportamento dell'intero flusso.

Ripulisci e porta via la regola

docker compose --profile strumenti down --remove-orphans
rm -f evidence/alice.cookie evidence/bob.cookie

Container e rete vengono rimossi; puoi conservare i report. La lezione difensiva è concreta: ricava l'identità da una sessione verificata, applica i permessi all'oggetto e all'operazione, registra gli accessi negati senza salvare token o contenuti privati. Poi ripeti sia i casi negati sia quelli consentiti: una correzione che blocca tutti non soddisfa la policy.

Domande frequenti

Che differenza c'è tra IDOR e furto di un cookie?

Nel furto di sessione qualcuno usa il token di un altro utente. Qui Alice conserva la propria sessione valida e cambia soltanto il documento richiesto. Il difetto è il controllo di autorizzazione mancante sul server.

Un UUID risolve una IDOR?

Rende più difficile indovinare un identificatore, ma non decide chi può usare l'oggetto. Se un ID arriva da un link, da un log o da un'altra risposta, il server deve comunque verificare i permessi dell'utente.

Perché il laboratorio restituisce 404 anziché 403?

È una scelta del laboratorio per usare la stessa risposta quando il documento non esiste e quando non appartiene all'utente. La correzione vera è il controllo prima di inviare i dati: cambiare soltanto il codice HTTP non basta.

Perché devo rifare il login dopo aver applicato la correzione?

L'app conserva le sessioni in memoria e la ricreazione del container le elimina. Un 401 ottenuto con un vecchio cookie dimostra soltanto che la sessione non è più valida. Il retest richiede nuovi cookie di Alice e Bob.

Questo controllo vale anche per scrittura e cancellazione?

Sì, ogni operazione deve applicare la propria policy sull'oggetto. Il laboratorio implementa solo letture: il risultato non dimostra che endpoint di modifica, cancellazione, esportazione o richieste batch siano protetti.

Fonti e approfondimenti