如何在PHP应用程序中不使用PDO或绑定解决二阶SQL注入问题
如何在PHP应用程序中不使用PDO或mysqli绑定解决二阶SQL注入问题。我做了很多研究,但都指向我没有的PDO。mysql\u real\u escape\u string PHP escape只是为了防止引用。 现在我们使用的是使用mysql_connect的传统PHP。我们无法将系统升级为使用PDO或MySQLi,因为它需要安装依赖项。我们用逃逸来对付注射。但这并不能防止二阶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
$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我的回答对你有帮助吗?如果是这样,请记住,投票或接受答案是适当的。看见