XSS - 哪些 HTML 标签和属性会触发 JavaScript 事件?

24
我正在尝试编写一个安全且轻量级的基于白名单的HTML净化器,它将使用DOMDocument。为了避免不必要的复杂性,我愿意做出以下妥协:
- HTML注释将被删除 - script和style标签将被完全去除 - 只有body标签的子节点将被返回 - 所有可以触发Javascript事件的HTML属性将被验证或删除
我一直在阅读关于XSS攻击和预防的文章,希望我不会太天真(如果我是,请告诉我!),因为我认为如果我遵循上述所有规则,我将免受XSS攻击的威胁。
问题是我不确定还有哪些标签和属性(在任何[X]HTML版本和/或浏览器版本/实现中)可以触发Javascript事件,除了默认的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. 是否存在任何攻击向量未被这些规则覆盖?

经过大量测试、思考和研究,我想出了以下(相当简单的)实现方法,它似乎对我能想到的任何XSS攻击向量都是免疫的。
非常感谢您宝贵的回答,谢谢。

1
如果浏览器支持类似于 http:jascript:alert(... 的格式错误的 URL,那么您检查 URI 的方法可能会被欺骗。 - hakre
有关JavaScript评估的方法有很多可能的变化,例如编码和解码、eval、外部JavaScript文件等等......基本上,没有已知的方法可以阻止用户做坏事。你可以尝试转义标签、单词、引号,但仍然可能通过有趣的方法注入XSS。我建议阅读WhiteHat security来了解这个问题,也许你能找到一些有用的东西? - Igoris Azanovas
1
这听起来不像是“基于白名单”的方法。基于白名单的方法是只复制你知道是无害的标签和属性。你不需要一个有害属性的列表。 - hmakholm left over Monica
只要没有执行JavaScript,链接是否损坏我并不在意。从我的有限测试中(我没有大量的操作系统和浏览器),那段代码片段(以及其他一些变体)都不会起作用。 - Alix Axel
@Troy:我明白你的意思,但以a标签为例。你将其列入白名单。显然,它本身并不是很有用,除非你也将其href属性列入白名单;现在你有一个问题,如何将每个可能的有效和安全(绝对和相对)URL都列入白名单?!如果没有第二次黑名单,我会说那是不可能的。虽然每天都会发现新的攻击向量,但(至少我所见过的)所有攻击都依赖于同样的旧标签和/或属性,可以执行Javascript代码,我打算删除JS特定的内容并清理有用的内容。 - Alix Axel
显示剩余3条评论
4个回答

11
你提到了在哪些地方可以出现javascript:的URL,包括hrefaction,但你错过了一堆其他加载URL属性中的src属性。

OWASP Java HTMLPolicyBuilder的第399行是一个白名单HTML消毒器中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 中包含了属性类型的摘要。虽然它没有提到一些条件性的东西,比如<input type=URL value=...>,但如果您在该列表中搜索valid URL和friends,您应该会对HTML5增加了什么有一个很好的概念。具有%URI类型的HTML 4属性集也是有启发性的。

您的协议白名单看起来非常类似于OWASP sanitizer。添加ftpsftp似乎毫无危险。

有关HTML元素和属性的安全相关模式信息的一个好来源是Caja JSON白名单,这些白名单由Caja JS HTML sanitizer使用。

您打算如何呈现结果DOM?如果您不小心,即使您剥离了所有的<script>元素,攻击者也可能会让一个有缺陷的渲染器生成被浏览器解释为包含<script>元素的内容。请考虑不包含脚本元素的有效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白名单也非常不错。 - Alix Axel
关于DOM渲染,我的代码还有些生疏,但我使用了PHP内置的strip_tags()函数来过滤白名单标签(以减轻dom扩展的工作量),然后使用DOMDocument遍历剩余的HTML节点,如果它们不在白名单中或被永久加入黑名单,则删除标签或属性节点。我发现strip_tags()中存在一些错误,所以我将重新编写整个代码,只使用dom扩展。我仍在测试是否需要在使用dom之前使用tidy,或者dom本身就足够智能。 - Alix Axel
http://my.opera.com/karlcow/blog/list-of-elements-attributes-having-url-for-value-in-html5 - Alix Axel
https://dev59.com/SHE85IYBdhLWcg3wikIu - Alix Axel
抱歉贴了这么多链接,但我有很多标签页打开,它们可能会引起某些人的兴趣。我“搜索”了Caja属性白名单并进行了一些谷歌搜索,显然OWASP项目没有考虑以下(新)属性:profilemanifestposterformactioniconlongdesc。此外,我无法找到你提到的dsync属性的任何参考资料,你有吗? - Alix Axel
@Alix Axel,我不记得dsync是什么了。我认为它是一些晦涩的供应商特定的东西,被列入了我的清单中。我现在也找不到任何关于它的参考资料。无论是Caja列表还是OWASP项目都不是HTML 5方面的详尽白名单,但它们都是白名单。 - Mike Samuel

5
Garuda已经给出了我认为是“正确”的答案,他的链接非常有用,但他比我更快!
我只是为了强调而回答。
在这个日益增长的html和ecmascript规范功能的时代,避免脚本注入和其他类似漏洞在html中变得越来越困难。随着每一个新的添加,一个可能的注入世界就被引入。这与不同的浏览器可能有不同的想法如何实现这些规范相结合,因此您会得到更多的潜在漏洞。
看看html 5引入的矢量的简短列表。
最好的解决方案是选择允许而不是拒绝什么。说“这些标签和这些给定标签的属性是允许的。其他所有内容将被相应地净化或丢弃”要容易得多。

我编制一份列表并说“好的,这里是你错过的所有注入向量的列表,你可以放心睡觉”,这将非常不负责任。事实上,黑帽子或白帽子可能还不知道许多注入向量。正如ha.ckers网站所述,脚本注入实际上仅受思维的限制。

我想至少回答你的具体问题,这是你的黑名单中明显遗漏的一些内容:

  • img src属性。我认为需要注意的是,src是其他元素上的有效属性,可能会造成潜在危害。另外img还有dynsrclowsrc等属性。
  • typelanguage 属性
  • 除了html注释外,还有CDATA
  • 未经适当清理的输入值。这可能取决于您的HTML解析的严格程度。
  • 任何模棱两可的特殊字符。我的看法是,即使是不含歧义的字符也应该进行编码。
  • 属性缺失或引号使用错误(如重音符号引号)。
  • textarea标签过早地关闭。
  • 脚本中的UTF-8(和7)编码字符
  • 尽管您只会返回标记的子节点,但许多浏览器仍会评估内部的和元素,以及大多数仅限的元素,所以这可能帮助不大。
  • 除了css表达式之外,还有背景图像表达式
  • frameiframe
  • embed和可能的objectapplet
  • 服务器端包含
  • PHP标记
  • 任何其他注入(SQL注入、可执行注入等)

顺便说一句,我相信这并不重要,但驼峰式属性是无效的xhtml,应该改为小写。我相信这不会影响你。


好的回答,+1。您提到的链接依赖于onfocus属性,如果将其删除,则新的autofocus属性本身不会构成危险,因此我不认为这是一个新的攻击向量,它只是“增强”了现有的攻击向量。 - Alix Axel
关于您提到的一些问题,其中一些可能会成为问题,但是我使用基于白名单的方法 - 我只是试图编译一个始终内部使用的黑名单(即不可配置)。src属性特别令人担忧,我将测试您提到的所有内容,看看情况如何。 - Alix Axel
当你说“xss表达式”时,你是指“CSS表达式”,例如IE中的<div style="height: expression(alert(1337))">和其他浏览器中的moz-binding等吗? - Mike Samuel

2

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

http://adamcecc.blogspot.com/2011/01/javascript.html(当您的“过滤”输入会在页面上的脚本标记之间找到时,仅适用于此)

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

我像您一样使用了HTML Purifier,这也是为了与wysiwyg编辑器结合使用。我所做的不同之处在于使用非常严格的白名单,其中包含几个基本的标记和属性,并在需要时扩展它。这可以使您免受非常模糊的向量(如上面的第一个链接)的攻击,并且您可以逐个挖掘新需求的标记/属性。

只是我的个人意见。


谢谢,我知道 XSS Cheat Sheet。第一个链接看起来很有趣,但是那个帖子恰好总结了我试图避免的事情:“如果它在JavaScript/dom的可执行部分中任何地方出现,这就是一个alert(),它会弹出cookie”。HTML Purifier 是 PHP HTML 标记清理的事实上标准,但是它也非常沉重,我希望通过做一些小妥协,能够得到更轻量级的解决方案。 - Alix Axel
你对于过度使用重量级组件的看法是完全正确的 :) 尽管我还没有因为HTML净化器的清理而明显延迟页面加载的经验。由于这是一个相当成熟的框架,我相信开发人员已经意识到了性能问题,并且他们很可能使其尽可能轻量级和快速。如果您个人仍然觉得这是一个问题,我建议您考虑使用PHP代码缓存(如APC)或从Zend引擎中进行优化。 - Garuda
所有页面未找到。 - mpgn

0

+1,我之前不知道这些新属性。我查了一下,似乎只有以“on”开头的属性都是JavaScript事件触发器。我可能会删除所有符合该模式的属性。 - Alix Axel
2
请不要引用w3schools,使用更有信誉的来源。请参考http://www.w3fools.com/。 - molnarg

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