Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在SQL注入中使用嵌套SQL子查询_Php_Mysql_Sql Server_Database_Sql Injection - Fatal编程技术网

Php 在SQL注入中使用嵌套SQL子查询

Php 在SQL注入中使用嵌套SQL子查询,php,mysql,sql-server,database,sql-injection,Php,Mysql,Sql Server,Database,Sql Injection,这个问题刚出现在我的脑海中,我在任何地方都找不到,所以我想这是最好的提问地点。这只是为了教育目的。我使用适当的卫生设施,并且没有为我的真实数据库提供删除权限 让我们假设一个具有所有权限的数据库和一个具有三个值的简单插入查询 INSERT INTO test(a,b,c) VALUES('$a','$b','$c'); 上述查询易受sql注入攻击 让我们假设用户输入为 a',(选择数据库(),'a')-- 开始2 开始3 结果查询如下: INSERT INTO test(a,b,c) VAL

这个问题刚出现在我的脑海中,我在任何地方都找不到,所以我想这是最好的提问地点。这只是为了教育目的。我使用适当的卫生设施,并且没有为我的真实数据库提供删除权限

让我们假设一个具有所有权限的数据库和一个具有三个值的简单插入查询

INSERT INTO test(a,b,c) VALUES('$a','$b','$c');
上述查询易受sql注入攻击

让我们假设用户输入为

  • a',(选择数据库(),'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')
我尝试运行上面的查询,但它抛出了一个错误。这个查询有什么问题

我的问题是,攻击者是否能够在不知道数据库名称的情况下删除数据库

答案是肯定的,这就是为什么我们应该使用参数而不是包含字符串,并尽可能避免使用动态SQL

恶意用户可以使用以下函数获取数据库名称:

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;
我的问题是,攻击者是否能够在不知道数据库名称的情况下删除数据库

答案是肯定的,这就是为什么我们应该使用参数而不是包含字符串,并尽可能避免使用动态SQL

恶意用户可以使用以下函数获取数据库名称:

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;
这个查询有什么问题

此查询有两个问题

  • 不能将DROP数据库放入子查询中。子查询必须是SELECT语句并具有结果集(在您显示的示例中,它必须是一列一行的结果集)

    无论如何,也不允许在子查询中使用INSERT/UPDATE/DELETE

  • DROP数据库不接受子查询的结果作为其参数。语法DROP DATABASE接受数据库标识符(名称),不能删除数据库“”。子查询的结果总是数据值(如字符串和数字),而不是标识符

    与此查询进行比较:

    SELECT a, b, c, (SELECT x FROM table2)
    FROM table1
    
    子查询返回列
    x
    的值。如果
    x
    的值是字符串值“d”,这不会导致外部查询返回标识为
    table1.d
    的列的值。它返回一个文本字符串“d”

  • 通常,SQL不允许您使用数据值作为标识符。在解析查询之前,必须在查询中显式写入数据库名、表名和列名。要使标识符成为动态的,必须运行两个查询,即,在创建第二个SQL语句时使用第一个查询的结果

    这个查询有什么问题

    此查询有两个问题

  • 不能将DROP数据库放入子查询中。子查询必须是SELECT语句并具有结果集(在您显示的示例中,它必须是一列一行的结果集)

    无论如何,也不允许在子查询中使用INSERT/UPDATE/DELETE

  • DROP数据库不接受子查询的结果作为其参数。语法DROP DATABASE接受数据库标识符(名称),不能删除数据库“”。子查询的结果总是数据值(如字符串和数字),而不是标识符

    与此查询进行比较:

    SELECT a, b, c, (SELECT x FROM table2)
    FROM table1
    
    子查询返回列
    x
    的值。如果
    x
    的值是字符串值“d”,这不会导致外部查询返回标识为
    table1.d
    的列的值。它返回一个文本字符串“d”

  • 通常,SQL不允许您使用数据值作为标识符。在解析查询之前,必须在查询中显式写入数据库名、表名和列名。要使标识符成为动态的,必须运行两个查询,即,在创建第二个SQL语句时使用第一个查询的结果

    攻击者是否能够在没有实际攻击的情况下删除数据库 知道数据库名称吗

    对。假设使用MySQL,请参阅以下PHP代码:

    $a=“”,”);设置@sql=CONCAT('DROP DATABASE',DATABASE());从@sql准备stmt;执行stmt;--”;
    $b=null;
    $c=null;
    $sql=“插入测试(a,b,c)值('$a','$b','$c');”;
    echo$sql;
    
    它将创建以下MySQL语句:

    插入测试(a,b,c)值(“”,“”);设置@sql=CONCAT('DROP DATABASE',DATABASE());从@sql准备stmt;执行stmt;--','','');
    
    尝试执行上述SQL将删除当前数据库

    攻击者是否能够在没有实际攻击的情况下删除数据库 知道数据库名称吗

    对。假设使用MySQL,请参阅以下PHP代码:

    $a=“”,”);设置@sql=CONCAT('DROP DATABASE',DATABASE());从@sql准备stmt;执行stmt;--”;
    $b=null;
    $c=null;
    $sql=“插入测试(a,b,c)值('$a','$b','$c');”;
    echo$sql;
    
    它将创建以下MySQL语句:

    插入测试(a,b,c)值(“”,“”);设置@sql=CONCAT('DROP DATABASE',DATABASE());从@sql准备stmt;执行stmt;--','','');
    

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

    是,例如:
    插入选项卡值(1,2,3);删除数据库…;--恶意用户可以通过两个步骤(插入数据库名称并读取)或使用动态SQL完成此操作。所以正确的答案是:使用参数化查询。@LukaszSzozda我已经使用了准备好的查询,但这里我只是举一个例子,不管怎么说,是为了