常见的防御跨站脚本攻击的方法有哪些?

14

换句话说,目前最常用的技术是什么,用于清理输入和/或输出? 工业界(甚至个人使用)网站上的人们使用什么来解决这个问题?


3
防御跨站脚本攻击(XSS)的主题非常多,毫无疑问它们是非常普遍的。http://stackoverflow.com/questions/tagged/xss - mauris
输入和输出从哪里到哪里? - Gumbo
以HTTP请求的形式向服务器输入,或以响应的形式从服务器输出。 - Admiraldei
内容安全策略(CSP)也是一种非常有效的防御跨站脚本攻击(XSS)的保护机制。请参阅此博客文章和http://content-security-policy.com/。 - rugk
4个回答

22

您应该参考优秀的OWASP网站,了解攻击(包括XSS)及其防御的概述。这是我能想到的最简单的解释,可能比他们的网页更易读(但可能远不如完整)。

  1. 指定字符集。首先,确保您的网页在头部或者在head元素的最开始处指定了UTF-8字符集。HTML编码所有输入以防止UTF-7攻击在Internet Explorer中(以及旧版本的Firefox)尽管有其他预防XSS的措施。

  2. HTML转义。请记住,您需要对所有用户输入进行HTML转义。这包括将<替换为&lt;,将>替换为&gt;,将&替换为&amp;,将"替换为&quot;。如果您将来要使用单引号的HTML属性,您还需要将'替换为&#39;。典型的服务器端脚本语言如PHP提供了函数来执行此操作,我鼓励您通过创建标准函数来插入HTML元素而不是以adhoc方式插入它们。

  3. 其他类型的转义。但是,您仍然需要小心,永远不要将用户输入作为未引用的属性或解释为JavaScript的属性(例如onloadonmouseover)插入。显然,这也适用于script元素,除非输入被正确地JavaScript转义,这与HTML转义不同。另一种特殊类型的转义是URL参数的URL转义(在HTML转义之前执行它以正确地将参数包含在链接中)。

  4. 验证URL和CSS值。对于链接和图像的URL(不基于已批准前缀进行验证),情况也是如此,因为存在javascript: URL方案,还有CSS样式表URL和style属性内的数据。 (Internet Explorer允许将JavaScript表达式作为CSS值插入,而Firefox在其XBL支持方面也存在问题。)如果您必须从不受信任的来源包含CSS值,则应该安全严格地验证或CSS转义它。

  5. 不允许用户提供的HTML。如果可以选择,请不要允许用户提供的HTML。这是导致XSS问题的简单方法,对自己的标记语言编写基于简单正则表达式替换的“解析器”也是如此。只有在HTML输出通过真正的解析器以明显安全的方式生成并使用标准转义函数转义输入中的任何文本并单独构建HTML元素时,我才会允许格式化的文本。如果您无法选择,使用验证器/净化器AntiSamy

  6. 防止基于DOM的XSS。不要将用户输入包含在JavaScript生成的HTML代码中并将其插入文档中。相反,请使用正确的DOM方法确保它被处理为文本而不是HTML。

显然,我无法涵盖攻击者可以插入JavaScript代码的每个特定情况。通常情况下,HTTP-only cookie 可能会使XSS攻击变得更加困难(但绝不是完全防止),而为程序员提供安全培训则是必不可少的。

2
我不明白为什么这个答案被投票评为最高。它实际上没有提到最重要的部分:使用适当的跨站请求伪造预防安全令牌,并且不对GET响应进行任何修改。你可以在自己的网站上引用和转义任意数量的内容,但这并不能防止其他网站包含一个表单或恶意脚本,以重复使用用户现有的登录cookie在你的网站上。我认为指出这一点很重要,因为问题本身很困惑(主题说XSS;问题说引用)。 - Jon Watte
2
@JonWatte 那些东西可以防止CRSF,而不是XSS。这个问题是关于XSS的,请求伪造与XSS无关。 - Johannes Kuhn

5
有两种XSS攻击。一种是您的网站以某种方式允许HTML被注入。这并不难以防御:要么转义所有用户输入数据,要么剥离所有<>标签并支持类似UBB代码的东西。注意:URL可能仍然会让您面临rick-rolling类型的攻击。
更加阴险的攻击是,某些第三方网站包含IFRAME、SCRIPT或IMG标签等,该标签会命中您网站上的URL,并且此URL将使用用户当前对您网站的身份验证。因此,您永远不应直接响应GET请求采取任何直接行动。如果您收到试图执行任何操作(更新配置文件、查看购物车等)的GET请求,则应该响应一个表单,该表单需要POST才能接受。该表单还应包含跨站请求伪造令牌,以便没有人可以在第三方网站上放置一个表单,该表单设置为使用隐藏字段提交到您的站点(再次避免伪装攻击)。

1

您的代码中只有两个主要区域需要妥善处理,以避免xss问题。

  1. 在查询中使用任何用户输入值之前,使用数据库辅助函数(如mysql_escape_string)对数据进行转义处理,然后再将其用于查询。这将保证防止xss攻击。

  2. 在将用户输入值显示回表单输入字段之前,请通过htmlspecialchars或htmlentities将它们通过。这将将所有易受xss攻击的值转换为浏览器可以显示的字符,而不会被破坏。

完成上述操作后,您将更加安全,可防范95%以上的xss攻击。然后,您可以继续从安全网站学习高级技术,并在您的站点上应用额外的安全措施。

大多数框架所做的是鼓励您不要直接编写HTML表单代码或字符串形式的查询,以使使用框架助手函数时,您的代码保持清洁,同时任何严重问题都可以通过在框架中更新一两行代码来快速解决。您可以简单地编写自己的常用函数库,并在所有项目中重复使用。


要明确的是,当你处理要传输到数据库的数据时,你需要考虑SQL注入问题,而不是跨站脚本攻击。此外,根据http://php.net/manual/en/function.mysql-escape-string.php的说明,该函数已被弃用(因为它忽略了字符集,并可能容易受到字符集编码过滤逃避技术的攻击),因此应该使用mysql_real_escape_string()函数。当然,在PHP中还需要做更多的工作:http://php.net/manual/en/security.database.sql-injection.php。 - atk

-1

如果你正在使用.NET进行开发,避免XSS攻击最有效的方法之一是使用Microsoft AntiXSS Library。这是一种非常有效的输入数据清洗方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接