我一直在阅读有关保护 PHP 应用程序的内容,在我看来,这mysqli_real_escape_string
是在将数据插入 MySQL 表时使用的正确函数,因为addslashes
可能会导致聪明的攻击者发生一些奇怪的事情。对?
然而,有一件事让我感到困惑。我似乎记得被建议addslashes
比htmlentities
将用户输入的数据回显给用户以保护他们的数据要好,但似乎addslashes
是有漏洞的那个。这是真的,还是我记错了?
我一直在阅读有关保护 PHP 应用程序的内容,在我看来,这mysqli_real_escape_string
是在将数据插入 MySQL 表时使用的正确函数,因为addslashes
可能会导致聪明的攻击者发生一些奇怪的事情。对?
然而,有一件事让我感到困惑。我似乎记得被建议addslashes
比htmlentities
将用户输入的数据回显给用户以保护他们的数据要好,但似乎addslashes
是有漏洞的那个。这是真的,还是我记错了?
它们是用于不同目的的不同工具。
mysqli_real_escape_string 使数据可以安全地插入 MySQL(但参数化查询更好)。
Htmlentities 使数据可以安全地输出到 HTML 文档中
addlashes 在其他一些情况下使数据安全,但对于 MySQL 来说还不够
您的数据有不同的上下文。将数据插入数据库的上下文需要以不同于呈现 html/xml 甚至电子邮件消息的上下文进行转义。
转义进入数据库的数据应该在所有新代码中被弃用,以支持准备好的语句。任何告诉你其他情况的人都是对你的极大伤害。
转义到浏览器的数据需要根据目标以多种不同的方式进行转义。有时 htmlspecialchars 就足够了,有时你需要使用 htmlentities。有时您需要数字实体。这是一个你应该做一些研究以了解所有细微差别的话题。
我遵循的一般规则是验证(不过滤,如果不正确则拒绝)输入和转义输出(基于上下文)。
你也可以使用为你完成大部分转义的PDO 库,以防你在服务器上使用 PHP5。
在回声时,我个人更喜欢 htmlspecialchars,但有人可能会纠正我
是的,在所有用户输入上使用 mysqli_real_escape_string 或类似 PDO 的库。回显时,我使用带有 ENT_QUOTES 作为第二个参数的 htmlentities,因为它将所有适用的字符转义到它们的 html 实体,包括引号。
注意:应避免在 UTF-8 编码的文档中使用 htmlentities()。看:
注意(引自phpwact.org):
借助现代 Web 浏览器和对 UTF-8 的广泛支持,您不需要 htmlentities,因为所有这些字符都可以直接用 UTF-8 表示。更重要的是,一般来说,只有浏览器支持 HTML 的特殊字符——例如,普通的文本编辑器不知道 HTML 实体。根据您的操作,使用 htmlentities 可能会降低其他系统“使用”您的内容的能力。
此外(未确认但听起来很合理 - 来自此处的匿名评论),字符实体(例如 » 或 —)在文档用作 application/xml+xhtml 时不起作用(除非您定义它们)。不过,您仍然可以摆脱数字形式。
PHP 5.2 及更高版本的另一个有趣的解决方案是使用过滤器扩展:http ://www.php.net/manual/en/book.filter.php
它允许您验证和清理用户输入。有许多可用的内置过滤器,它们可以与标志组合以调整它们的行为。此外,这些过滤器还可用于验证/清理整数、浮点数、电子邮件、特定正则表达式。
我个人已经开始在我的项目中使用它们来验证表单和输出用户输入的数据,我很高兴我做到了。虽然,当我在 MySQL 数据库中插入值时,我使用准备好的查询来增加安全性。这些解决方案一起可以帮助避免大多数 SQL 注入和 XSS 类型的攻击。
您不能拥有一个“转义”功能并期望它一直工作。有不同的攻击需要特定的卫生程序。理解这个概念的唯一方法是编写一些易受攻击的代码然后利用它。编写漏洞利用代码对于理解任何安全系统都至关重要。
例如,此查询易受 Sql 注入攻击:
$host=htmlspecialchars($_GET[host],ENT_QUOTES);
$name=htmlspecialchars($_GET[name],ENT_QUOTES);
mysql_query("select * from user where Host='$host' and Name='$name' ");
利用: http://localhost/sqli_test.php?host= \&name=%20sleep(20)--%201
mysql 的最佳转义函数是 mysqli_real_escape_string() 但这可能会失败:
mysql_query("select * from user where id=".mysqli_real_escape_string($_GET[id]));
利用: http://localhost/sqli_test.php?id=1%20or%20sleep(20)
事实上,处理 sql 注入的最佳方法不是调用转义函数,它使用 ADODB 的参数化查询进行 sql 注入。对 XSS 使用 htmlspecialcahrs($var,ENT_QUTOES)。阅读OWASP 前 10 名,因为 Web 应用程序安全性可能出错的地方还有很多。