Intereting Posts
Запрос разрешения с использованием нового PHP SDK (3.XX) Как я могу предотвратить зависание curl_multi_select от osx? преобразованный html в php wordpress footer css не работает Преобразование ключей массива / дерева объектов в нижний регистр fullcalendar: есть способ вызвать dayRender только после того, как я загружу свои события через функцию событий Использование автозагрузки Composer Дефисы в ключах объекта Передача двух разных форм с внешней кнопкой отправки не работает должным образом генерировать список дат между двумя датами и списком сохранения в базе данных Список Ajax-функций как передать идентификатор в контроллере из действия формы с помощью codeigniter Возвращенный JSONObject всегда равен нулю. Я не могу использовать для предотвращения дублирования имен Artisan, создание таблиц в базе данных Исключить исключение «com_exception» с сообщением «<b> Источник: </ b> Microsoft Office Excel <br/>

Защищен паролем password_verify () от чрезвычайно длинных паролей (DoS-атака)?

Общий сценарий атаки:

В 2013 году у Django была общая уязвимость, так как злоумышленник мог создавать чрезвычайно интенсивные вычисления CPU с помощью очень больших паролей ( см. Здесь уведомление о безопасности ). Я не уверен, что это возможно при использовании PHP password_verify () и других методов хеширования пароля без каких-либо дополнительных проверок.

Документация PHP говорит:

Использование параметра PASSWORD_BCRYPT для параметра algo приведет к усечению параметра пароля до максимальной длины 72 символа.

Но, код PHP MAYBE говорит что-то другое:

Однако код C за функцией password_verify () PHP 5.5.0 не ограничивает переданный аргумент напрямую (возможно, на более глубоком уровне внутри алгоритма bcrypt?). Кроме того, реализация PHP не ограничивает аргумент.

Вопрос:

Является ли password_verify () (и другие функции одного и того же набора функций) уязвимыми для DoS с помощью максимальных параметров POST? Также рассмотрите конфигурационные ситуации на уровне сайта в размерах загрузки POST, значительно превышающих 4 МБ.

Пароль ограничен 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 символа ключа. Больше не надо.

Заметка

Теперь есть интересный побочный эффект для этого алгоритма. Поскольку он использует C-Strings (строки, завершенные нулевым байтом \0 ), невозможно использовать что-либо в прошлом \0 . Таким образом, пароль, содержащий нулевой байт, теряет любую энтропию. Пример: http://3v4l.org/Y6onV