SQL Injection
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.
Un'iniezione SQL è una vulnerabilità di sicurezza che consente agli attaccanti di interferire con le query del database di un'applicazione. Questa vulnerabilità può consentire agli attaccanti di visualizzare, modificare o eliminare dati a cui non dovrebbero avere accesso, inclusi informazioni di altri utenti o qualsiasi dato a cui l'applicazione può accedere. Tali azioni possono comportare modifiche permanenti alla funzionalità o al contenuto dell'applicazione o addirittura compromettere il server o causare un'interruzione del servizio.
Quando un sito appare vulnerabile all'iniezione SQL (SQLi) a causa di risposte insolite del server a input correlati all'SQLi, il primo passo è comprendere come iniettare dati nella query senza interromperla. Questo richiede di identificare il metodo per uscire dal contesto attuale in modo efficace. Questi sono alcuni esempi utili:
Poi, devi sapere come correggere la query in modo che non ci siano errori. Per correggere la query puoi inserire dati in modo che la query precedente accetti i nuovi dati, oppure puoi semplicemente inserire i tuoi dati e aggiungere un simbolo di commento alla fine.
Nota che se puoi vedere messaggi di errore o puoi notare differenze quando una query funziona e quando non funziona, questa fase sarà più facile.
Un metodo affidabile per confermare una vulnerabilità di SQL injection implica l'esecuzione di un operazione logica e l'osservazione dei risultati attesi. Ad esempio, un parametro GET come ?username=Peter
che produce contenuti identici quando modificato in ?username=Peter' o '1'='1
indica una vulnerabilità di SQL injection.
Allo stesso modo, l'applicazione di operazioni matematiche funge da tecnica di conferma efficace. Ad esempio, se l'accesso a ?id=1
e ?id=2-1
produce lo stesso risultato, è indicativo di SQL injection.
Esempi che dimostrano la conferma dell'operazione logica:
Questa lista di parole è stata creata per cercare di confermare le SQLinjections nel modo proposto:
In alcuni casi non noterai alcuna modifica nella pagina che stai testando. Pertanto, un buon modo per scoprire le SQL injection cieche è far eseguire azioni al DB che avranno un impatto sul tempo necessario per caricare la pagina. Pertanto, andremo a concatenare nella query SQL un'operazione che richiederà molto tempo per completarsi:
In alcuni casi, le funzioni sleep non saranno consentite. Quindi, invece di utilizzare quelle funzioni, potresti far sì che la query esegua operazioni complesse che richiederanno diversi secondi. Esempi di queste tecniche saranno commentati separatamente su ciascuna tecnologia (se presenti).
Il modo migliore per identificare il back-end è provare a eseguire funzioni dei diversi back-end. Potresti utilizzare le funzioni sleep della sezione precedente o queste (tabella da payloadsallthethings:
Anche se hai accesso all'output della query, potresti farlo stampare la versione del database.
In seguito discuteremo diversi metodi per sfruttare diversi tipi di SQL Injection. Useremo MySQL come esempio.
Se puoi vedere l'output della query, questo è il modo migliore per sfruttarlo. Prima di tutto, dobbiamo scoprire il numero di colonne che la richiesta iniziale sta restituendo. Questo perché entrambe le query devono restituire lo stesso numero di colonne. Due metodi sono tipicamente utilizzati per questo scopo:
Per determinare il numero di colonne in una query, regola progressivamente il numero utilizzato nelle clausole ORDER BY o GROUP BY fino a ricevere una risposta falsa. Nonostante le funzionalità distinte di GROUP BY e ORDER BY all'interno di SQL, entrambi possono essere utilizzati in modo identico per accertare il conteggio delle colonne della query.
Seleziona sempre più valori nulli fino a quando la query non è corretta:
Dovresti usare i valori null
poiché in alcuni casi il tipo delle colonne di entrambi i lati della query deve essere lo stesso e null è valido in ogni caso.
Negli esempi seguenti recupereremo il nome di tutti i database, il nome della tabella di un database, i nomi delle colonne della tabella:
C'è un modo diverso per scoprire questi dati su ogni database diverso, ma la metodologia è sempre la stessa.
Quando l'output di una query è visibile, ma un'iniezione basata su union sembra irraggiungibile, ciò significa che è presente un'iniezione basata su union nascosta. Questo scenario porta spesso a una situazione di iniezione cieca. Per trasformare un'iniezione cieca in una basata su union, è necessario discernere la query di esecuzione sul backend.
Questo può essere realizzato attraverso l'uso di tecniche di iniezione cieca insieme alle tabelle predefinite specifiche per il tuo Sistema di Gestione del Database (DBMS) target. Per comprendere queste tabelle predefinite, è consigliato consultare la documentazione del DBMS target.
Una volta estratta la query, è necessario adattare il tuo payload per chiudere in modo sicuro la query originale. Successivamente, una query union viene aggiunta al tuo payload, facilitando lo sfruttamento della nuova iniezione basata su union accessibile.
Per ulteriori approfondimenti, consulta l'articolo completo disponibile su Healing Blind Injections.
Se per qualche motivo non puoi vedere l'output della query ma puoi vedere i messaggi di errore, puoi utilizzare questi messaggi di errore per ex-filtrare dati dal database. Seguendo un flusso simile a quello dell'exploitation basata su Union, potresti riuscire a dumpare il DB.
In questo caso non puoi vedere i risultati della query o gli errori, ma puoi distinguere quando la query restituisce una risposta vera o falsa perché ci sono contenuti diversi sulla pagina. In questo caso, puoi abusare di quel comportamento per estrarre il database carattere per carattere:
Questo è il stesso caso di prima ma invece di distinguere tra una risposta vera/falsa dalla query puoi distinguere tra un errore nella query SQL o meno (forse perché il server HTTP si blocca). Pertanto, in questo caso puoi forzare un errore SQL ogni volta che indovini correttamente il carattere:
In questo caso non c'è alcun modo per distinguere la risposta della query in base al contesto della pagina. Ma, puoi far sì che la pagina impieghi più tempo a caricarsi se il carattere indovinato è corretto. Abbiamo già visto questa tecnica in uso prima per confermare una vulnerabilità SQLi.
Puoi utilizzare le stacked queries per eseguire più query in successione. Tieni presente che, mentre le query successive vengono eseguite, i risultati non vengono restituiti all'applicazione. Pertanto, questa tecnica è principalmente utile in relazione a vulnerabilità cieche in cui puoi utilizzare una seconda query per attivare una ricerca DNS, un errore condizionale o un ritardo temporale.
Oracle non supporta stacked queries. MySQL, Microsoft e PostgreSQL le supportano: QUERY-1-HERE; QUERY-2-HERE
Se nessun altro metodo di sfruttamento ha funzionato, puoi provare a far sì che il database esfiltri le informazioni a un host esterno controllato da te. Ad esempio, tramite query DNS:
Controlla il SQLMap Cheatsheet per sfruttare una vulnerabilità SQLi con sqlmap.
Abbiamo già discusso tutti i modi per sfruttare una vulnerabilità di SQL Injection. Trova alcuni altri trucchi dipendenti dalla tecnologia del database in questo libro:
Oppure troverai molti trucchi riguardanti: MySQL, PostgreSQL, Oracle, MSSQL, SQLite e HQL in https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.
Elenco da provare per bypassare la funzionalità di accesso:
Questa query mostra una vulnerabilità quando MD5 viene utilizzato con true per l'output raw nei controlli di autenticazione, rendendo il sistema suscettibile a SQL injection. Gli attaccanti possono sfruttare questo creando input che, quando hashati, producono parti di comandi SQL inaspettate, portando ad accessi non autorizzati.
Elenco raccomandato:
Dovresti usare come nome utente ogni riga dell'elenco e come password sempre: Pass1234. (Questi payload sono anche inclusi nel grande elenco menzionato all'inizio di questa sezione)
SE ' viene scappato puoi usare %A8%27, e quando ' viene scappato verrà creato: 0xA80x5c0x27 (╘')
Python script:
Per farlo dovresti provare a creare un nuovo oggetto chiamato come il "master object" (probabilmente admin nel caso degli utenti) modificando qualcosa:
Crea un utente chiamato: AdMIn (lettere maiuscole e minuscole)
Crea un utente chiamato: admin=
SQL Truncation Attack (quando c'è qualche tipo di limite di lunghezza nel nome utente o nell'email) --> Crea un utente con nome: admin [molti spazi] a
Se il database è vulnerabile e il numero massimo di caratteri per il nome utente è ad esempio 30 e vuoi impersonare l'utente admin, prova a creare un nome utente chiamato: "admin [30 spazi] a" e qualsiasi password.
Il database verificherà se il nome utente introdotto esiste all'interno del database. Se non esiste, taglierà il nome utente al numero massimo di caratteri consentito (in questo caso a: "admin [25 spazi]") e poi rimuoverà automaticamente tutti gli spazi alla fine aggiornando all'interno del database l'utente "admin" con la nuova password (potrebbero apparire alcuni errori, ma non significa che non abbia funzionato).
Ulteriori informazioni: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref
Note: Questo attacco non funzionerà più come descritto sopra nelle ultime installazioni di MySQL. Anche se i confronti ignorano ancora gli spazi finali per impostazione predefinita, tentare di inserire una stringa più lunga della lunghezza di un campo comporterà un errore e l'inserimento fallirà. Per ulteriori informazioni su questo controllo: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation
Aggiungi quanti più ','',''
ritieni necessari per uscire dalla dichiarazione VALUES. Se viene eseguito un ritardo, hai una SQLInjection.
La clausola ON DUPLICATE KEY UPDATE
in MySQL è utilizzata per specificare le azioni che il database deve intraprendere quando si tenta di inserire una riga che comporterebbe un valore duplicato in un indice UNIQUE o in una PRIMARY KEY. Il seguente esempio dimostra come questa funzionalità possa essere sfruttata per modificare la password di un account amministratore:
Esempio di Payload di Iniezione:
Un payload di iniezione potrebbe essere creato come segue, dove si tenta di inserire due righe nella tabella users
. La prima riga è un'esca e la seconda riga mira all'email di un amministratore esistente con l'intenzione di aggiornare la password:
Ecco come funziona:
La query tenta di inserire due righe: una per generic_user@example.com
e un'altra per admin_generic@example.com
.
Se la riga per admin_generic@example.com
esiste già, la clausola ON DUPLICATE KEY UPDATE
si attiva, istruendo MySQL ad aggiornare il campo password
della riga esistente a "bcrypt_hash_of_newpassword".
Di conseguenza, l'autenticazione può quindi essere tentata utilizzando admin_generic@example.com
con la password corrispondente all'hash bcrypt ("bcrypt_hash_of_newpassword" rappresenta l'hash bcrypt della nuova password, che dovrebbe essere sostituito con l'hash effettivo della password desiderata).
Quando si tenta di creare un nuovo utente, sono necessari nome utente, password e email:
Con questa tecnica puoi estrarre informazioni creando solo 1 account. È importante notare che non è necessario commentare nulla.
Utilizzando hex2dec e substr:
Per ottenere il testo puoi usare:
Utilizzando hex e replace (e substr):
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.
Routed SQL injection è una situazione in cui la query iniettabile non è quella che produce output, ma l'output della query iniettabile va alla query che produce output. (From Paper)
Esempio:
No Space (%20) - bypass utilizzando alternative agli spazi bianchi
No Whitespace - bypass using comments
No Whitespace - bypass using parenthesis
No Comma - bypass utilizzando OFFSET, FROM e JOIN
Blacklist usando parole chiave - bypass usando maiuscole/minuscole
Blacklist usando parole chiave senza distinzione tra maiuscole e minuscole - bypass usando un operatore equivalente
Puoi trovare una spiegazione più approfondita di questo trucco nel blog di gosecure. Fondamentalmente puoi utilizzare la notazione scientifica in modi inaspettati per bypassare il WAF:
Prima di tutto, nota che se la query originale e la tabella da cui vuoi estrarre il flag hanno lo stesso numero di colonne puoi semplicemente fare: 0 UNION SELECT * FROM flag
È possibile accedere alla terza colonna di una tabella senza utilizzare il suo nome usando una query come la seguente: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
, quindi in un sqlinjection questo apparirebbe come:
O usando un comma bypass:
Questo trucco è stato preso da https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro fervente per professionisti della tecnologia e della cybersecurity in ogni disciplina.
Impara e pratica Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Impara e pratica Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)