Wednesday, 15 December 2010

cformsII CAPTCHA Bypass Vulnerability

The cformsII plugin for WordPress contains a vulnerability within its Captcha Verification functionality. This vulnerability exists due to an inherent trust of user controlled input. An attacker could utilise this vulnerability to completely bypass the captcha security mechanism on any wordpress forms created with this plugin.

Captcha Generation:
CformsII generates it's captcha by randomly selecting characters from a character set of ak,m,n,p-z2-9. I assume that the letters l and o, and the numerals 1 and 0 were excluded to avoid any confusion when rendered as an image. It selects a random number of these characters based on preset minimum and maximum limits, and assembles a string of them. It then creates an md5 hash of this string, prepends 'i+' to the hash and sets it as a cookie called 'turing_string_'. See the below code excerpts:
$min = prep( $_REQUEST['c1'],4 );
$max = prep( $_REQUEST['c2'],5 );
$src = prep( $_REQUEST['ac'], 'abcdefghijkmnpqrstuvwxyz23456789');

### captcha random code
$srclen = strlen($src)-1;
$length = mt_rand($min,$max);

$turing = '';
for($i=0; $i<$length; $i++)
$turing .= substr($src, mt_rand(0, $srclen), 1);

$tu = ($_REQUEST['i']=='i')?strtolower($turing):$turing;

setcookie('turing_string_'.$no, $_REQUEST['i'].'+'.md5($tu),(time()+60*60*5),"/");

This cookie is set when the user is presented with generated captcha image. When they submit their completed form, the capctha code is submitted in a POST parameter titled 'cforms_captcha'. This parameter is then md5'd and compared to the md5 value from the turing_string_ cookie. If the two hashes match, then it is considered to be valid.

else if( $field_type == 'captcha' ){  ### captcha verification

         $validations[$i+$off] = 1;

$a = explode('+',$_COOKIE['turing_string_'.$no]);

$a = $a[1];
$b = md5( ($captchaopt['i'] == 'i')?strtolower($_REQUEST['cforms_captcha'.$no]):$_REQUEST['cforms_captcha'.$no]);

if ( $a <> $b ) {
$validations[$i+$off] = 0;
$err = !($err)?2:$err;


The end result is that an attacker could pre-set a 'valid' captcha string. They then get the md5 hash of the string, and prepend “i%2b” (url encoded 'i+') to the value and set that as the turing_string_ cookie for their post requests. Every request set with this parameter and cookie combination will be inherently trusted as valid from the Captcha standpoint.

The problem here is two fold. The first issue, is that the captcha codes are not one time use codes, as they should be. So even without tricking the Captcha system in the first place, it would be possible to launch  a replay attack against this system to generate large amounts of submissions. Each captcha code should only be valid for one use and only during a very limited time window.

The second problem is the trust of user supplied data. The process is meant to create a validation of entered data against another piece of data. However both sets of data are freely offered up to the client-side for tampering. This completely negates the verification process as the server side is not truly in control of the validation at this point.

The take-away:
using cookies to store captcha data then comparing against user supplied input is not an appropriate method of validation for a number of reasons. The captcha code, whether in raw form or hashed should be stored server side for validation, should be valid for only one use, and should be valid only for a limited timeframe. This could be done by using an in-memory array, a database, or even a flatfile.


  1. Because we are a captcha business, I came across this post. We are a start-up and would like to hear your thoughts on the security of our solution.

  2. dont work, shit

  3. Nice blog & captcha coding...... Excellent coding.. very useful... Thank you!...

    captcha solver

  4. Wow!... superb blog... Really nice... Superb color theme... nice coding for captcha verification... Thank you!!...

    Captcha Bypass