About.com Poll Exploit
Any online poll that doesn’t require some form of registration is going to run into big problems when trying to limit users to one vote each. The standard procedure of many online polls is to assume that each IP address constitutes one person, and thus the poll is limited to one vote per IP address. Whilst this assumption is of course flawed in both aspects (one IP address can be assigned to multiple people, and one person may have access to multiple IP addresses), it is a good one to have when trying to limit the amount of “voter fraud” in anonymous online polls. However, relying on this assumption alone as a preventative measure is not even close to good enough.
Other methods for limiting people to one vote each usually rely on the ignorance of most internet users in terms of how browsers work. For instance, a relatively common method I have seen is to set a cookie when the user votes, and then to check the status of that cookie whenever they make a subsequent vote. If the cookie is set, the vote is disallowed (though this action may not be communicated back to the user), and if the cookie is empty or non-existent, the vote goes into the system. Since cookies are stored on the user’s computer and not the poll server, they can be easily (in most cases) deleted by the user in question. In fact, many browsers have methods built-in to them to deny cookies from certain websites1, and some have extensions that can easily be used to perform repetitive votes in an online poll.2
If preventing as many instances of voter fraud as possible is your aim, then using methods that depend on client-side procedures is a big mistake. Limiting the poll to one vote per IP address is the best way to go if you don’t want to code a registration system, but the additional security measures should not be overlooked.
About.com’s content is provided by a large group of writers, who each write for a specific topic, ranging from African History to Yoga. According to Alexa4, About.com is ranked as the 64th most visited website on the internet, so you would expect their design team would know a few things about how the internet works. Sadly, when it comes to anonymous online polls, this is not the case.
Every year, About.com run a “Readers’ Choice Awards” competition, where their readers vote in various polls for each topic. The medium for most polls used appears to be a custom-made form, the processing of which is done on an About.com server. The poll I chose to do my analysis on was the “Best Web Design Overall” poll at the About.com Web Design / HTML topic. I thought it a good poll to choose given that at the time it had received relatively few actual votes, and the topic ties in nicely with the security of online polls.
Using Paros (a nifty proxy tool that allows you to view raw HTTP requests / responses), I captured the exact requests sent to the About.com server that were responsible for making a vote (my vote went to the site in last place, which at that point had only 3 votes).
GET http://webdesign.about.com/gi/pages/poll.htm?linkback=http%3A%2F%2Fwebdesign.about.com%2Fb%2F2011%2F02%2F11%2Fvote-for-the-about-com-readers-choice-awards.htm&poll_id=6765141284&poll=4 HTTP/1.1 Host: webdesign.about.com Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Proxy-Connection: keep-alive Referer: http://webdesign.about.com/b/2011/02/11/vote-for-the-about-com-readers-choice-awards.htm Cookie: TMog=B2FKLs2J20kA0972; zFD=B2IPB2F20B20R20B00R02; gs=webdesign; jsc=13; Mint=B2IMZK0U20SA18BF; zBT=0; pc=30; zRf=-2; zFS=B2IB0B20B10B00B01 GET http://guidepolls.about.com/webdesign/6765141284/results.js?linkback=http%3A%2F%2Fwebdesign.about.com%2Fb%2F2011%2F02%2F11%2Fvote-for-the-about-com-readers-choice-awards.htm&poll_id=6765141284&poll=4 HTTP/1.1 Host: guidepolls.about.com Accept: */* Accept-Language: en-us,en;q=0.5 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Proxy-Connection: keep-alive Referer: http://webdesign.about.com/gi/pages/poll.htm?linkback=http%3A%2F%2Fwebdesign.about.com%2Fb%2F2011%2F02%2F11%2Fvote-for-the-about-com-readers-choice-awards.htm&poll_id=6765141284&poll=4 Cookie: TMog=B2FKLs2J20kA0972; zFD=B2IPB2F20B20R20B00R02; gs=webdesign; jsc=13; Mint=B2IMZK0U20SA18BF; zBT=0; pc=30; zRf=-2
For security reasons I have removed the User Agent information from the two HTTP requests above.
Knowing that the poll used a GET request, and that I could not simply manipulate the poll by sending multiple requests from the same IP address, I set up a fake HTML image tag in the footer of a website I run. The URL of the image would be the voting URL for my chosen poll option (i.e. the one in the second request above), and I added some custom CSS to the image that would hide it from view, so that no browser would show a missing image icon and draw attention to the code. The resultant code looked like this:
This type of exploit is known as a Cross-Site Request Forgery (CSRF/XSRF), and once embedded within the website footer, it was only a matter of time before site visitors would load the page and get their browser to (unknowingly) send a vote to the About.com server. The vote would be from their IP address, and would go completely unnoticed to most web users. Sure enough, after a few minutes, the poll results had gone from this:
With the exploit working, and the site “Fido” in the lead, I removed the malicious code from my site. I refrained from posting this blog post until the official About.com voting period was over, and the results were announced (in the end, Google won).