Using Polldaddy hacks to give yourself free votes in Polldaddy polls

As many of you know, RustyBrick had a Halloween contest and a PollDaddy poll was set up in order to vote for the winner. It was going to be a tough race. First of all, Mabe had an outstanding satyr costume. Both Jimmy and Joe submitted adorable shots of their children all dressed up. Heck, even the ellusive Andy wore a costume! So, how could I possibly compete with race car drivers, hot satyrs and cute kids? By cheating!

I did ask permission with Barry first who informed me that "anything goes". Seeing this as a fun little challenge, I looked at the poll on the blog page and began the peel away at the edges to unlock the heart of the poll so I could bend it to my will.

**NOTE: There's computer-programming talk below. But DON'T PANIC. I made it super easy to follow, even for a computer newbie. Keep reading and I guarantee no matter what your skill level is, you'll learn something***

Well, the poll was run by PollDaddy, a popular online poll service. The widget on the blog is a bit confusing because it's coded a bit funny to make up for the fact that it's not running off it's "home" website. Because of this fact, it's compressed and weird. So, instead of delving into the code on the blog, I figured there has to be an original version on "homepage" of the code back at the PollDaddy page. I used Firebug, a Firefox extension to look through the source revealed a NOSCRIPT tag used to provide a link for users without Javascript enabled.

 Finding the URL of Polldaddy

 

Voila! We can now go straight to the PollDaddy poll here! OK, so we see a big form with all the entries. To vote, you click on the radio button and then click the big green vote button. Time to crack this baby open and see how she runs. Back to Firebug to inspect the radio button next to my name. The radio button appears to have a "name" of PDI_answer, an "id" of PDI_answer10761055 and a "value" of 10761055. So, based on this information, I am going to make the assumption that 10761055 is my unique identifier. This means that when you submit the form with me selected, it takes the value 10761055 and sends it to the code that processes the vote. Sure enough, all the other entries had values increasing incrementally. (Meaning that the next entry down [Andy] had a value of 10761056, Jimmy had a value of 10761057 and so on.)

 Grabbing Polldaddy Ids

 

Cool, now it's time to try and see if we can figure out what other data is passed to the code processor to create a "vote". The next step I did was look for the FORM tag to see if I could find secret variables sent to the code processor passed as hidden INPUT's. Instead of looking through the code, I used the powerful Firefox extension Web Developer Toolbar and ran the "Display Form Details" tool. This displayed all the details of every FORM on the page. The first FORM was the little Search form on the top right. The second FORM was the important voting form. Darn! It only shows the 5 radio buttons... even the action is blank. [The FORM action is the location of the code of the code processor... where the information is sent after you click "vote"]. And our report from Web Developer Toolbar has just given us what we already know...

 Polldaddy Form Analysis

 

OK, not all is lost yet, we can still get a clue by looking at the "Vote" button which submits the form. Aha! The vote "button" isn't even a button at all! It's an image that calls a Javascript function when it's clicked. The function it calls is called "vote" and it passes 5 variables to the vote function. The data it's passing here appears to be 5 numbers. 2189218, 0, 1, 0 and 10.

 Polldaddy Exploit Howto

 

Now, looking at the URL of the poll page, I can tell that the first number is the ID for the poll itself. This is sent so that when the vote is tallied, it'll know which poll to tally it to. OK, now we have to look for the javascript function called "vote". Hopefully, it will help clue us into what the other 4 numbers being passed are all about. Viewing the page source shows that the Javascript function isn't right on the page; it has to be in one of the included Javascript files. Again, the developer toolbar can help us out by going to "Information", then "View Javascrip"t. This features grabs the source of all the included Javascript files. Toolbar shows us that, not only are they non-obfuscated, the function we need to analyze is right in the first included Javascript file, "common.js"!

With the actual function, we can see the variable names being passed. They are id, poll_other, rand, poll_type and u. ID links with the poll and I assume rand is just a random number to prevent spamming. The other ones probably just identify the type of poll (e.g. non-multiple choice, etc.) Looking at the code of the function, we can see how the form is processed and the data is sent to the code processor.

 

