PHP:保护会话变量/验证码的任何方法?

时间:2012-06-28 00:43:39

标签: php security session post captcha

我做了一些图片验证。用户必须从动态生成的图像中输入代码。

此代码正在主php文件中使用:

@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;

请注意:

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

这就是我调用生成的图像的方式。这就是它的内容:

<?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);
}
?>

注意:

$_SESSION['result'] = $pass;

这是我在会话中存储密钥的方式。

现在,问题是,图像可能被阻止,会话密钥不会从上次存储的结果发生变化。这意味着巨大的威胁。我想知道是否有任何保护或解决办法?

请仅在您了解问题和安全性时回答: - )

2 个答案:

答案 0 :(得分:1)

您应该更关心缓存而不是被阻止的请求。在包含一些Cache-Control标题等之前,可能无法刷新背景图像。

更重要的是防止重播。为此,您应该:

  • 时间戳值。并使验证码验证拒绝接受较旧的值。

  • 在一次或两次成功验证后清除验证码会话状态。

未加载(“阻止”)背景图像只表示您在会话存储中没有有效的令牌。这不是问题,除非你的验证逻辑设计得很糟糕。

最后,验证码的有效性不会随着图像中的随机线条而增加。它与你的表单结构一样有效。一旦蜘蛛适应您的自定义变体,它就很容易规避。虚假的安全在于它的默默无闻。虽然没有这么好的学习经验,但建议使用现成的验证码脚本。

答案 1 :(得分:0)

除了存储结果外,为什么不存储时间戳。这样,您可以在十分钟内使结果到期。

还在部分中放置了一些代码,用于验证表单中的提交以清除该会话变量,无论它是否成功。这样,如果他们想再次提交,他们将需要输入新的结果。