【问题标题】:XSS - Which HTML Tags and Attributes can trigger Javascript Events?XSS - 哪些 HTML 标签和属性可以触发 Javascript 事件?
【发布时间】:2011-08-07 21:54:49
【问题描述】:

我正在尝试编写一个安全且轻量级的基于白名单的 HTML 净化器,它将使用 DOMDocument。为了避免不必要的复杂性,我愿意做出以下妥协:

  • HTML cmets 被移除
  • scriptstyle 标记一起被剥离
  • 只会返回body标签的子节点
  • 所有可以触发 Javascript 事件的 HTML 属性都将被验证或删除

我已经阅读了很多关于 XSS 攻击和预防的内容,我希望我不会太天真(如果我是,请告诉我!)假设我遵守了上面提到的所有规则,我不会受到 XSS 的伤害。

问题是我不确定除了default Javascript event attributes之外还有哪些其他标签和属性(在任何[X]HTML版本和/或浏览器版本/实现中)可以触发Javascript事件:

  • onAbort
  • onBlur
  • onChange
  • onClick
  • onDblClick
  • onDragDrop
  • onError
  • onFocus
  • onKeyDown
  • onKeyPress
  • onKeyUp
  • onLoad
  • onMouseDown
  • onMouseMove
  • onMouseOut
  • onMouseOver
  • onMouseUp
  • onMove
  • onReset
  • onResize
  • onSelect
  • onSubmit
  • onUnload

是否有任何其他非默认或专有事件属性可以触发 Javascript(或 VBScript 等)事件或代码执行?我可以想到hrefstyleaction,比如:

<a href="javascript:alert(document.location);">XSS</a> // or
<b style="width: expression(alert(document.location));">XSS</b> // or
<form action="javascript:alert(document.location);"><input type="submit" /></form>

我可能会删除 HTML 标记中的所有 style 属性,actionhref 属性提出了更大的挑战,但我认为以下代码足以确保它们的值是相对值或绝对值URL 而不是一些讨厌的 Javascript 代码:

$value = $attribute->value;

if ((strpos($value, ':') !== false) && (preg_match('~^(?:(?:s?f|ht)tps?|mailto):~i', $value) == 0))
{
    $node->removeAttributeNode($attribute);
}

所以,我的两个明显问题是:

  1. 我是否缺少任何可以触发事件的标签或属性?
  2. 是否存在这些规则未涵盖的攻击媒介?

经过大量测试、思考和研究,我想出了following (rather simple) implementation,它似乎对我可以扔给它的任何 XSS 攻击向量免疫。

非常感谢您提供的所有宝贵答案,谢谢。

