- Home
- Academy
- Ethical Hacking: percorso tecnico
- Sicurezza web: injection, XSS e accessi ai dati
Sicurezza web: injection, XSS e accessi ai dati
La sicurezza web richiede di capire come dati non affidabili raggiungano operazioni importanti. Una stringa può diventare codice, un identificatore può puntare all’oggetto di un altro utente, una configurazione può esporre una funzione amministrativa. In questa lezione colleghi queste famiglie di problemi a controlli e prove di correzione.
Il laboratorio usa un database in memoria con due utenti fittizi. Non cerchi vulnerabilità su siti esterni: osservi come una query parametrizzata e un vincolo di proprietà rispondano a due problemi differenti. Il risultato deve poter essere ripetuto e spiegato riga per riga.
Sicurezza web: famiglie, non una lista da memorizzare
Le raccolte OWASP aiutano a orientare la conoscenza, ma non sostituiscono un piano di verifica. Un elenco di categorie non racconta ogni funzione dell’applicazione, le sue identità o le condizioni del tuo ambiente. Per organizzare le prove puoi partire dalla Web Security Testing Guide.
Distingui una categoria da una vulnerabilità concreta. «Injection» indica una famiglia di problemi; il tuo risultato deve nominare il dato controllabile, l’interprete che lo riceve e l’operazione resa possibile. «Controllo di accesso debole» deve diventare una relazione precisa tra utente, oggetto e azione.
Evita di verificare soltanto ciò che uno scanner riconosce facilmente. Le regole del business possono introdurre abusi che non dipendono da una stringa speciale: approvare due volte una richiesta, modificare un importo già autorizzato o saltare un passaggio richiesto. Devi conoscere il processo per capire quando il comportamento è scorretto.
SQL injection: separare dati e struttura
Una query costruita unendo direttamente il testo ricevuto dal client può confondere dati e istruzioni. La difesa principale dell’esempio è usare parametri, così che il valore non venga interpretato come struttura della query. La guida OWASP alla prevenzione della SQL injection approfondisce questo principio.
La parametrizzazione non sostituisce però ogni controllo. Se un utente può scegliere liberamente il nome di una colonna o la direzione di un ordinamento, il problema coinvolge elementi strutturali per i quali servono scelte ammesse e costruzione controllata. E se può leggere l’ordine altrui con un numero valido, manca un’autorizzazione anche quando la query è perfettamente parametrizzata.
Anche i privilegi del database contano. Un account applicativo con poteri inutilmente ampi può aumentare l’impatto di un errore. Ridurre quei poteri non giustifica una query insicura, ma può contribuire a limitare le conseguenze di un problema non ancora individuato.
XSS: il contesto della risposta
Cross-site scripting riguarda dati che finiscono in un contesto interpretato dal browser in modo non previsto. I contesti non sono tutti uguali: testo HTML, attributi, script e indirizzi richiedono trattamenti differenti. Non esiste una sostituzione di caratteri valida per ogni destinazione possibile.
Quando il contenuto deve essere testo, mantienilo testo attraverso le funzioni adatte del framework e del contesto. Quando l’applicazione permette HTML, devi definire quali elementi siano ammessi e usare una sanitizzazione adatta. Una policy del browser può offrire un ulteriore livello di protezione, ma non sostituisce automaticamente la corretta gestione dell’output.
Nel laboratorio puoi usare un valore innocuo come <b>messaggio</b> per distinguere visualizzazione letterale e interpretazione HTML. Questo confronto non dimostra da solo esecuzione di script: mostra un passaggio di contesto che dovrai analizzare. La conclusione deve rimanere proporzionata alla prova eseguita.
Accesso agli oggetti e logica applicativa
Un identificatore imprevedibile non sostituisce un controllo di autorizzazione. L’utente deve essere autorizzato a leggere o modificare l’oggetto richiesto anche se ne conosce il riferimento. Altrimenti la sicurezza dipende soltanto dal mantenere nascosti gli identificatori.
Controlla anche attributi e transizioni. Un utente potrebbe leggere correttamente il proprio profilo ma poter aggiungere un campo amministrativo in una richiesta di modifica. Una richiesta formalmente valida può proporre un passaggio non consentito dal processo. L’applicazione deve validare ciò che l’identità può effettivamente cambiare.
Per le funzioni che recuperano risorse remote, studia il confine tra dato fornito dall’utente e richieste eseguite dal server. Non trasformare un indirizzo controllabile in una capacità generale di contattare reti e servizi. La valutazione deve considerare destinazioni ammesse, risoluzione, reindirizzamenti e controlli applicati alla connessione effettiva.
Laboratorio passo per passo
Esegui questo programma soltanto come esercizio locale. Crea un archivio in memoria, due ordini fittizi e una funzione che considera insieme identificatore dell’ordine e proprietario verificato. Il parametro utente_sessione rappresenta un’identità già autenticata dal server; in un’applicazione reale non va preso liberamente dal corpo inviato dal client.
import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE ordini (id INTEGER, proprietario TEXT, nota TEXT)")
conn.executemany(
"INSERT INTO ordini VALUES (?, ?, ?)",
[(1, "alice", "Ordine didattico A"), (2, "bruno", "Ordine didattico B")],
)
def leggi_ordine(id_ordine, utente_sessione):
return conn.execute(
"SELECT nota FROM ordini WHERE id = ? AND proprietario = ?",
(id_ordine, utente_sessione),
).fetchone()
assert leggi_ordine(1, "alice") == ("Ordine didattico A",)
assert leggi_ordine(2, "alice") is None
assert leggi_ordine("1 OR 1=1", "alice") is None
print("Tre controlli didattici superati")
La documentazione di sqlite3 in Python descrive il passaggio dei parametri. Nell’esercizio il terzo controllo verifica che una stringa non venga trasformata nella struttura SQL desiderata dal suo autore. Il secondo verifica invece la separazione tra proprietari: sono due proprietà diverse.
Ora rimuovi, soltanto nella copia didattica, il vincolo sul proprietario e osserva quale controllo fallisca. Non serve introdurre una SQL injection per creare un accesso scorretto: il numero dell’ordine può essere valido e appartenere a un altro utente. Ripristina il vincolo e conserva il confronto.
Aggiungi poi un quarto caso di test per un ordine inesistente. Descrivi come l’applicazione dovrebbe comunicare il risultato senza rivelare dati non necessari. Non estendere il programma fino a farlo diventare un servizio pubblico: mancano molte parti di autenticazione, gestione degli errori e ciclo di vita che qui non stiamo implementando.
Dalla prova alla correzione
Per ogni problema descrivi il percorso completo: origine del dato, trattamento, controllo mancante, effetto e prova. Una correzione adatta deve intervenire sul confine che hai identificato. Cambiare il testo dell’errore può ridurre un’informazione esposta senza correggere l’operazione sottostante.
Nel retest mantieni sia il caso che deve fallire sia quello che deve riuscire. Un controllo che rifiuta tutte le richieste può far sparire il sintomo ma interrompere la funzione legittima. La sicurezza del comportamento comprende anche la possibilità di usare correttamente il servizio.
Conserva le verifiche come test di regressione quando il contesto lo permette. Un controllo manuale documentato può essere utile; un test ripetibile vicino al codice rende più facile riconoscere il ritorno dello stesso difetto dopo una modifica successiva.
Checklist ed errori da evitare
- Sai indicare il punto in cui un dato diventa istruzione o operazione.
- Parametrizzazione e autorizzazione sono trattate separatamente.
- Il contesto di output del browser è stato identificato.
- I privilegi dell’applicazione e del database sono motivati.
- Esistono casi consentiti e casi rifiutati da confrontare.
- La conclusione non supera ciò che l’esercizio ha dimostrato.
Evita la frase «input ripulito» senza spiegare destinazione e regola. Evita anche di considerare un firewall applicativo come correzione universale del codice: può contribuire a una mitigazione, ma la sua copertura va verificata rispetto al problema specifico.
Consigli pratici
Scegli una funzione e scrivi una prova per ciascun confine: input, identità, oggetto e risultato. Questo aiuta a rendere concreta una code review di sicurezza, evitando un rapporto fatto soltanto di categorie astratte.
Domande frequenti
Una query parametrizzata elimina ogni accesso indebito?
No. Protegge la separazione tra valori e struttura della query, ma devi comunque limitare gli oggetti e le operazioni disponibili all’identità corrente.
Un testo interpretato come HTML dimostra sempre XSS?
Non necessariamente. Devi verificare il contesto e il comportamento ottenibile. L’interpretazione HTML è un’osservazione da approfondire, non una prova automatica di qualsiasi esecuzione.
Che cosa consegno?
Il programma con quattro controlli, il confronto del vincolo sul proprietario e una scheda che distingua injection, autorizzazione e contesto di output.
Riferimento di studio: Ric Messier, CEH v12 Certified Ethical Hacker Study Guide with 750 Practice Test Questions, Wiley/Sybex, 2023, capitolo 12.
Continua il percorso
Riparti dal capitolo 13: HTTP e sessioni: le basi della sicurezza web. Prosegui con il capitolo 15: Wi-Fi e dispositivi mobili: verifica delle difese. L’indice dei venti capitoli è nella pagina della serie.






