Exploit: PHPCaptcha / Securimage is not secure.

Published on by

Recently I discovered an easy way to bypass PHPCaptcha also known as SecurImage. The method described below will break the CAPTCHA every time, without fail and affects versions 1.0.4 and above. Previous versions are also probably vulnerable tho only exploit code for the MP3 file format (implemented as default since version 2.0.0) is provided.

The flaw in the CAPTCHA stems from the way MP3 and WAV audio codes, intended for use by by the visually impaired, are generated. It is worth noting that even when the user of the site has removed the audio functionality from their displayed CAPTCHA the functionality can still be accessed via forceful browsing to the file called "/securimage_play.php". This means that unless the administrator of the site has removed the securimage_play.php file that their site is vulnerable to attack.

The audio codes that are generated by PHPCaptcha are created by concatenating a set of audio files (that are publicly accessible in /audio directory). To prevent simple binary analysis of the output the author randomly changes the value of every 64th byte in the generated audio file starting from an initial offset that is also defined by a random integer in the range 1-64. The effect of the mutation means that when you listen to the audio its very hard to determine what letters are being heard. The code used for the mutation is shown below:

function scrambleAudioData(&$data, $format)
{
    if ($format == 'wav') {
        $start = strpos($data, 'data') + 4;
        if ($start === false) $start = 44; 
    } else { // mp3
        $start = 4;
    }

    $start  += rand(1, 64); 
    $datalen = strlen($data) - $start - 256;

    for ($i = $start; $i < $datalen; $i += 64) {
        $ch = ord($data{$i});
        if ($ch < 9 || $ch > 119) continue;

        $data{$i} = chr($ch + rand(-8, 8));
    }
    }

While this prevents simple binary analysis of the generated audio it does not prevent an attacker from building a list of 64 byte strings from the publicly accessible audio samples and using these in comparison against the concatenated audio file. By determining where in the file these strings occur its possible to decode the CAPTCHA with a 100% success rate. The decision by the author to change only the 64th byte of the final audio file is a fatal design flaw.

You can download the PHPCaptcha exploit capable of decoding the MP3 CAPTCHA format. It is currently configured to run against the "sample_form.php" script that comes by default with SecurImage / PHPCaptcha. Below is a video of the exploit running:

No fix is currently available from the author. The only current solution is to remove the securimage_play.php script from your site.