« Energy screen The Valley Song »

Rigging a http://stuff.co.nz/ poll

Posted by Simon Welsh | 29 September 2009 | Comments (2)

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.

Trackbacks

None
Trackback URL: http://simon.geek.nz/Trackbacks/add/1161

Post your comment

Sign in with Twitter

Comments

  • 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 (6 months ago)

RSS feed for comments on this page | RSS feed for all comments