Make PHP CAPTCHA more secure

January 05, 2012

In the past we posted PHP code to generate CAPTCHA, and here is a small fix to the code that will make it more secure.

Here is the link to previous post: http://superiorwebsys.com/55-how-to-create-captcha-using-php/

In new code we encrypt session with md5 and also we use md5 for the numbers that user entered.

 

Here is source of secureImage.php:

<?
session_start
();
header("Content-type: image/png");
$_SESSION["secureNumber"]="";
//Size of the image Width, Height
$im imagecreate(10520);        
//Set background color
imagecolorallocate($im167218239); 
$grey imagecolorallocate($im128128128);
$black imagecolorallocate($im000);        
// You can replace fornt by your own
$font 'LHANDW.TTF';        
$sessionString="";
for(
$i=0;$i<=5;$i++) {
    
$numb=rand(09);
    
$sessionString.=$numb;
    
$angle=rand(-2525);
    
imagettftext($im9$angle8+15*$i13$black$font$numb);    
    
// Add shadow to the text    
    
imagettftext($im9$angle9+15*$i14$grey$font$numb);    
}
$_SESSION["secureNumber"]=md5($sessionString);
imagepng($im);
imagedestroy($im);
?>

How to use this code

1. Display CAPTCHA and input field

<table border="0" cellpadding="0" cellspacing="0">
<tr>
    <td valign="top"><input name="secretNumber"  value="" maxlength="6" /></td>
    <td valign="bottom">
        <img src="/blog/posts/55/secureImage.php" alt="CAPTCHA" />
    </td>
</tr>
</table>

2. Check if correct number was entered

<?
if(!empty($_POST["secretNumber"]) &&
    
$_SESSION["secureNumber"]==
md5($_POST["secretNumber"]))
{
    
//Correct number is entered
}
{
    
//Display error message
}
?>

 

 

Problem with previous code was that we saved unencrypted captcha in the sessions are accessible on the computers in cookies files, so bot had to open up the page, then look into session file to get captcha value and input it into the form, instead of reading the image.

This is not 100% fix, because there are databases of md5 strings where you can enter md5 output and will get initial string. In case md5 does not work for you, and you still get spam you can use PHP mcrypt_ecb() and save key in file or DB. If you want us to post this code, please leave a response in comments below.