How I (sort-of) Hacked Reddit

If you're reading this with Mozilla/Firefox, are logged in to Reddit, and have enough karma to submit without the CAPTCHA, you just upvoted it.

This is a follow-on to the CSRF vulnerability described by Monkeyget and posted to Programming Reddit earlier today. I wanted to see just how far I could get with this vulnerability. The answer is "not as far as I'd like" ;-), but it's still enough to be worrisome.

I initially wanted to create a story that, whenever it is clicked on, automatically upvotes itself. This turned out to be impossible, however, because Reddit includes a token with each AJAX vote, most likely a base64-encoded hash of an internal user ID. Without the token, Reddit ignores your vote. If I could grab a Reddit page - any Reddit page - while you are logged in, I could use a regexp to extract the token and then XMLHttpRequest it to the AJAX receiver. Unfortunately, browser security rules prevent me from reading pages on a separate domain. IFRAMEs, XMLHttpRequests, and plain old framesets will not let you read the source of a page loaded without the user's interaction.

However, there's another way to upvote stories. If you submit something that has already been submitted, it counts as an upvote. That's the approach taken here - this page has a hidden IFRAME, which loads a fake submission form, which is submitted automatically through JavaScript. Reddit has a CAPTCHA on submissions, but only for people below a certain karma threshold. Otherwise, as long as you're logged in, the system will not be able to tell whether you're submitting the story or whether my fake submission page is tricking your browser into submitting the story.

I would've liked to have made this work on IE, but IE blocks cookies going to sites other than the one the user is explicitly visiting. So when the fake submission comes in, Reddit sees it as not being logged in, and pops up a login page (which the user never sees, of course). If your security level is set low enough, IE will let the request through, but I don't know anyone who turns the default IE security levels down lower.

Right now, this hack isn't terribly impressive. I figure it might pick up an extra couple dozen voters, most of whom will reverse their votes once they get back to the main page. But it's potentially worrisome because hackers won't necessarily be submitting the same link every time. For example, a spammer might setup the hidden IFRAME to point to a PHP script (on their servers), which submits a random domain that they want pimped out. Each of these URLs would be submitted under the username of a high-karma user, bypassing the CAPTCHA and flooding the New page with spam.

The solution should be fairly simple: the submission form should include a username-unique token, like the AJAX moderation functions, that must be sent back with the submission. Only problem I can see might be with bookmarklets, but they ought to be checking the referer anyway, so it should be easy to catch abuse like this.