Wednesday, April 7, 2010

Online Competitions: Fail by design voting system

These days we are seeing more and more online competitions that involve some sort of e-voting for the participants. If you're planning to have one, there is only one advice I would like to give; don't do anything client side if you're planning to have some sort of protection against possible abuse.

Recently, there was this competition which a friend of mine took part. On the website, you can vote as many times as you would like as there is no registration needed, but you can only vote once every 1 hour.

Out of curiosity, I decided to figure out how their voting system works.

To my surprise, I found out that the mechanism the website is using to stop people from cheating is based on the information provided by the bwowser.



POST /entry/vote.asmx/VoteForMe HTTP/1.1
Host: example.example.com
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT) Version/4.0.2 Safari/530.19
Content-Type: application/json; charset=utf-8
Referer: http://example.example.com/entry/Users/Kitty_Girl/Default.aspx?UserId=315
Origin: http://example.example.com
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Cookie: __utma=156400292.896968250.1270549747.1270671468.1270678496.15; __utmb=156400292.2.10.1270678496; __utmc=156400292; __utmz=156400292.1270549747.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); ASP.NET_SessionId=kghh0yvgbd35m055wfm0cq55
Content-Length: 42
Connection: keep-alive

{"UserId":"315","UserIp":"122.19.21.47"}



HTTP/1.1 200 OK
Date: Wed, 07 Apr 2010 22:15:58 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Content-Length: 33

{"d":"Thank you for your vote #1957"}




So it's getting the IP of the client to check if the user has voted before, this is very easy to bypass with something like this:


from random import randint

def randip():
return str(randint(1, 250)) + '.' + str(randint(1, 254)) + '.' + str(randint(1, 254)) + '.' + str(randint(1, 254))




Of course this code can be improved further.

In conclusion, while this will stop many people from abusing the system, it's still a bad anti-cheating mechanism. Web developers are not security experts excuse, anyone?

0 comments: