提问人:user332951 提问时间:9/12/2020 更新时间:9/14/2020 访问量:248
如何在 PHP 应用程序中不使用 PDO 或绑定的情况下解决二阶 SQL 注入问题
How to address second order SQL injection without using PDO or binding in PHP application
问:
如何在 PHP 应用程序中不使用 PDO 或 mysqli 绑定的情况下解决二阶 SQL 注入问题。我做了很多研究,但都指向我没有的PDO。mysql_real_escape_string PHP 转义只是为了防止引号。 现在我们有使用mysql_connect的旧 PHP。我们无法升级系统以使用 PDO 或 MySQLi,因为它需要安装依赖项。为了克服注射,我们使用逃逸。但这并不能防止二阶 SQL 注入。
$name = $_POST['名称'];$user =“从名称 = $name 的用户中选择用户”
现在使用 $id 获取用户位置。请注意,当前代码不执行 join,因为这只是示例。
$loc = “从用户 = $user的位置选择 *”
目前,我们正在使用Escape进行$name和$user来防止注射。但问题是,如果第一个查询包含SQL查询,那么我们就有问题了。因此,我们需要一种方法来转义查询,这样第二个查询将是安全的
答:
您说得对,在将整个子查询插入到位置查询中时不能使用。mysql_real_escape_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 注入的建议通常归结为“使用查询参数”,这在许多情况下是正确的,但在这种情况下它不起作用。
escape-string 函数和绑定查询参数都仅用于保护 SQL 表达式中的单个值。对于动态 SQL 查询的其他部分,这两种方法都不是有用的:
- 标识符,如表名或列名
- 值列表(例如,在谓词中)
IN(...)
- 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'"
然后,您可以将该子查询用作第二个查询的一部分,并且不存在 SQL 注入的风险。
$loc_query = "Select * from location where user IN ($user_query)"
顺便说一句,我做了两个小改动:
- 将子查询放在括号内
- 使用代替 .如果子查询可以在其结果中返回多行,则不允许使用 .
IN( )
=
=
我还建议您学习如何在 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 变量进行转义。
您还会发现 PHP 7+ 通常比 PHP 5.x 具有更好的性能。
你不能升级是不正确的。这需要一些工作。
评论
上一个:开关函数SQL注入安全吗?
下一个:如何防止PHP中的SQL注入?
评论
mysql_real_escape_string PHP escape is just for protection against the quotes.
谁告诉你这些废话?也被弃用了很长时间,所以你似乎在那里有非常过时的设置mysql_