UNION SQL Injection

1

Sto cercando di dimostrare SQL Injection con una query UNION ma non ho risultati.

Questo è il codice C # e il database è SQL Server 2008 R2:

        string cString = "server=.\sqlexpress; database=testDB; trusted_connection=true";
        SqlConnection conn = new SqlConnection(cString);
        conn.Open();

        string sql = "select * from Users where UserName='" + userName + "' and Password='" + password + "'";
        SqlCommand cmd = conn.CreateCommand();
        cmd.CommandText = sql;

        SqlDataReader reader = cmd.ExecuteReader();

        StringBuilder sb = new StringBuilder(1024);

        while (reader.Read())
        {
            for (int i = 0; i < reader.FieldCount; i++)
            {
                sb.Append(" " + reader.GetName(i));
                sb.Append(": ");
                sb.Append(reader[i]);
            }
            sb.Append("<br />");
        }
        dataLabel.Text = sb.ToString();

Ho una casella di testo username e password e l'input è passato a questo metodo.
Ho provato quanto segue ma nessun risultato:

'union select * from products -

la tabella Utenti e la tabella Prodotti hanno tipi di colonna identici (int, nvarchar, nvarchar).
Qualcuno può aiutare? Cosa mi manca?

    
posta Test Er 13.01.2013 - 02:04
fonte

2 risposte

3

Perché una dichiarazione di selezione unione funzioni, entrambe le istruzioni select devono restituire lo stesso numero di colonne. Questo perché una selezione unione concatena entrambe le istruzioni selezionate e le restituisce come un unico set di dati.

Se la prima tabella, Users ha 4 colonne, l'exploit sarà simile a:

select * from Users where UserName='' union select producs.id,products.name,products.price,products.quantity,products from products-- ' and Password=''"

In questo caso la prima istruzione select non restituirà un valore perché non c'è un record nel database dove UserName='' , dove come la seconda dichiarazione restituirebbe informazioni dalla tabella prodotti. Sebbene un exploit più probabile sarebbe quello di selezionare la password dalla tabella Users nella posizione del nome utente in modo che venga stampata da reader.GetName(i) .

Un altro modo per sfruttare questo problema è fornire i tuoi dati da restituire:

select * from Users where UserName='' union select 1,'admin','password','ADMINISTRATOR','[email protected]' -- ' and Password=''"

Se i dati restituiti dalla query vengono utilizzati in una funzione sensibile, come essere in grado di contaminare una variabile utilizzata nella valutazione di file o codice.

Come fai a sapere quante colonne ha la prima query?
Uso l'intruso di rutti per iterare su ogni possibilità e filtrare per richieste senza errori.

... o potresti semplicemente usare sqlmap

    
risposta data 13.01.2013 - 07:22
fonte
0

Durante il test, perché non aggiungere un'istruzione di debug che registra la query SQL prima di eseguirla?

Quindi provare a eseguirlo direttamente nel database e vedere quale messaggio di errore viene restituito dal DB (se presente)?

Se non ci sono inavvertitamente l'escape automatico di ' nel tuo framework, sembra che la tua query:

string sql = "select * from Users where UserName='" + userName + "' and Password='" + password + "'";

diventa:

 string sql = "select * from Users where UserName='' union select * from products --' and Password=''";

Puoi verificare che una stringa come questa appaia nel tuo log (che il tuo framework non abbia inavvertitamente scappato ' caratteri)?

È possibile eseguire quella specifica stringa SQL? Restituisce un messaggio di errore per il tuo schema / tabelle specifici? (Non programma in .NET, uso SQL-server, o ho il tuo database (tendo ad usare lo stack linux, ad es. Postgresql).)

Ma in esecuzione su un DB di esempio ho avuto dove ho provato un UNION di due tabelle come SELECT * FROM table_a where name='' union select * from table_b , ottengo un errore dal mio DB: SELECT a sinistra ea destra dell'unione non hanno lo stesso numero di colonne di risultati. Il mio table_a aveva 7 colonne e table_b aveva 11 colonne. Pertanto, l'unione delle 7 colonne di table_a e delle 11 colonne di table_b non funzionerà.

Questo ha senso se cerchi ciò che SQL UNION fa:

The UNION operator is used to combine the result-set of two or more SELECT statements.

Notice that each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order.

PS: The column names in the result-set of a UNION are always equal to the column names in the first SELECT statement in the UNION.

Quindi devi indovinare lo schema e assicurarti che corrisponda. Cioè se la query SQL originale aveva un select * from Users , e le colonne degli Utenti sono user_id (INT), userName (VARCHAR), password (VARCHAR), devi assicurarti che l'UNION richieda tre campi specifici che hanno i dati int, VARCHAR e VARCHAR presenti nella seconda tabella. Inoltre, se non vuoi i risultati della prima query, potresti voler aggiungere un AND 1=0 alla tua clausola WHERE .

    
risposta data 13.01.2013 - 11:08
fonte