Come la Sicurezza DataSunrise protegge dalle Iniezioni SQL
In questo articolo, dimostriamo come DataSunrise previene le iniezioni SQL, uno degli strumenti di hacker più popolari per violare le applicazioni web. Per mostrarti esattamente cosa accade quando DataSunrise intercetta una query dannosa, eseguiamo un test di penetrazione con un software dedicato.
Sqlmap
Sebbene esistano molte applicazioni dedicate a svolgere la valutazione automatizzata delle vulnerabilità, utilizziamo Sqlmap nell’esperimento corrente. Questo programma gratuito e open-source è scritto in linguaggio Python ed è facile da usare grazie alla sua interfaccia a riga di comando.
Secondo la descrizione ufficiale, SQLmap può utilizzare le seguenti tecniche di iniezione SQL per i test di penetrazione:
Cieco basato su booleani
Sqlmap aggiunge al parametro vulnerabile nella query HTTP una dichiarazione SQL sintatticamente valida, contenente una subdichiarazione SELECT o qualsiasi altra dichiarazione SQL utilizzata per recuperare l’output dal database. Quindi Sqlmap confronta ogni risposta HTTP con la richiesta originale e ottiene l’output della dichiarazione iniettata carattere per carattere.
Cieco basato sul tempo
Sqlmap aggiunge al parametro vulnerabile una dichiarazione sintatticamente valida, contenente una query che causa un ritardo nel back-end DBMS per un certo numero di secondi. Poi l’utilità esegue un confronto tra il tempo di risposta originale e il tempo impiegato per la risposta alla query iniettata e quindi deduce l’output della dichiarazione iniettata carattere per carattere.
Basato su errori
Sqlmap aggiunge al parametro vulnerabile nella richiesta HTTP una stringa di dichiarazione sintatticamente non valida causando il messaggio di errore specifico del database. Quindi Sqlmap analizza la risposta HTTP cercando di trovare messaggi di errore contenenti codice SQL iniettato e l’output della subquery all’interno. Questo metodo di iniezione SQL funziona solo se il DBMS è configurato per mostrare i messaggi di errore del DBMS back-end.
Basato su query UNION
Sqlmap aggiunge al parametro vulnerabile nella richiesta HTTP una dichiarazione SQL sintatticamente valida che inizia con UNION ALL SELECT. Questo metodo è utile quando la pagina dell’applicazione web utilizza un ciclo FOR o simile per passare l’output della dichiarazione SELECT, quindi ogni riga dell’output della query è stampata sul contenuto della pagina. Sqlmap è in grado di sfruttare anche le vulnerabilità di iniezione SQL della query UNION “parziale”. Tali vulnerabilità si verificano quando il ciclo FOR non è utilizzato e solo la prima voce dell’output della query viene mostrata.
Basato su query impilate (piggybacking)
Se l’applicazione web di destinazione supporta query impilate, Sqlmap aggiunge al parametro vulnerabile nella query HTTP un punto e virgola (;) seguito dalla dichiarazione SQL da iniettare. Questa tecnica è utilizzata per eseguire l’iniezione di dichiarazioni SQL diverse da SELECT (come le dichiarazioni di definizione dei dati o di manipolazione dei dati). Potenzialmente, questo metodo può essere utilizzato per ottenere l’accesso in lettura/scrittura al file system e l’esecuzione di comandi del sistema operativo a seconda del back-end DBMS e dei privilegi dell’utente della sessione.
Come puoi vedere, Sqlmap è uno strumento potente in grado non solo di rivelare vulnerabilità ma di sfruttarle con varie tecniche di iniezione SQL. Ecco di più sui metodi di rilevazione delle iniezioni SQL.
Preparazioni per il test
Per eseguire la nostra dimostrazione abbiamo bisogno di una qualche applicazione “di prova” da sottoporre a iniezione SQL, quindi utilizziamo un semplice server web scritto in Python. Questo server è progettato per produrre informazioni dal database definite dai parametri nella stringa URL. Abbiamo salvato il codice del server web nel file webserv_inj.py:
import re import urllib.request from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import urlparse import pyodbc global dbconnection global dbcursor class InjectedServer(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html charset=windows-1251") self.end_headers() o = urlparse(self.path) params = urllib.request.unquote(o.query) m = re.search("id=(?P[^;]+);name=(?P[^;]+)", params) id = m.group("id") name = m.group("name") dbconnection = pyodbc.connect( "Driver=PostgreSQL ODBC Driver(ANSI);Server=localhost;Port=54321;Database=test_db;Uid=postgres;Pwd=admin;UseServerSidePrepare=1") dbcursor = dbconnection.cursor() queryStr = "select * from injected_table where id = " + id + " and name = '" + name + "' order by id" dbcursor.execute(queryStr) result = dbcursor.fetchall() for row in result: self.wfile.write(bytes(str(row[0]), "utf-8")) self.wfile.write(bytes(str(row[1]), "utf-8")) self.wfile.write(bytes(str(row[2]), "utf-8")) myServer = HTTPServer(("127.0.0.1", 6589), InjectedServer) try: myServer.serve_forever() except KeyboardInterrupt: pass myServer.server_close()
Proveremo a violare il nostro server web auto-costruito e ottenere alcuni dati da un database PostgreSQL. Abbiamo utilizzato il seguente codice per creare una nuova tabella nel database (“injected_table“) e riempirla con due voci:
CREATE TABLE injected_table ( id integer, name character varying(200), surname character varying(200) ) INSERT INTO injected_table VALUES (1, Bob, Martin); INSERT INTO injected_table VALUES (2, Denis, Morgan);
Ecco come appare la nuova tabella in PGAdmin
Quindi avviamo il nostro server eseguendo il seguente comando tramite il prompt dei comandi di Windows:
python webserv_inj.py
Per essere sicuri che tutto funzioni come previsto, inviamo la seguente query al server web tramite browser web:
http://127.0.0.1:6589/?id=2;name=Denis
Come risultato, il server web produrrà la voce di “injected_table” con ID=2 e Nome=Denis
Testare il server web con Sqlmap
Ora è il momento di verificare se il nostro server web può essere sottoposto a iniezione SQL.
Prima iniziamo la procedura di test di Sqlmap tramite il prompt dei comandi:
python.exe sqlmap.py -u http://127.0.0.1:6589/?id=2;name=Denis
Quando il processo di test è terminato, diamo un’occhiata al file di log di Sqlmap (è stato creato automaticamente e salvato all’interno della cartella “output”).
sqlmap identified the following injection point(s) with a total of 50 HTTP(s) requests: --- Parameter: id (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: id=2;name=Denis' AND 8150=8150 AND 'lsHq'='lsHq Type: AND/OR time-based blind Title: PostgreSQL > 8.1 AND time-based blind Payload: id=2;name=Denis' AND 9061=(SELECT 9061 FROM PG_SLEEP(5)) AND 'TLxE'='TLxE Type: UNION query Title: Generic UNION query (NULL) - 3 columns Payload: id=2;name=Denis' UNION ALL SELECT NULL,NULL,(CHR(113)|| CHR(112)||CHR(120)||CHR(120)||CHR(113))||(CHR(88)||CHR(109)||CHR(66)||CHR(103)||CHR(114)|| CHR(69)||CHR(83)||CHR(119)||CHR(113)||CHR(98)||CHR(110)||CHR(73)||CHR(90)||CHR(83)|| CHR(90)||CHR(121)||CHR(113)||CHR(102)||CHR(85)||CHR(117)||CHR(107)||CHR(72)||CHR(78)|| CHR(101)||CHR(79)||CHR(90)||CHR(112)||CHR(120)||CHR(74)||CHR(106)||CHR(114)||CHR(105)|| CHR(85)||CHR(84)||CHR(71)||CHR(104)||CHR(71)||CHR(89)||CHR(75)||CHR(111))||(CHR(113)|| CHR(22)||CHR(107)||CHR(122)||CHR(113))-- - --- back-end DBMS: PostgreSQL
Come mostra il log, Sqlmap ha identificato con successo la versione del DBMS (PostgreSQL) e ha determinato che il parametro “ID” è vulnerabile all’iniezione SQL. Inoltre, Sqlmap ci ha proposto tre varianti di dichiarazioni SQL che possono essere utilizzate per eseguire l’iniezione SQL (stringhe di Payload).
Impostazioni della regola di Sicurezza di DataSunrise (sezione iniezioni SQL)
Ora verificheremo quanto efficacemente DataSunrise può proteggere il server web vulnerabile (e il relativo database PostgreSQL) dalle iniezioni SQL.
Abbiamo creato una regola di Sicurezza “SQL injection” (consultare la guida utente di DataSunrise per i dettagli) e cancellato i file creati da Sqlmap durante il primo test.
Ora eseguiremo nuovamente la procedura di test di Sqlmap (come descritto sopra) e quando il test termina verifichiamo il log dell’utilità (si noti che Sqlmap non è stato in grado di creare un file di log quindi utilizziamo il suo log a riga di comando).
Secondo il log, Sqlmap ha definito che tutti i parametri testati non sono vulnerabili all’iniezione SQL, inclusi il parametro “ID” che era stato precedentemente marcato come iniettabile.
Conclusione
Il nostro esperimento dimostra che il firewall di DataSunrise è altamente efficace nel prevenire le iniezioni SQL. Tuttavia, per ottenere la migliore protezione possibile contro le minacce più complesse è necessario adottare misure protettive estese come le seguenti:
- Seguiras le migliori pratiche del settore per sviluppare applicazioni web resistenti alle iniezioni SQL
- Eseguire attacchi hacker simulati sui propri database e applicazioni web per rivelare possibili vulnerabilità (i cosiddetti “test di penetrazione”)
- Audit continuo del database per la rilevazione della violazione e della perdita di dati
- Seguire le raccomandazioni e le linee guida degli sviluppatori sull’uso sicuro dei database e del software associato.
DataSunrise supporta tutti i principali database e data warehouse come Oracle, Exadata, IBM DB2, IBM Netezza, MySQL, MariaDB, Greenplum, Amazon Aurora, Amazon Redshift, Microsoft SQL Server, Azure SQL, Teradata e altro ancora. Sei invitato a scaricare una prova gratuita se desideri installarla nei tuoi locali. In caso Lei sia un utente cloud e gestisca il tuo database su Amazon AWS o Microsoft Azure, puoi ottenerlo dal AWS market place o dall’Azure market place.