Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/228.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应用程序中不使用PDO或绑定解决二阶SQL注入问题_Php_Mysql_Pdo_Sql Injection - Fatal编程技术网

如何在PHP应用程序中不使用PDO或绑定解决二阶SQL注入问题

如何在PHP应用程序中不使用PDO或绑定解决二阶SQL注入问题,php,mysql,pdo,sql-injection,Php,Mysql,Pdo,Sql Injection,如何在PHP应用程序中不使用PDO或mysqli绑定解决二阶SQL注入问题。我做了很多研究,但都指向我没有的PDO。mysql\u real\u escape\u string PHP escape只是为了防止引用。 现在我们使用的是使用mysql_connect的传统PHP。我们无法将系统升级为使用PDO或MySQLi,因为它需要安装依赖项。我们用逃逸来对付注射。但这并不能防止二阶SQL注入 $name = $_POST['name']; $name_esc = mysql_real_esca

如何在PHP应用程序中不使用PDO或mysqli绑定解决二阶SQL注入问题。我做了很多研究,但都指向我没有的PDO。mysql\u real\u escape\u string PHP escape只是为了防止引用。 现在我们使用的是使用mysql_connect的传统PHP。我们无法将系统升级为使用PDO或MySQLi,因为它需要安装依赖项。我们用逃逸来对付注射。但这并不能防止二阶SQL注入

$name = $_POST['name'];
$name_esc = mysql_real_escape_string($name);

$user_query = "Select user from user where name = '$name_esc'"
$loc_query = "Select * from location where user IN ($user_query)"
$name=$_POST['name']$user=“从用户名=$name的用户中选择用户”

现在使用$id获取用户位置。请注意,当前代码没有连接,因为这只是一个示例

$loc=“从用户=$user的位置选择*”


目前,我们正在对$name和$user使用escape来防止注入。但问题是,如果第一个查询包含SQL查询,那么我们就有问题了。因此,我们需要一种方法来转义查询,这样第二个查询将是安全的

您是正确的,在将整个子查询插入位置查询时,您不能使用
mysql\u real\u escape\u string()

$name = $_POST['name'];

$user = "Select user from user where name = $name"

$user_esc = mysql_real_escape_string($user); -- WRONG

$loc = "Select * from location where user = $user"
通常归结为“使用查询参数”,这在许多情况下都是正确的,但在这种情况下它不起作用

转义字符串函数和绑定查询参数都仅用于保护SQL表达式中的单个值。这两种方法对于动态SQL查询的其他部分都不有用:

  • 表名或列名等标识符
  • 值列表(例如,(…)
谓词中的
内部)
  • SQL关键字
  • SQL表达式
  • 整个SQL子查询,如您的情况
  • 在您的例子中,您的子查询是由应用程序控制的固定字符串,除了$name变量。如果您转义该变量,那么它就不会受到SQL注入的影响

    $name = $_POST['name'];
    $name_esc = mysql_real_escape_string($name);
    
    $user_query = "Select user from user where name = '$name_esc'"
    
    $loc_query = "Select * from location where user IN ($user_query)"
    
    然后,您可以将该子查询用作第二个查询的一部分,并且不存在SQL注入的风险

    $name = $_POST['name'];
    $name_esc = mysql_real_escape_string($name);
    
    $user_query = "Select user from user where name = '$name_esc'"
    
    $loc_query = "Select * from location where user IN ($user_query)"
    
    顺便说一下,我做了两个小改动:

    • 将子查询放在括号内
    • 在()
    中使用
    ,而不是
    =
    。如果子查询可以在其结果中返回多行,则不允许使用
    =
    我还建议您学习如何在SQL中使用联接。这是一种使用SQL的普通且推荐的方法。通常,如果表的索引正确,使用联接的查询比使用子查询的查询具有更好的性能,即使两个查询产生相同的结果。下面是一个例子:

    $name = $_POST['name'];
    $name_esc = mysql_real_escape_string($name);
    
    $loc_query = "Select loc.* from user join loc using (user) 
        where user.name = '$name_esc'";
    

    我可能会因为给您提供了一个使用mysql_real_escape_string()的解决方案而被否决,因为该函数已被弃用,并且已从当前版本的PHP中删除

    我建议升级到PHP的当前版本,并建议使用PDO和查询参数。它们更容易、更安全、性能更好

    $loc_query = "Select loc.* from user join loc using (user) 
        where user.name = ?";
    
    $stmt = $pdo->prepare($loc_query);
    $stmt->execute( [ $_POST['name'] ] );
    
    使用查询参数时,无需转义post变量

    您还会发现PHP7+通常比PHP5.x具有更好的性能


    你不能升级不是真的。这需要一些工作。

    mysql\u real\u escape\u string PHP escape只是为了防止引用。
    谁告诉你这些废话的?另外,
    mysql\uuu
    已经被弃用很长一段时间了,所以您的设置似乎已经非常过时了,因此一阶或n阶sql注入之间没有区别。保护是一样的,应该为要插入到SQL中的每个字符串执行保护。不管是一级订单还是二级订单。只有一个SQL注入。然而,使用PHP5是非常不负责任的。如果你认真对待你的用户,你应该尽你所能尽快升级。上面的评论是错误的,他们显然没有阅读你的代码示例。他们是懒惰的,只是自动关闭几乎任何问题标记的PHP/SQL注入作为重复的。这是一个很好的例子,它回答了大多数SQL注入问题,但它没有涵盖您的情况。您的声明“转义字符串函数…仅用于保护SQL表达式中的单个值”是不正确的,并且具有误导性。不是“值”,而是字符串文字。或带引号的日期文字。或引用的数字文字(奇数但允许)。我相信您知道,我同意使用查询参数是一个更好的解决方案。但是OP可能会遇到这样的情况:他们的老板没有升级所需的预算。mysql中没有“日期文字”。两者都没有“引用的数字文字”。它可以是数字文字,也可以是字符串文字,不管里面可能是什么特殊字符。@user332951我的回答对你有帮助吗?如果是这样,请记住,投票或接受答案是适当的。看见