我想对我的用户好一点,但不想错误地获取恶意代码。看了这么多问题,我决定加入白名单,所以我只得到我认可的角色。
怎么可能对用户友善,所以我让他们输入许多字符并仍然保持我的输入免受恶意代码的影响?
我正在使用 Apache 和 PHP 5.3.8,我还没有合并 PDO,因为当我听说它时,我已经深入到项目中,担心它可能会发生太大的变化。
任何想法都会有所帮助!
我想对我的用户好一点,但不想错误地获取恶意代码。看了这么多问题,我决定加入白名单,所以我只得到我认可的角色。
怎么可能对用户友善,所以我让他们输入许多字符并仍然保持我的输入免受恶意代码的影响?
我正在使用 Apache 和 PHP 5.3.8,我还没有合并 PDO,因为当我听说它时,我已经深入到项目中,担心它可能会发生太大的变化。
任何想法都会有所帮助!
如果它可以输出给用户,则必须防止潜在的恶意用户在其代码中包含 HTML 标记。例如,如果在那篇文章中,我可以包含一个script
标签,这对于阅读我的文章的任何用户来说都是非常危险的。为了防止这种情况,你想使用htmlentities
:
$clean_data = htmlentities($_POST['data']);
这样,我的<script>
标签将被翻译,<script>
因此在浏览器显示时不会伤害用户。
现在,如果你想将我的帖子保存在你的数据库中,你必须小心 SQL 注入。假设您正在使用该查询保存我的帖子(是的,您不应该使用mysql_*
已弃用的函数,但这只是为了解释这个想法):
mysql_query($db, "INSERT INTO posts(data) values('$clean_data');");
听起来不错 ?好吧,如果我很讨厌,我会尝试包含该帖子:
test'); DELETE FROM posts; SELECT * FROM posts WHERE data = '
那么你的 MySQL 得到的是
INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = '');
哎哟。因此,您必须基本上防止您的用户在他的帖子中包含引号和双引号,或者更准确地说,您应该转义它们。这实际上取决于您使用的库,但在我使用的过时的库中,会这样写:
$really_clean_data = mysql_real_escape_string($db, $clean_data);
mysql_query($db, "INSERT INTO posts(data) values('$really_clean_data');");
所以,有了上面的恶意帖子,MySQL 现在会收到
INSERT INTO posts(data) values('test\'); DELETE FROM posts; SELECT * FROM posts WHERE data = \'');
现在,对于 MySQL,整个INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = '');
部分都是正确的字符串,所以发生的事情就是你想要发生的事情。
基本上,在几乎所有情况下,这就是您所需要的。请记住,当您将用户数据提供给解释器(它可以是 Web 浏览器、SQL 引擎或许多其他东西)时,您应该清理该数据,最好的方法是使用应该随您使用的库一起提供。
只是为了补充 Fabien 已经给出的答案,文本数据类型并不是您需要关注的唯一项目。数字同样重要。类型转换你的变量是处理它的一种方法。例如,
$really_clean_data = mysql_real_escape_string($db, $clean_data);
$query = "UPDATE posts SET post = '".$really_clean_data."' WHERE id = '".(int)$_POST['id']."'";
提交的所有数据,包括您要更新的帖子的 ID 号,都与文本区域或文本输入条目一样可疑,并且同样容易受到恶意修改。当你知道它应该是一个整数(数字)时,你可以这样转换它。如果它不是数字,则 (int) 会将其转换为 0。您无法更新第 0 行,因此 SQL 查询将失败。
要在执行查询之前检查该故障,您可以使用 is_numeric() 函数检查发布的数据以查看它是否为数字。
if(!is_numeric($_POST['id'])){
die("Post id is not a number.");
}
对于输入字段,尤其是用户名和密码字段,您可以设置最大长度并检查。例如,
if(strlen($_POST['username']) > 24){
$error = "username is too long";
}
如果您可以对此有所创意,那么防止 SQl 注入实际上很有趣!请记住,从现在起一年后,此页面上的所有内容都可能完全过时且无关紧要。安全是一个过程,而不是一个步骤,所以要时刻关注它。