Funzioni moderne e scelte efficaci
Padre: “Il mulino ha chiuso, non c’è più lavoro, siamo poveri.”
Figlioli: “Ohhhhh.”
Padre: “Mi sa che non ho altra scelta: devo vendervi tutti per esperimenti scientifici.”
— Monty Python, Il senso della vita
La sicurezza web è un aspetto cruciale nello sviluppo di applicazioni moderne e Django offre un insieme robusto di funzionalità per proteggere le nostre applicazioni. Questo articolo esplora le varie misure di sicurezza integrate in Django, dalla protezione CSRF alla gestione delle sessioni, dalla prevenzione di iniezioni SQL alla sicurezza a livello di autenticazione. Django non solo rende più semplice implementare queste misure di sicurezza, ma promuove anche un approccio alla sicurezza web che è al contempo completo e gestibile.
SQL injection
La SQL injection è un attacco che consente l’esecuzione di codice SQL arbitrario su un database, potenzialmente causando cancellazioni o perdite di dati. I QuerySet
di Django sono protetti da questo tipo di attacchi poiché le loro query sono costruite tramite la parametrizzazione dei dati passati al database. Questo significa che il codice SQL e i parametri delle query sono definiti separatamente e gli eventuali parametri forniti dall’utente vengono sanitizzati dal driver del database.
Sanitizzazione
La sanitizzazione dei dati è un processo critico nella programmazione e sicurezza informatica e consiste nella pulizia e validazione dei dati in entrata, prima del loro utilizzo o della loro memorizzazione. Questo processo, che è fondamentale per prevenire attacchi come SQL Injection e Cross-Site Scripting (XSS), si realizza attraverso la verifica che i dati rispettino formati e tipologie attesi, la rimozione o sostituzione di caratteri pericolosi e l’applicazione di tecniche quali l’escaping dei caratteri speciali in contesti come le query SQL. L’obiettivo è garantire che i dati trattati siano sicuri e non compromettano l’integrità o la sicurezza del sistema o dell’applicazione.
In ogni caso, siccome Django consente agli sviluppatori di scrivere query SQL dirette o eseguire SQL personalizzato tramite il metodo extra
dei QuerySet
o la classe RawSQL
, dobbiamo usare queste ultime due funzionalità con estrema parsimonia e in ogni caso dovremo pensare noi a sanitizzare correttamente qualsiasi parametro controllabile dall’utente.
Little Bobby Tables
Se non avete mai letto questa strip di Xkcd fatelo ora. È diventata praticamente un meme tra i programmatori (come tante altre vignette di Xkcd). Il fumetto mostra una conversazione telefonica tra una scuola e la madre di un alunno, nella quale la scuola riferisce di avere problemi informatici. La madre scopre che il problema è stato causato dal nome, a dir poco inusuale, che il figlio ha inserito nel sistema informatico della scuola:
Robert’); DROP TABLE Students;--
La storia rivela che, a causa di questo nome così strano, sono stati persi i dati degli studenti di quell’anno. La battuta finale della madre è un consiglio ironico sulla necessità di sanitizzare (cioè, verificare e pulire dai caratteri speciali) gli input nel database per evitare l’esecuzione di codici dannosi.
Cross Site Request Forgery (CSRF)
Gli attacchi CSRF permettono a un utente malintenzionato di eseguire azioni utilizzando le credenziali di un altro utente senza la conoscenza o il consenso di quest’ultimo.
Django è dotato di una protezione integrata contro la maggior parte degli attacchi CSRF, a patto che questa sia stata abilitata e utilizzata correttamente. Tuttavia, come ogni tecnica di mitigazione, presenta delle limitazioni. Per esempio, possiamo disabilitare il modulo CSRF globalmente o per specifiche viste (con il decoratore csrf_exempt
), ma questo dovrebbe essere fatto solo da chi ha piena consapevolezza delle implicazioni di questa azione. Inoltre, possono sorgere limitazioni se il nostro sito utilizza sottodomini che non sono sotto il nostro controllo.
Leggi anche: 9 libri per realizzare la cybersicurezza che ti serve
La protezione CSRF in Django funziona verificando la presenza di un segreto in ogni richiesta POST. Questo impedisce a un utente malintenzionato di ripetere una richiesta POST di un modulo sul tuo sito web e far sì che un altro utente loggato invii quel modulo senza saperlo. L’utente malintenzionato dovrebbe conoscere il segreto, che è specifico per ciascun utente (e conservato criptato all’interno di un cookie chiamato csrftoken
).
Quando viene utilizzato il protocollo HTTPS, il middleware CsrfViewMiddleware
controlla che l’header HTTP Referer
sia impostato su un URL della stessa origine (inclusi sottodominio e porta).
Poiché l’HTTPS offre una sicurezza aggiuntiva, è fondamentale garantire che le connessioni utilizzino HTTPS laddove disponibile, inoltrando le richieste di connessione non sicure e, ancora meglio, utilizzando HSTS per i browser che lo supportano.
HSTS
HSTS (HTTP Strict Transport Security) è un meccanismo di sicurezza che protegge i siti web contro gli attacchi man-in-the-middle, in particolare quelli che cercano di intercettare e modificare il traffico tra l’utente e il sito web. Quando un sito web usa HSTS, informa il browser che deve connettersi al sito utilizzando esclusivamente una connessione sicura HTTPS. Una volta ricevuto l’header HSTS da un sito web, il browser ricorderà di utilizzare solo connessioni sicure per quel sito per un determinato periodo di tempo, anche se l’utente cerca di accedere al sito tramite HTTP o fa clic su un link non sicuro.
Cross Site Scripting (XSS)
Gli attacchi XSS permettono di iniettare script lato client nelle pagine visualizzate dai browser di altri utenti. Questo avviene tipicamente memorizzando gli script maligni nel database, dove possono essere poi recuperati e visualizzati da altri utenti, o inducendo gli utenti a fare clic su un link che esegue via Javascript lo script dell’attaccante nel loro browser. Tuttavia, gli attacchi XSS possono originare da qualsiasi fonte di dati non affidabile, come i cookie o i servizi web, quando i dati non sono adeguatamente sanitizzati prima di essere inclusi in una pagina.
L’utilizzo dei template di Django ci protegge dalla maggior parte degli attacchi XSS. Tuttavia, è importante per noi comprendere le protezioni che offre e i suoi limiti. Questo implica una consapevolezza delle misure di sicurezza incorporate nei template e di come queste possano essere utilizzate in modo efficace per contrastare possibili vulnerabilità.
I template di Django escludono automaticamente alcuni caratteri specifici che sono particolarmente pericolosi per l’HTML. Sebbene ciò protegga gli utenti dalla maggior parte degli input maligni, non è un sistema completamente infallibile, come in situazioni dove attributi HTML vengono manipolati in modo improprio.
Dobbiamo inoltre fare molta attenzione quando utilizziamo is_safe
con tag personalizzati dei template o i tag template safe
, mark_safe
, o quando disattiviamo l’autoescape
(l’escaping automatico effettuato da Django). Inoltre, se usiamo il sistema di template per produrre qualcosa diverso dall’HTML, potrebbero esserci caratteri completamente differenti che richiedono l’escaping. Dovremmo prestare molta attenzione anche quando memorizziamo nel database codice HTML, specialmente se quest’ultimo viene in seguito recuperato e visualizzato.
Protezione da clickjacking
Il clickjacking (rapimento o dirottamento del clic) è un tipo di attacco informatico dove un sito malevolo ingloba un altro sito o una parte di esso all’interno di un frame o di un elemento simile. Questo consente all’attaccante di ingannare gli utenti, facendo credere loro di fare clic su elementi del sito originale, mentre in realtà stanno interagendo con il sito malevolo. Questo può portare a varie conseguenze, come la divulgazione involontaria di dati sensibili o l’effettuazione di azioni non intenzionali. L’attacco sfrutta la fiducia dell’utente verso il sito visibile, mascherando il reale sito in azione dietro l’interfaccia.
La protezione da clickjacking in Django si attua tramite il middleware X-Frame-Options, che impedisce il rendering di un sito all’interno di un frame in un browser compatibile. La protezione può però essere disabilitata per singole viste o configurata per inviare un valore specifico dell’header. Anche in questo caso dobbiamo essere assolutamente certi di sapere quello che stiamo facendo se disabilitiamo questo middleware, anche solo per una piccola sezione del nostro sito.
Best practice
Fare un elenco esaustivo di tutte le best practice riguardanti la sicurezza in Django è praticamente impossibile. La seguente lista vuole solo essere un promemoria del fatto che non dobbiamo mai, mai, mai sottovalutare l’argomento web security nelle nostre applicazioni. Tra gli altri punti ripetiamo comunque quanto detto nei precedenti paragrafi di questo capitolo.
- Utilizzo di HTTPS: assicuriamoci che la nostra applicazione usi HTTPS per proteggere le informazioni trasmesse tra il client e il server.
- Protezione CSRF (Cross-Site Request Forgery): Django ha un meccanismo di protezione CSRF integrato. Assicuriamoci di usarlo in tutti i nostri form.
- Gestione sicura delle password: usiamo
django.contrib.auth.hashers
per memorizzare le password in modo sicuro. - Prevenzione di SQL Injection: utilizziamo i
QuerySet
di Django ed evitiamo di inserire parametri direttamente nelle query SQL. - Controllo degli accessi: implementiamo controlli di autorizzazione per assicurarci che gli utenti possano accedere solo ai dati per cui hanno i permessi.
- Validazione e sanificazione dei dati: assicuriamoci di validare e sanificare tutti i dati in entrata per proteggere gli utenti dagli attacchi XSS (Cross-Site Scripting).
- Gestione delle sessioni: usiamo il sistema di gestione delle sessioni di Django e consideriamo l’implementazione di timeout di sessione e rotazione dei token di sessione.
- Protezione da clickjacking: usiamo il middleware X-Frame-Options di Django per proteggere il nostro sito dal clickjacking.
- Protezione da upload dannosi: verifichiamo e limitiamo il tipo e la dimensione dei file caricabili dall’utente.
- Logging e monitoraggio: implementiamo un sistema di logging per monitorare le attività sospette e rispondere prontamente a possibili incidenti di sicurezza.
- Honeypot: usiamo questo tipo di trappole, progettate per attirare e studiare gli hacker. Funzionano come una risorsa intenzionalmente vulnerabile e sono usate per monitorare gli attacchi e raccogliere informazioni sugli attaccanti.
- Aggiornamenti e dipendenze: manteniamo Django e tutte le dipendenze aggiornate per beneficiare delle ultime patch di sicurezza.
- Configurazione del database: assicuriamoci che la configurazione del database sia sicura, con permessi appropriati e isolamento dei dati quando necessario.
- Limitazione del numero di richieste per secondo: implementiamo un sistema di limitazione delle richieste per prevenire attacchi di tipo DoS (Denial of Service).
- Crittografia dei dati sensibili: crittografiamo i dati sensibili memorizzati, come le informazioni di pagamento o personali.
- Middleware di sicurezza: consideriamo l’uso di middleware di sicurezza di terze parti per una protezione aggiuntiva.
Questo articolo richiama contenuti da Sviluppare applicazioni con Django.
Immagine di apertura originale di KOBU Agency su Unsplash.