Может ли случайный сон предотвратить временные атаки?

Из Википедии

В криптографии временная атака - это атака по побочному каналу, при которой злоумышленник пытается скомпрометировать криптосистему, анализируя время, необходимое для выполнения криптографических алгоритмов.

На самом деле, чтобы предотвратить временные атаки, я использую следующую функцию, взятую из этот ответ:

function timingSafeCompare($safe, $user) {
    // Prevent issues if string length is 0
    $safe .= chr(0);
    $user .= chr(0);

    $safeLen = strlen($safe);
    $userLen = strlen($user);

    // Set the result to the difference between the lengths
    $result = $safeLen - $userLen;

    // Note that we ALWAYS iterate over the user-supplied length
    // This is to prevent leaking length information
    for ($i = 0; $i < $userLen; $i++) {
        // Using % here is a trick to prevent notices
        // It's safe, since if the lengths are different
        // $result is already non-0
        $result |= (ord($safe[$i % $safeLen]) ^ ord($user[$i]));
    }

    // They are only identical strings if $result is exactly 0...
    return $result === 0;
}

Но я подумал, можно ли предотвратить такую ​​атаку, используя случайный сон, например

function timingSafeCompare($a,$b) {
    sleep(rand(0,100));
    if ($a === $b) {
        return true;
    } else {
        return false;
    }
}

Или, может быть, увеличение случайности сна

sleep(rand(1,10)+rand(1,10)+rand(1,10)+rand(1,10));

Такой подход может полностью предотвратить временные атаки? Или просто усложняют работу?


person DrKey    schedule 08.02.2015    source источник
comment
Просто используйте hash_equals() и закончите.   -  person Scott Arciszewski    schedule 13.02.2015


Ответы (3)


Такой подход может полностью предотвратить временные атаки? Или просто усложняют работу?

Ни один. Это не предотвращает временных атак и не усложняет их.

Чтобы понять, почему, просмотрите документацию по сну. В частности, значение первого параметра:

Время остановки в секундах.

Таким образом, вашему приложению требуется 0,3 секунды, чтобы ответить без сна. Во сне требуется 0,3, 1,3, 2,3 и т. Д.

На самом деле, чтобы получить интересующую нас часть (разницу во времени), нам просто нужно отрезать целую часть:

$real_time = $time - floor($time);

Но давайте сделаем еще один шаг. Допустим, вы спите случайным образом, используя usleep. Это намного более детально. Это спит за микросекунды.

Что ж, измерения ведутся в масштабе 15-50 нано секунды. Таким образом, сон по-прежнему примерно в 100 раз менее детализирован, чем выполняемые измерения. Таким образом, мы можем усреднить до одной микросекунды:

$microseconds = $time * 1000000;
$real_microseconds = $microseconds - floor($microseconds);

И все же есть значимые данные.

Вы можете пойти дальше и использовать time_nanosleep, который может спать с точностью до наносекунды.

Тогда вы можете начать возиться с числами.

Но данные все еще есть. Прелесть случайности в том, что ее можно просто усреднить:

$x = 15 + rand(1, 10000);

Выполните это достаточное количество раз, и вы получите красивый красивый график. Вы скажете, что существует около 10000 различных чисел, так что затем вы можете усреднить случайность и вывести «частные» 15.

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

Итак, вопрос, который я хотел бы задать:

Зачем возиться с хаками, похожими на сон, если вы можете исправить проблему правильно?