function vote(id, poll_other, rand, poll_type, u)
{
var answerString = '';
var otherText = '';

for (i = 0; i < document.formPoll.elements.length; i++)
{
if (document.formPoll.elements[i].type == "checkbox" || document.formPoll.elements[i].type == "radio")
{
if (document.formPoll.elements[i].checked)
{
answerString += document.formPoll.elements[i].value + ',';
}
}
}

if (poll_other == 1)
{
otherText = $('PDI_OtherText').value;
}

if (answerString.length > 0 || otherText.length > 0)
{
location.href = '/vote/?va=' + u + '&pt=' + poll_type + '&r=' + rand + '&p=' + id + '&a=' + answerString + '&o=' + otherText;
}
else
{
alert('Please choose an answer first!');
}
}

The loop between the function whose brackets I highlighted in red go through the form and grab the value of the person you checked (in this case, my unique identifer of 10761055). The function whose brackets in green aren't used in this poll. And lastly, but most importantly, the part in the blue brackets is what sets the page to redirect to the code processor while sending along 6 variables.

 

  • va = "u", the 5th parameter in the vote function = 10
  • pt = "poll_type", the 4th parameter in the vote function = 0
  • r = "rand", the 3rd paramenter in the vote function = 1
  • p = id, the 1st parameter in the vote function = 2189218 [the poll's ID number]
  • a = answerString, the unique identifer of my entry in the poll = 10761055
  • o = otherText = [blank]

So using this data, we can create the way to make out votes. Every time the following URL is accessed, a vote is placed for me in the poll.

http://answers.polldaddy.com/vote/?va=10&pt=0&r=1&p=2189218&a=10761055&o=

We're almost there... so close! Now, PollDaddy put some roadblocks in place to prevent the user from simply refreshing the page and revoting. The main way it does this is by setting a cookie on the user. A cookie is a piece of data stored by a website on your computer. In this case, the cookie says "I already voted in this poll". When you come back and try and vote on the poll again, the website reads your cookie, sees you've already voted and won't let you vote again. Now, there's 2 easy ways to counteract this. The first comes back to the good old Web Developer Toolbar. By going to "Cookies", then "Disable All Cookies". The website will not be able to store its "you already voted" cookie and therefore when you refresh the poll and come back, you can vote again! However, this vote, refresh, vote process is too slow and too boring for me. To truly dominate the poll, I need to create a program that could keep submitting the data for me automatically!

I acheived this using PHP and the built-in cURL library. The cURL library is a very powerful library of codes that help the server running your PHP script communicate with another server (in our case, the PollDaddy server). So, all the code needs to do is just keep sending this data to server over and over again. The code I used to accomplish this is below.

<?

set_time_limit(0);

while(true){

$rand = rand(1,10);
$pollid = "2189218";
$voting_id = "10761055";

$useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://answers.polldaddy.com/vote/?va=10&pt=0&r=".$rand."&p=".$pollid."&a=".$voting_id);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
$res = curl_exec ($ch) ;


curl_close($ch);

sleep(6);
}
?>

This code begins by calling "set_time_limit(0)". This tells the PHP script to ignore the built-in time limit and to run forever. The next part begins a while loop which is deliberately written to loop forever. The next 3 lines set some of the data to be sent including the random number, the poll id and the id of my entry. The next line is used in a attempt to foll PollDaddy into thinking that it's a browser sending this data and not the truth, which is a server PHP script. Then the code sets up a connection to PollDaddy, sends out the data to be tallied and takes a quick 6 second "sleep" break before looping and sending the data again.

Poll Daddy Results

Now, PollDaddy has a system in place to prevent this type of "poll spamming". It tracks all incoming votes based on the unique IP address. And if alot of votes are coming from one IP address all at once, a temporary ban is placed on that IP address and all the questionable votes are deleted. This is why the script is told to sleep for 6 seconds because if you have run in a constantly loop, it will run multiple times every second and in about a minute, you could easily have over a 1,000 votes. This will get you banned very quickly as I soon discovered. When I ran this on the RB server, the whole office was blocked from voting on the poll since all the computers share an IP address. Through trial and error, I found that a 6 second sleep was perfect for getting a maximum amount of votes without being banned. Through the help of Wesley and other friends who had access to servers, we were able to spread the script around and run them all simultaneously. This is what allowed me to rack up 1,000s of votes in less than an hour.

So, there you have it! With a little bit of ingenuity, a lot of technical skill and some luck, it can be quite easy and fun to do some low-grade "hacking". In my case, it can even be profitable!! Thanks for the $50 iTunes gift card Barry, and better luck next time everybody else! tease

Bookmark and Share    
blog comments powered by Disqus