【问题讨论】:

  • 如果浏览器支持 http:jascript:alert(... 等格式错误的 url,您对 URI 的检查可能会被愚弄。
  • 好吧,javascript 的评估有很多可能的变化,比如编码和解码。 eval,外部 javascript 文件等等......基本上,没有已知的方法可以防止用户做坏事。您可以尝试转义标签、单词、引号,但仍然可以通过有趣的方法注入 xss。对于这个问题,我建议阅读WhiteHat security,也许你能找到有用的东西?
  • 这听起来不像“基于白名单”。基于白名单的方法是只复制您知道是无害的标签和属性。你不需要一个harm_ful_属性列表。
  • @hakre:只要不执行 Javascript,我真的不在乎链接是否损坏。从我有限的测试(我没有过多的操作系统、浏览器)来看,sn-p(和其他一些变体)不起作用。
  • @Henning:我应该说得更清楚...标签必须始终列入白名单(scriptstyle 将始终被删除)。标签属性可以列入白名单,也可以不列入(允许所有属性,应内部清理或列入黑名单)。如果您允许a 标签,您可能还需要允许href 属性并且您仍然遇到同样的问题 - 这就是为什么我采用第二遍黑名单方法,因为将所有可能的标签属性列入白名单值会过于繁琐且极易出现人为错误。

标签: php javascript html security xss


【解决方案1】:

您提到hrefaction 作为可以出现javascript: URL 的地方,但是您在一堆其他URL 加载属性中缺少src 属性。

Line 399 of the OWASP Java HTMLPolicyBuilder 是白名单 HTML sanitizer 中 URL 属性的定义。

private static final Set<String> URL_ATTRIBUTE_NAMES = ImmutableSet.of(
  "action", "archive", "background", "cite", "classid", "codebase", "data",
  "dsync", "formaction", "href", "icon", "longdesc", "manifest", "poster",
  "profile", "src", "usemap");

HTML5 Index 包含属性类型的摘要。它没有提到像&lt;input type=URL value=...&gt; 这样的条件性内容,但是如果您扫描该列表以查找valid URL 和朋友,您应该对HTML5 添加的内容有一个不错的了解。类型为%URIHTML 4 attributes 集合也提供了丰富的信息。

您的协议白名单看起来与OWASP sanitizer 非常相似。 ftpsftp 的添加看起来很无害。

HTML 元素和属性的安全相关架构信息的良好来源是 Caja JS HTML sanitizer 使用的 Caja JSON whitelists

您打算如何渲染生成的 DOM?如果你不小心,那么即使你去掉了所有的&lt;script&gt; 元素,攻击者也可能得到一个有缺陷的渲染器来生成浏览器解释为包含&lt;script&gt; 元素的内容。考虑不包含脚本元素的有效 HTML。

<textarea><&#47;textarea><script>alert(1337)</script></textarea>

有缺陷的渲染器可能会输出以下内容:

<textarea></textarea><script>alert(1337)</script></textarea>

其中确实包含一个脚本元素。

(完全披露:我编写了上面提到的两种 HTML 清理程序。)

【讨论】:

  • 你的答案是黄金,如果可以的话+10!我查看了 OWASP PHP Sanitizer,但那里只有一个抽象类,然而 Java 版本似乎非常完整。我不确定如何测试您提到的某些属性中是否正在执行 Javascript,如果您碰巧知道,请告诉我。 Google Caja 白名单也很简洁。
  • 哦,至于 DOM 渲染,我的代码仍然非常前卫,但我使用 PHP 内置的 strip_tags() 和白名单标签(从 @987654344 中提取一些工作@ 扩展名),然后使用 DOMDocument 遍历剩余的 HTML 节点,如果它们没有被列入白名单或被永久列入黑名单,则删除标记或属性节点。我想我在strip_tags() 中发现了一些错误,所以我将仅使用dom 扩展名重写整个内容。我还在测试之前是否需要使用tidy,或者单独使用dom 是否足够聪明。
  • 很抱歉发布所有这些链接,但我有大量的选项卡打开 ATM,他们可能会感兴趣。我“搜索”了 Caja 属性白名单并进行了一些谷歌搜索,显然 OWASP 项目没有考虑以下(新)属性:profilemanifestposterformactionicon 和 @ 987654355@。另外,我找不到对您提到的dsync 属性的任何引用,您碰巧有吗?
【解决方案2】:

Garuda 已经给出了我认为“正确”的答案,他的链接非常有用,但他打败了我!

我给出我的答案只是为了加强。

在这个 html 和 ecmascript 规范中功能不断增加的时代,避免 html 中的脚本注入和其他此类漏洞变得越来越困难。随着每一个新的添加,引入了一个可能的注射的整个世界。再加上不同的浏览器可能对如何实现这些规范有不同的想法,因此您可能会遇到更多可能的漏洞。

看看html 5介绍的向量的简短列表

最好的解决方案是选择允许的,而不是拒绝的。说“这些标签和这些给定标签的属性是允许的。其他所有东西都会相应地清理或丢弃。”

如果我编制一份清单并说“好吧,给你:这是你错过的所有注射载体的清单。你可以睡得安稳”,这是非常不负责任的。事实上,可能有许多甚至是黑帽或白帽都不知道的注入向量。正如 hackers 网站所说,脚本注入实际上只受头脑的限制。

我想至少稍微回答一下您的具体问题,因此您的黑名单中有一些明显的遗漏:

  • imgsrc 属性。我认为重要的是要注意src 是其他元素的有效属性,并且可能有害。 img 还有dynsrclowsrc,也许更多。
  • typelanguage 属性
  • CDATA 除了 html cmets。
  • 未正确清理输入值。这可能不是问题,具体取决于您的 html 解析的严格程度。
  • 任何不明确的特殊字符。在我看来,即使是明确的也应该被编码。
  • 属性上的引号缺失或不正确(例如严重引号)。
  • textarea 标签过早关闭。
  • 脚本中的 UTF-8(和 7)编码字符
  • 即使您只返回 body 标记的子节点,许多浏览器仍然会评估 headhtml 内的元素 body,以及大多数 head 内的元素 body 无论如何,所以这可能不会有太大帮助。
  • 除了css表达式,还有背景图表达式
  • frames 和 iframes
  • embed 可能还有 objectapplet
  • 服务器端包括
  • PHP 标记
  • 任何其他注入(SQL 注入、可执行注入等)

顺便说一句,我确定这无关紧要,但是 camelCased 属性是无效的 xhtml 并且应该小写。我相信这不会影响你。

【讨论】:

  • 好答案,+1。您提到的链接依赖于 onfocus 属性,如果将其删除,则新的 autofocus 属性本身不会造成任何危险,因此我不认为 new 攻击向量,它只是“赋予“现有的权力。
  • 至于你提到的几点,其中一些可能是一个问题,但我再次使用基于白名单的方法 - 我只是想编译一个将永远存在的黑名单内部使用(即不可配置)。 src 属性特别令人担忧,我会测试你提到的所有内容,看看效果如何。
  • 当您说“xss 表达式”时,您的意思是指“CSS 表达式”,如 IE 的 &lt;div style="height: expression(alert(1337))"&gt; 和其他浏览器的 moz-binding 和类似的吗?
【解决方案3】:

您可能需要查看这两个链接以获取更多参考:

http://adamcecc.blogspot.com/2011/01/javascript.html(这仅适用于您被“过滤”的输入会在页面上的脚本标签之间找到自己的情况)

http://ha.ckers.org/xss.html(其中列出了许多特定于浏览器的事件触发器)

正如您所做的那样,我使用了 HTML Purifier,因为这个原因也结合了所见即所得的编辑器。我所做的不同之处在于使用了一个非常严格的白名单,其中包含几个可用的基本标记标签和属性,并在需要时对其进行扩展。这可以防止您受到非常晦涩的向量(如上面的第一个链接)的攻击,并且您可以一个一个地挖掘新需要的标签/属性。

只要我的 2 美分..

【讨论】:

  • 谢谢,我知道 XSS 备忘单。第一个链接看起来很有趣,但是海报用一句话总结了我试图避免的内容:“没错,这是一个 alert() 如果它位于 JavaScript/dom 的可执行部分中的任何位置它弹出cookie”。 HTML Purifier 是 PHP HTML 清理的de facto 标准,但它也很重,我希望如果做出一些小的妥协,我将能够提出更轻量级的东西.
  • 你在重量级的矫枉过正方面是绝对正确的 :) 虽然我还没有经历过由于 HTML 净化器的清理而导致页面加载的明显延迟。由于它是一个非常完善的框架,我很确定开发人员已经意识到了性能问题,并且他们很可能使其尽可能轻巧和快速。如果它对您个人来说仍然是个问题,我建议您研究 PHP 代码缓存(如 APC)或 Zend 引擎。
  • 找不到所有页面
【解决方案4】:

不要忘记 HTML5 JavaScript 事件处理程序

http://www.w3schools.com/html5/html5_ref_eventattributes.asp

【讨论】:

  • +1,我不知道这些新属性。我查了一下,似乎唯一以on 开头的属性都是Javascript 事件触发器。我可能会删除所有与该模式匹配的内容。
  • 请不要参考 w3schools,使用更有信誉的来源。见w3fools.com
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 2011-04-16
  • 2010-11-05
  • 2017-10-27
  • 2011-11-14
相关资源
最近更新 更多