php - php: sql-injection > 无法使用prepared statement时如何防止?
问题描述
一个简单的问题:我有一个不使用准备好的语句(mySQLi)的框架。当我有一些用户输入(通过公共表单进行但不允许 HTML 代码)时,如何避免 sql 注入。该评论必须存储在 mysqli 数据库中。
检测和删除可能的注入代码的最佳做法是什么?请不要建议使用准备好的语句,如果不重写整个框架,它们是不可用的!
编辑
我不是在问如何进行 MySQLi 查询!我问如何防止 php 级别的 sql 注入。重复一遍:一些网站访问者在纯文本字段中留下评论。在此评论中,此访问者(脚本小子)认为,他可以发布 sql-injection。
现在再说一遍:在将其添加到数据库之前如何从评论中删除此伪代码。诸如“嘿,使用准备好的语句”、“使用 pdo”、“使用这种带有这些参数的查询”之类的答案并没有回答我的问题。还有像“改变”你的框架“或不够用的答案!
我知道这样的代码可以被 preg_replace(..) 等删除。是的,我知道这里有些人不使用这种技术的意见..所以最好不要朝那个方向回答!
解决方案
您可能认为在每个输入上使用mysqli::real_escape_string()之类的“转义”函数与使用准备好的语句一样安全。
除了:
转义不适用于数字输入,仅适用于带引号的字符串和带引号的日期。
转义有一些意想不到的情况,它不起作用。这些是边缘情况,但它们存在。请参阅有关mysql_real_escape_string()的 SQL 注入答案中的一些示例
编写代码时转义更难。正确地做是费时费力的,而且容易出错。开发人员经常想跳过它。
关心防止 SQL 注入的开发人员建议使用查询参数来代替,原因有几个,包括但不限于以下几点:
查询参数也适用于数值。
使用查询参数的代码更易于编写和阅读,并且不易出错。我们希望开发者一旦养成了使用查询参数的习惯,使用这种方式的可靠性会更高,漏洞的可能性也会降低。
例如,您可以编写如下代码:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES ('" . mysqli_real_escape_string($_POST['col1']) . "', "
. $mysqli->real_escape_string($_POST['col2']) . "', '"
. $mysqli->real_escape_string($_POST['col3']) . "', '"
. $mysqli->real_escape_string($_POST['col4']) . ", '"
. $mysqli->real_escape_string($_POST['col5']) . "', '"
. $mysqli->real_escape_string($_POST['col6']) . "')";
你能发现错误吗?有足够的时间,我相信你可以。但它会减慢你的编码速度,并且在你寻找丢失的引号字符和其他错误时可能会让你眼睛疲劳。
但是这样写要容易得多,之后也更容易阅读:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES (?, ?, ?, ?, ?, ?)";
查询参数对于更多数据类型是安全的,它们可以帮助您更快地编写代码,减少错误。这是一个很大的胜利。
与上面的其他评论一样,我不同意您关于 MySQLi 不支持查询参数的说法。它清楚地显示在文档中:https ://www.php.net/manual/en/mysqli.prepare.php
如果您有一些使用 MySQLi 但不支持的包装器代码mysqli::prepare()
,那么我建议您停止使用该包装器代码。要么为你的框架编写特性以便它使用查询参数,要么得到另一个框架。
还有像“改变”你的框架“或不够用的答案!
看,这是事实:如果你不能编写安全地处理用户输入的代码,那么你就不应该接受用户输入。
您认为有使用方法,preg_replace()
但没有。注入代码的方法有很多种(SQL 或 Javascript),最终您也会过滤掉许多合法的用户评论。如果您的 Web 应用程序从他们的评论中去掉引号和撇号,您的用户会有什么反应?您还需要删除哪些其他字符?
查询参数是这个问题最有效的解决方案。你对他们的抵制是荒谬的。
这就像一个电工问,“我怎样才能防止被电击?但我不能使用绝缘手套或工具,所以不要这么建议。”
推荐阅读
- c++ - 如何在 C++ 中以这种方式返回一行文本?
- bash - 根据 SSID 更改 MacOS 位置 - 无法让脚本自动运行
- ios - 在连接的设备上构建和运行带有 Firebase 框架错误的 swiftUI ios 应用程序的修复方法是什么?
- python - Flask-Uploads:如何按内容强制文件类型(不仅仅是扩展名)
- c++ - 从 cin 读取不会返回整个输入字符串
- python - Pygame 显示不更新
- c# - 如何在 Fact 测试方法中获取 xUnit Fact Attribute 'DisplayName' 参数
- sass - 如何使用汇总从 @material 导入 scss 文件?
- ios - xcode ios - 每当调整滑块时更新预定计时器
- r - 在 R 中,我如何在 5 个变量中随机选择(和平均)3 个和(以及其余 2 个)变量组?