Reputation: 4630
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 :-)
Upvotes: 0
Views: 550
Reputation: 1954
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.
Upvotes: 0
Reputation: 145492
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.
Upvotes: 1