Энтропия в CSRF токенах и одноразовых номерах - PullRequest
2 голосов
/ 21 марта 2012

Я делаю сайт объявлений с Zend Framework (да, я знаю, что в мире нет места для "еще одного клона Craigslist").Я пытаюсь реализовать возможность публиковать / редактировать / удалять без необходимости в учетной записи.

Чтобы сделать это, я чувствую, что мне нужно создать одноразовый номер после отправки и сохранить в базе данных.Затем отправьте по электронной почте ссылку на пользователя, который отправляет GET-запрос на удаление, например:

http://www.somesite.com/post/delete/?id=123&nonce=2JDXS93JFKS8204HJTHSLDH230945HSLDF

Только у пользователя есть этот уникальный ключ или одноразовый номер,и после отправки я проверяю базу данных под идентификатором сообщения и проверяю соответствие одноразовых номеров перед удалением.

Моя проблема заключается в том, насколько безопасным является одноразовый номер.Если я использую Zend Framework Zend_Form_Element_Hash, он создает хеш следующим образом:

protected function _generateHash()
{
    $this->_hash = md5(
        mt_rand(1,1000000) 
        .  $this->getSalt() 
        .  $this->getName() 
        .  mt_rand(1,1000000)
    );
    $this->setValue($this->_hash);
}

Читая о mt_rand (), один комментатор сказал" Эта функция имеет ограниченную энтрофиюТаким образом, если вы хотите создать случайную строку, она выдаст только около 2 миллиардов различных строк, независимо от длины строки. Это может быть серьезной проблемой безопасности, если вы используете такие строки для идентификаторов сеансов, паролей и т. Д."

Из-за срока действия одноразового номера / токена в приложении, который может занять несколько дней или недель, прежде чем пользователь решит удалить сообщение, я думаю, что для потенциального взлома будет выделено более чем достаточно времени.

Я понимаю, mt_rand() - это огромное улучшение с rand(), как видно на , это визуальное отображение пикселей с rand слева и mt_rand справа.Но достаточно ли этого?Что делает « 2 миллиарда различных строк » проблемой безопасности?

И, в конечном счете, как я могу увеличить энтропию для nonce / token / hash?

Ответы [ 2 ]

1 голос
/ 21 марта 2012

Код Zend, генерирующий код, указанный выше для функции хеширования md5 (), имеет 1 000 000 X 1 000 000 различных возможностей.md5 () имеет 32 ^ 16 (1208925819614629174706176) возможных результатов независимо от того, что ввод.В среднем хакеру потребуется отправить 500 000 000 000 запросов на ваш сервер, чтобы угадать правильный одноразовый номер.

При 100 запросах в минуту это около 3472222 дней на взлом.

1 голос
/ 21 марта 2012

Для такой безопасности важно не только то, как долго ваш вывод. Он подсчитывает, сколько случайности вы использовали для его создания.

Для mt_rand() источником случайности является ее начальное число и состояние (количество раз, когда вы использовали его с момента посева). Более mt_rand() вызовы просто дадут вам больше повторения одного и того же источника случайности (без новой энтропии).

mt_rand() семя только 32-битное (что-либо меньше 128-битного делает криптографов подозрительным;)

Сила ключей с 32-разрядной энтропией составляет 4 миллиарда, деленных на (примерно) количество ключей, которые вы сгенерируете (например, после использования 100 КБ будет ~ 1: 43000 шансов угадать любой действительный ключ, что приближается к практическому) скотина форсирования).

Вы добавляете соль к этому, что делает ее намного сильнее, потому что в дополнение к предположению, злоумышленник также должен знать соль, так что если соль длинная, то в целом ключ может быть довольно сильным, несмотря на то, что "низкая" энтропия.

Чтобы увеличить энтропию, вам нужно добавить больше случайных вещей (даже немного случайных - тоже хорошо, просто дает меньше битов) из разных источников, чем mt_rand: microtime(), объем используемой памяти, идентификатор процесса ... или просто использовать /dev/random, который собирает всю энтропию, которую он может получить.

(правка: uniqid () имеет слабую энтропию, поэтому здесь это не поможет)

...