Shell Scripting Online Contests

For my more technical readers, stick with me here while I provide a bit of background, or jump ahead to the technical stuff.

Meet Colt

Colt
Colt is shelter dog at the Humane Society for Hamilton County in Noblesville, Indiana. He is deaf but has learned sign language for all his basic commands. He is a great dog who has found himself homeless like thousands of others. Is he not both the cutest and coolest dog you’ve never met?

The Contest

Hallmark Hall of Fame is holding a contest to find the “cutest dog of the season” as part of their promotion for their upcoming movie, “a Dog Named Christmas.” The winner of the contest receives a $1000 cash prize PLUS a $1000 donation to their favorite animal charity. As Colt’s owner is an animal charity, him winning would result in $2000 going to the Humane Society for Hamilton County, IN.

The Situation

Yesterday I got an email encouraging me to support Colt in the contest (to view this link you must create an account and log in, or use the username and password I created: thisisatest/password). Not being able to resist that face of his, I decided to do everything I could to make sure he was noticed.

The Problem

But there are so many dogs! The signal to noise ratio makes it where there is almost no chance for any one dog to run away with the voting, but somehow, there were a few. Knowing immediately what was happening, that the leading dogs were all running scripts, I decided to move Colt to the front page to put him in front of as many eyes as possible.

The Technical Solution

This is where things start getting a little bit gray. I wrote a script to automatically and continuously vote for Colt. I’m not proud of what I did, but know that I did so with only the best intentions. If you’re not a technical person, you may want to resume reading where I discuss making things right.

Taking a quick look at their voting page you can see this chunk of code:

<div id="dog-vote-link-8068-container" class="dog-vote-link"><a id='dog-vote-link-8068' href='/vote/8068/21770/e158e2a0b631ca319a361addabe1dab4/1259213400/full' class='dog-vote-link'><img id='dog-vote-link-8068-img' src='/sites/all/themes/adnc/images/btn-vote.png' title='Vote Now' alt='Vote for This Pooch' width='456' height='252'/></a></div>

The contest uses jQuery to hijack that link and make a simple request for the same. Super-easy, all I have to do is set up a script to repeatedly request that URL. Well, not quite. The URL changes on each page request, so I would at least have to make a request and parse that page before I could vote. As it would turn out, that was the only roadblock I faced because it is the only protection mechanism the site implemented, and so Colt was off to the front page. The simplified code to vote for Colt looks something like this:


#!/bin/bash
for i in {1..2000}
do
DOG=$(curl --silent http://hhofdogcontest.com/dogs/colt-nov-23 | grep "a id='dog-vote-link" | cut -c 98-159 | sed "s/\'/http:\/\/hhofdogcontest.com/")
curl --silent -O "$DOG"
echo "$i of 2000"
done

How to Create a More Secure Contest

Simply stating the attack only covers a third of topic. There is also the discussion of the problem space and proposing solutions to help prevent this from being a problem in the future.

This problem space falls into the same as spam, meaning there is no easy solution. The typical solution to spam is a captcha, with the goal being to verify the humanity of the person on the other end of the connection. However, in this scenario, we’re not only trying to verify the humanity of the requester, but also the uniqueness. Note that you do not have to log in to vote for the dogs that haven’t been unpublished.

There is a fine line that must be walked and the best solution probably requires integrating an external trusted-but-verified network, like Facebook. This type of contest is a prime example of a way in which either Facebook Connect or the Facebook App Platform could have been used to better meet their goals.

If you don’t wish to involve such an outside network, you could also go with a more old-fashioned approach:

  1. Require completion of a captcha for all votes (either in a registration process or per vote).
  2. Only allow one vote per IP address.

This is less optimal, but will still reduce the problem to only those with intentions to create trouble. Proxies and a mechanical turk setup for captcha solving can certainly still result in gaming the system, but the investment is much higher than spending 5 minutes writing a script.

A More Devious Plot

As you can see, there are a lot of problems with the current setup, but there is also a problem with the way in which Hallmark Hall of Fame has responded. They have simply removed the profiles of dogs who appear to have received votes that are illegitimate. With only a few minor modifications the above script could take a scorched earth approach and vote for all of the highest rated dogs, hoping to cause Hallmark Hall of Fame to remove them from the contest. This could also accomplish the goals of a fraudster without ever specifically identifying the perpetrator.

Getting It Right

If Hallmark can implement either of the solutions I proposed above they can restore some legitimacy to this contest. As it stands, there is absolutely no trusting the vote totals. To make it fair to all, they should consider completely resetting the vote totals for all of the dogs to zero and begin anew with a more secure process.

Fixing What I Broke

If you went to view Colt’s contest profile you probably noticed “UNPUBLISHED” printed in huge letters on the page. As a result of what I’ve done, the contest organizers have pulled down his page. It should be noted that I would benefit in no way whatsoever from Colt winning this prize and I was simply trying to help the Humane Society for Hamilton County, IN.

I encourage you to send email to the people behind the contest urging them to reconsider. To make it easy, I’ve drafted some text that you can use as a starting point:

Penance

First, Hallmark Hall of Fame, I do freelance web development and have experience with Drupal. I am happy to assist in implementing either a Facebook Connect or one-off solution to your spam problem at no cost.

Second, in the event that the approach to this contest is resolved with a solution I am comfortable with (detailed above), I will match any dollars from the grand prize donation that go to an animal-related charity up to a maximum of the $2000 cash prize value.

Conclusion

I encourage everybody to go visit the Humane Society for Hamilton County, IN to donate as they are able.