person ircmaxell    schedule 12.02.2015
comment
Мне нравится, что я автор сообщения, цитируемого в обоих других ответах, и они получили больше голосов, чем я :-P ... (Просто играю, на самом деле это большая честь) - person ircmaxell; 13.02.2015
comment
Хороший пост в блоге. Может быть, есть какая-то временная атака, которую вы можете использовать, чтобы взломать вопрос и заставить его принять ваш ответ. - person Phil; 13.02.2015
comment
Вы уверены, что они совсем не усложняют их? Вообще? Если одно время ответа составляет в среднем 1 мс, и вы добавляете около 1 секунды случайного сна, по крайней мере, теперь злоумышленник должен ждать в тысячу раз больше (или использовать гораздо больше потоков), что делает атаки не сложнее, но, по крайней мере, дольше. Если у моего веб-приложения безумный трафик в течение 1 недели, это легче обнаружить, чем короткий всплеск трафика в 3 часа ночи. - person Fermin Silva; 14.03.2017
comment
Я не статистик, но разве не в том, что число 15 в приведенном выше примере не всегда согласовано в зависимости от внешних факторов (например, нагрузки на сервер)? Итак, если у вас есть операция, которая обычно занимает от 12 до 18 микросекунд, и вы вводите от 0 до 6 микросекунд сна, это невозможно обнаружить. Другой вариант - сделать так, чтобы все операции занимали фиксированное количество времени, то есть спать из-за разницы в фактическом затраченном времени и некоторой произвольной продолжительности времени? - person Angry Dan; 14.06.2019

Энтони Феррара ответил на этот вопрос в своем сообщении в блоге Все о времени < / а>. Я очень рекомендую эту статью.

Многие люди, когда слышат о временных атаках, думают: «Ну, я просто добавлю случайную задержку! Это сработает!». И это не так.

person Scott Arciszewski    schedule 11.02.2015
comment
Множество красивых графиков, и я уверен, что сама лекция это объясняет, но я лично не вижу, как добавления действительно случайного сна недостаточно для смягчения временной атаки. - person Phil; 12.02.2015
comment
@ Phil_1984_ 1) детализация. Большинство случайных снов находятся на уровне миллисекунд, а разница, которую мы измеряем, находится на уровне десятков наносекунд. 2) Населенный пункт. Агент на оборудовании может отслеживать загрузку ЦП и отличать сон от активности (в виртуальных машинах и т. Д.). 3) Статистически эти случайные сны можно усреднить. 4) Это пластырь. Это не смягчает, это не затыкает лежащую под ним рану, это просто делает ее так, чтобы вы ее не видели. Это безвестность. - person ircmaxell; 12.02.2015
comment
А я прочитал только вторую ссылку. 1-я ссылка все это объясняет и очень интересна, спасибо. Вам просто нужно сделать много запросов, чтобы усреднить случайность. Существует также случайность в нагрузке (как вы сказали) и на каждом сетевом переходе, которая теоретически может быть усреднена таким же образом. Что касается проблемы сравнения строк OPs, есть ли что-то неправильное в том, чтобы сначала просто хешировать, а затем сравнивать результаты? - person Phil; 13.02.2015
comment
@ Phil_1984_ просто хеширования недостаточно (поскольку хеширование предсказуемо). Вам потребуется хеширование со случайной строкой (желательно в HMAC): isecpartners.com/blog/2011/feb February/ (обратите внимание, что используется статический ключ, но многие из нас рекомендуют использовать случайный). - person ircmaxell; 13.02.2015
comment
Да, двойной HMAC с одноразовым номером действительно делает временные атаки непрактичными, если у вас есть аллергия на правильное решение. - person Scott Arciszewski; 13.02.2015
comment
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - person Michael Irigoyen; 11.05.2015
comment
Хорошая статья. В нем говорится, что ограничение времени до минимума сработает. Я подозреваю, что, по крайней мере, некоторые люди, которые спрашивают о добавлении случайного количества времени, на самом деле думают об этом так называемом ограничении, но плохо себя объясняют. - person Buttons840; 05.05.2021

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

Однако, если злоумышленник сделает достаточно запросов, эта случайная задержка может усредниться, как указано в ответе Скотта со ссылкой на сообщение в блоге ircmaxell:

