这个问题刚刚出现在我的脑海中,无法在任何地方找到这个问题,所以我认为这是最好的提问地点。这仅用于教育目的。我使用了适当的卫生设施,并且没有为我的真实数据库提供 DROP 权限。
让我们假设一个具有所有权限的数据库和一个具有三个值的简单插入查询
INSERT INTO test(a,b,c) VALUES('$a','$b','$c');
上述查询容易受到 sql 注入(inject)攻击。
让我们假设用户输入是
- a',(select DATABASE()),'a')--
- 离开2
- 离开3
结果查询将是这样的:
INSERT INTO test(a,b,c) VALUES('a',(select DATABASE()),'a')-- ','begone2','begone3')
上述查询将执行并将数据库名称插入表中,但我的问题是攻击者是否能够在不知道数据库名称的情况下删除数据库?,使用如下查询:
INSERT INTO test(a,b,c) VALUES
('a',(DROP DATABASE (select DATABASE())),'a')-- ','begone2','begone3')
我尝试运行上面的查询,但它抛出了一个错误。这个查询有什么问题?
最佳答案
What's wrong with this query?
INSERT INTO test(a,b,c) VALUES
('a',(DROP DATABASE (select DATABASE())),'a')-- ','begone2','begone3')
这个查询有两个问题。
您不能将 DROP DATABASE 放入子查询中。子查询必须是 SELECT 语句并具有结果集(在您显示的示例中,它必须是一列、一行的结果集)。
就其值(value)而言,您也不允许在子查询中使用 INSERT/UPDATE/DELETE。
DROP DATABASE 不接受子查询的结果作为其参数。语法 DROP DATABASE 接受数据库标识符(名称),您不能 DROP DATABASE ''。子查询的结果始终是数据值(如字符串和数字),而不是标识符。
与这个查询比较:
SELECT a, b, c, (SELECT x FROM table2) FROM table1
子查询返回列
x
的值。如果x
的值是字符串值“d”,这不会导致外部查询返回标识为table1.d
的列的值。它返回文字字符串“d”。
通常,SQL 不允许您使用数据值作为标识符。数据库名称、表名称和列名称必须在查询被解析之前显式写入查询。要使标识符动态化,您必须运行两个查询,也就是说,您将在创建第二个 SQL 语句时使用第一个查询的结果。
关于php - 在 SQL 注入(inject)中使用嵌套 SQL 子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52027618/