/ xss

xss

如果提交的表单数据中包含 HTML 或 JavaScript,会导致严重的问题。

如果用户输入在评论中输入This page<b>rules!!!</b> ,而且应用一字不差地将其显示出来,那么浏览这个页面时看到的 rules!!! 就是粗体。Web 浏览器不会区分应用自身提供的 HTML 标签(例如显示评论的表格或列表)和内嵌在评论中的 HTML 标签。

虽然显示粗体的文本没什么问题,但是如果不过滤用户输入话,应用就会遇到更大的麻烦。如果用户输入 <a href=" 这种没有关闭的标签,此时 Web 浏览器便无法正确显示页面。

更糟的是,提交的评论中可能包含 JavaScript 代码,当你查看页面时,Web 浏览器会执行那些代码,做些破坏,例如把 cookie 发送到陌生人的电子邮箱中,或者偷偷地重定向到其他网页。

这时,你的应用成了帮凶,允许恶意用户上传 HTML 或 JavaScript 代码,当不知情的用户访问页面时,那些代码会在用户的浏览器中运行。

这种问题叫跨站脚本攻击,因为编写不当的博客程序把来自一处(恶意用户)的代码伪装成来自另一处(评论所在的应用)。

为了防止程序遭受跨站脚本攻击,一定不能原封不动地显示外部输入。要么删除可疑的部分(如HTML标签),要么编码特殊字符,从而避免让浏览器执行内嵌的 HTML 或 JavaScript。

strip_tags() 删除标签

$comments = '<b>XSS</b>';

// 要么删除评论中的 HTML 标签
$comments = strip_tags($_POST['comments']);

strip_tags() 函数特别便利,但是不能正确匹配 <>。例如,它会把 I <3 Monkey 处理为 I,一旦遇到 <strip_tags()就会开始删除标签,然后就停不下来,因为它没有发现对应的>

htmlentities() 编码,效果更好。

编码的效果通常更好。

$comments = '<b>XSS</b>';

// 要么编码字符串中的特殊字符
$comments = htmlentities($_POST['comments']);

I <3 Monkey 会处理为 I &lt;3 Monkey

总结

对多数应用来说,应该使用 htmlentities() 净化外部输入。这个函数不会丢掉任何内容,而且还能防止跨站脚本攻击。