PHP的Password_VATEY()对超长密码(DoS攻击)安全吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (12)

一般攻击情景:

在2013年,Django存在一个普遍的漏洞,因为攻击者可能通过非常大的密码创建非常强大的CPU计算。我不确定在使用PHP的password_verify()和其他密码散列方法时没有进一步检查,这是否仍然可行。

PHP文档说:

使用PASSWORD_BCRYPT作为algo参数,将导致密码参数被截断,最大长度为72个字符。

但是,PHP的代码MAYBE说了一些不同的东西:

PHP 5.5.0的password_verify()函数背后的C代码并不直接限制传递的参数(可能在bcrypt算法的更深层次上?)。另外,PHP实现不会限制参数。

问题是:

是否password_verify()(和其他功能集相同的功能)通过最大化POST参数来抵御DoS?请考虑POST上传大小大于4MB的站点范围配置情况。

提问于
用户回答回答于

密码算法内部的密码限制为72个字符。

要明白为什么,让我们来看看它crypt()的来源:http : //lxr.php.net/xref/PHP_TRUNK/ext/standard/crypt.c#202

    } else if (
            salt[0] == '$' &&
            salt[1] == '2' &&
            salt[3] == '$') {
        char output[PHP_MAX_SALT_LEN + 1];

        memset(output, 0, PHP_MAX_SALT_LEN + 1);

        crypt_res = php_crypt_blowfish_rn(password, salt, output, sizeof(output));
        if (!crypt_res) {
            ZEND_SECURE_ZERO(output, PHP_MAX_SALT_LEN + 1);
            return NULL;
        } else {
            result = zend_string_init(output, strlen(output), 0);
            ZEND_SECURE_ZERO(output, PHP_MAX_SALT_LEN + 1);
            return result;
        }

password领域是一个简单的char*领域。所以没有长度信息。所有这一切都是一个普通的指针。

所以如果我们遵循这一点,我们最终会落地BC_set_key

重要的部分是循环:

for (i = 0; i < BF_N + 2; i++) {
    tmp[0] = tmp[1] = 0;
    for (j = 0; j < 4; j++) {
        tmp[0] <<= 8;
        tmp[0] |= (unsigned char)*ptr; /* correct */
        tmp[1] <<= 8;
        tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */

        if (j)
            sign |= tmp[1] & 0x80;
        if (!*ptr)
            ptr = key;
        else
            ptr++;
    }
    diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */

    expanded[i] = tmp[bug];
    initial[i] = BF_init_state.P[i] ^ tmp[bug];
}

BF_N被定义为16.所以外层循环将循环18次(BF_N + 2)。

内循环将循环4次。4 * 18 == 72。

在那里,只有72个字符的密钥会被读取。不再。

扫码关注云+社区