Таким образом, если нам нужно было запустить 49 000 тестов, чтобы получить точность 15 нс [без случайной задержки], то нам потребовалось бы, возможно, 100 000 или 1 000 000 тестов той же точности со случайной задержкой. Или, возможно, 100000000. Но данные все еще есть.

В качестве примера давайте оценим количество запросов, которые потребуются для временной атаки, чтобы получить действительный 160-битный идентификатор сеанса, например PHP с 6 битами на символ. что дает длину 27 символов. Предположим, как в связанном ответе, что атака может быть выполнена только на одного пользователя одновременно (поскольку они сохраняют пользователя в поиск в куки).

В лучшем случае из сообщения в блоге, 100 000, количество перестановок будет 100,000 * 2^6 * 27.

В среднем злоумышленник найдет значение на полпути через количество перестановок.

Таким образом, количество запросов, необходимых для обнаружения идентификатора сеанса при атаке по времени, составляет 86 400 000. Это по сравнению с 42 336 000 запросов без предложенной вами защиты времени (при условии точности 15 нс, как в сообщении в блоге).

В сообщении блога, взятие самой длинной из протестированных длин, 14, в среднем заняло 0,01171 секунды, что означает, что 86 400 000 займет 1 011 744 секунды, что соответствует 11 дням 17 часам 2 минутам 24 секундам.

Может ли случайный сон предотвратить временные атаки?

Это зависит от контекста, в котором используется случайный сон, и разрядности строки, которую он защищает. Если это для функции «держать меня в системе», которая является контекстом в связанном вопросе, то злоумышленнику может быть полезно потратить 11 дней на использование временной атаки для перебора значения. Однако это предполагает идеальные условия (т.е. довольно постоянное время отклика вашего приложения для каждой протестированной позиции строки и отсутствие сброса или смены идентификаторов). Кроме того, этот тип активности злоумышленника создаст много шума, и, вероятно, он будет обнаружен через IDS и IPS.

Это не может полностью предотвратить их, но может затруднить их выполнение злоумышленником. Было бы намного проще и лучше использовать что-то вроде hash-equals, которое полностью предотвратить атаки по времени при условии, что длины строк равны.

Ваш предложенный код

function timingSafeCompare($a,$b) {
    sleep(rand(0,100));
    if ($a === $b) {
        return true;
    } else {
        return false;
    }
}

Обратите внимание, что rand функция PHP не является криптографически безопасный:

Внимание! Эта функция не генерирует криптографически безопасные значения и не должна использоваться в криптографических целях. Если вам нужно криптографически безопасное значение, рассмотрите возможность использования _5 _ вместо этого.

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

Лучший способ приблизиться к безопасности - это предположить, что злоумышленник знает ваш исходный код - единственное, что является секретом от злоумышленника, - это такие вещи, как ключи и пароли - предполагайте, что он знает используемые алгоритмы и функции. Если вы все еще можете сказать, что ваша система защищена, даже если злоумышленник точно знает, как она работает, вы будете почти всегда там. Такие функции, как rand, обычно устанавливаются для заполнения с текущим временем дня, поэтому злоумышленник может просто убедиться, что его системные часы установлены так же, как и на вашем сервере, а затем сделать запросы, чтобы убедиться, что их генератор соответствует вашему.

По этой причине лучше избегать небезопасных случайных функций, таких как rand, и изменить свою реализацию на использование openssl_random_pseudo_bytes, что будет непредсказуемо.

Кроме того, согласно комментарию ircmaxell, sleep недостаточно детализирован, поскольку он принимает только целое число для представления количества секунд. Если вы собираетесь попробовать этот подход, просмотрите time_nanosleep со случайным количество наносекунд.

Эти указатели должны помочь защитить вашу реализацию от такого типа временных атак.

person SilverlightFox    schedule 09.02.2015
comment
Также: sleep() принимает в качестве параметра секунды. У которого слишком низкая степень детализации, чтобы что-то скрыть ... - person ircmaxell; 12.02.2015