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

От Википедия

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

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

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));

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

14

Решение

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

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

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

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

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

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

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

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

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

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

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

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

Тогда вы можете начать играть с цифрами.

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

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

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

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

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

14

Другие решения

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

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

9

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

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

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

В качестве примера, давайте оценим количество запросов, которое может понадобиться атаке по времени, чтобы получить действительный 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;
}
}

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

предосторожность
Эта функция не генерирует криптографически безопасные значения и не должна использоваться в криптографических целях. Если вам нужно криптографически безопасное значение, рассмотрите возможность использования openssl_random_pseudo_bytes() вместо.

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

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

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

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

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

8
По вопросам рекламы [email protected]