Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I've made some image validation. The user has to enter the code from the dynamically generated image.

This code is being used in the main php file:

@session_start();
if (isset($_POST['session_pw'])&&$_SESSION['result']==$_POST['security_im']) {
    $_SESSION['pw']=$_POST['session_pw'];
    $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
}
if ($_SESSION['pw']=='mypassword'&&$_SESSION['ip'] == $_SERVER['REMOTE_ADDR']){

        // OK we are in.
    // Otherwise display a login form:
}else echo <<<EOD
    <form method="POST">
    <font color="blue"> Authorization is required:</font><br>
    <input type="text" name="security_im" style="text-align:right;padding-right:1px;background-repeat:no-repeat;background-image:url(../imagecheck.php)"><br>
    <input type="password" name="session_pw" style="text-align:right;padding-right:1px"><br>
    <input type="submit" style="margin:0px">
    </form>
EOD;

Note this:

background-image:url(../imagecheck.php)

This is how I call the generated image. And this is it's content:

<?php
session_start();
create_image();
exit();

function create_image() {
    $md5 = "";
    while (strlen($md5) == 0) {
        $md5 = md5(mt_rand());
        $md5 = preg_replace('/[^0-9]/', '', $md5);
    }
    $pass = substr($md5, 10, 5);
    $_SESSION['result'] = $pass;
    $width = 60;
    $height = 20;
    $image = ImageCreate($width, $height);

    //We are making three colors, white, black and gray
    $clr[1] = ImageColorAllocate($image, 204, 0, 204);
    $clr[2] = ImageColorAllocate($image, 0, 204, 204);
    $clr[3] = ImageColorAllocate($image, 204, 204, 0);

    $R = rand(1, 3);
    $black = ImageColorAllocate($image, 255, 255, 255);
    $grey = ImageColorAllocate($image, 204, 204, 204);

    //Make the background black
    ImageFill($image, 0, 0, $black);

    //Add randomly generated string in white to the image
    ImageString($image, 5, 7, 2, $pass, $clr[$R]);

    //Throw in some lines to make it a little bit harder for any bots to break
    imageline($image, 0, 0, $width - 2, $height - 2, $grey);
    imageline($image, 0, $height - 2, $width - 2, 0, $grey);
    ImageRectangle($image, 0, 0, $width - 1, $height - 1, $grey);

    //Tell the browser what kind of file is come in
    header("Content-Type: image/jpeg");
    //Output the newly created image in jpeg format
    ImageJpeg($image, null, 80);
    //Free up resources
    ImageDestroy($image);
}
?>

Note:

$_SESSION['result'] = $pass;

This is how I store key in the session.

Now, the problem is, the image can be potentially blocked, and the session key will not change from the last stored result. This means a huge threat. I wonder if there any protection or workaround possible?

Please answer only if you understand the question and security :-)

share|improve this question
Captchas aren't "security" features. They're behaviour or permission logic. – mario Jun 28 '12 at 0:49
Are you using a captcha on every page? And if the image is blocked,they won't be able to verify the captcha. If the session key is the same after serving the image, you know it's been blocked. And what if they have images turned off? or someone steals the image? – Anthony Jun 28 '12 at 1:04

2 Answers

up vote 1 down vote accepted

You should be more concerned about caching than about blocked requests. Background images might not be refreshed until you include some Cache-Control headers etc.

What's more important is to prevent replays. To do so, you should have:

  • A timestamp value. And make the captcha validation refuse to accept older values.

  • Clear the captcha session state after one or two successful validations.

The background image not being loaded ("blocked") just means you won't have a valid token in the session store to begin with. That's not a problem, unless your verification logic is badly designed.

Lastly, the effectiveness of your captcha doesn't increase with random lines in the image. It's just as effective as uncommon your form structure is. Once a spider adapts to your custom variation, it's pretty simple to circumvent. The faux security lies in its obscurity. While not such a great learning experience, a readymade captcha script might be advisable.

share|improve this answer

Besides storing a result, why not also store a time stamp. That way, you can expire the result in maybe ten minutes.

Also put some codes in the part that validate the submission from the form to clear that session variable regardless of whether it is successful or not. That way, if they want to submit again they will need to enter the new result.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.