即使只有密码部分正确,是否可以登录?

时间:2013-08-03 15:27:55

标签: php login hash salt bcrypt

我在登录表单上偶然发现了问题。当密码部分正确时,我似乎能够登录。

如果我创建以下用户:

用户名:hehehehehe

密码:呵呵呵呵呵

我可以使用“hehehehe”,“hehehehehe11111”等密码登录。如果我写错了,它就行不通。

的login.php

if (empty($_POST) === false) {

$username = trim($_POST['username']);
$password = trim($_POST['password']);

if (empty($username) === true || empty($password) === true) {
    $errors[] = 'Sorry, but we need your username and password.';
} else if ($users->user_exists($username) === false) {
    $errors[] = 'Sorry that username doesn\'t exists.';
// } else if ($users->email_confirmed($username) === false) {
    // $errors[] = 'Sorry, but you need to activate your account. 
                 // Please check your email.';

} else {
    if (strlen($password) > 18) {
        $errors[] = 'The password should be less than 18 characters, without spacing.';
    }
    $login = $users->login($username, $password);
    if ($login === false) {
        $errors[] = 'Sorry, that username/password is invalid';
    }else {
        $_SESSION['id'] =  $login;
        header('Location: home.php');
        exit();
    }
}

}

User.class.php

public function login($username, $password) {

    global $bcrypt;

    $query = $this->db->prepare("SELECT `password`, `user_id` FROM `users` WHERE `username` = ?");
    $query->bindValue(1, $username);

    try{

        $query->execute();
        $data               = $query->fetch();
        $stored_password    = $data['password']; 
        $id                 = $data['user_id']; 

        if($bcrypt->verify($password, $stored_password) === true){ 
            return $id;
        }else{
            return false;   
        }

    }catch(PDOException $e){
        die($e->getMessage());
    }

}

Bcrypt.class.php

class Bcrypt {
private $rounds;
public function __construct($rounds = 12) {
    if(CRYPT_BLOWFISH != 1) {
        throw new Exception("Bcrypt is not supported on this server, please see the following to learn more: http://php.net/crypt");
    }
    $this->rounds = $rounds;
}

private function genSalt() {

    $string = str_shuffle(mt_rand());
    $salt   = uniqid($string ,true);

    return $salt;
}


public function genHash($password) {

    $hash = crypt($password, '$2y$' . $this->rounds . '$' . $this->genSalt());
    return $hash;
}


public function verify($password, $existingHash) {

    $hash = crypt($password, $existingHash);


    if($hash === $existingHash) {
        return true;
    } else {
        return false;
    }
}

}

有什么想法吗?

如果你们认为它可以处理注册过程,请告诉我,我也会上传注册码。我无法弄清楚的是,即使密码的一部分是正确的,为什么它仍然有效,我以前从未体验过。

1 个答案:

答案 0 :(得分:1)

似乎地穴使用DES进行哈希而不是河豚: http://php.net/manual/en/function.crypt.php

  

标准的基于DES的crypt()返回salt作为输出的前两个字符。它也只使用str的前八个字符,所以较长的字符串以相同的八个字符开头将产生相同的结果(当使用相同的盐时)。

尝试使用您的代码仅使用前8个字符登录。

另请查看存储在数据库中的已保存哈希值,以查看它们是否正在使用blowfish或DES。如果使用河豚,他们应该使用$ 2y $签名。