Как создавать и использовать нончелики
-
30-09-2019 - |
Вопрос
Я запускаю веб-сайт, и есть система оценки, которая дает вам очки на количество раз, когда вы играете в игру.
Он использует хеширование для доказательства целостности HTTP-запроса для оценки, чтобы пользователи ничего не могли изменить, однако, как я боялся, может произойти, кто-то разобрался, что им не нужно его менять, им просто нужно было получить высокий балл и дублировать HTTP-запрос, заголовки и все.
Раньше мне было запрещено защищать от этой атаки, потому что он считался маловероятным. Однако теперь, когда это произошло, я могу. HTTP-запрос возникает из флеш-игры, а затем проверяется PHP, и PHP входит в это в базу данных.
Я почти уверен, что это решает проблему, но я не совсем уверен, как их реализовать. Что такое общий и безопасный способ создания системы NONECE?
Решение
Это на самом деле довольно легко сделать ... Есть некоторые библиотеки, чтобы сделать это для вас:
Или если вы хотите написать свое собственное, это довольно просто. С использованием Страница Википедии Как прыгающий точка, в псевдокод:
На стороне сервера вам нужны два клиента Callable функций
getNonce() {
$id = Identify Request //(either by username, session, or something)
$nonce = hash('sha512', makeRandomString());
storeNonce($id, $nonce);
return $nonce to client;
}
verifyNonce($data, $cnonce, $hash) {
$id = Identify Request
$nonce = getNonce($id); // Fetch the nonce from the last request
removeNonce($id, $nonce); //Remove the nonce from being used again!
$testHash = hash('sha512',$nonce . $cnonce . $data);
return $testHash == $hash;
}
И на стороне клиента:
sendData($data) {
$nonce = getNonceFromServer();
$cnonce = hash('sha512', makeRandomString());
$hash = hash('sha512', $nonce . $cnonce . $data);
$args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash);
sendDataToClient($args);
}
Функция makeRandomString
Действительно просто нужно вернуть случайное число или строку. Чем лучше случайность, тем лучше безопасность ... также обратите внимание, что, поскольку он кормит прямо в хэш-функцию, детали реализации не имеют значения из запроса на запрос. Версия клиента и версия сервера не нужно соответствовать. На самом деле, единственный бит, который должен соответствовать 100%, - это функция хеша, используемая в hash('sha512', $nonce . $cnonce . $data);
... вот пример достаточно безопасного makeRandomString
Функция ...
function makeRandomString($bits = 256) {
$bytes = ceil($bits / 8);
$return = '';
for ($i = 0; $i < $bytes; $i++) {
$return .= chr(mt_rand(0, 255));
}
return $return;
}
Другие советы
Нет, не могут червей.
Нет, действительно, один из мотивов для нескольких ЦЕЗАРЬ Записи состояли в том, чтобы разработать аутентифицированную схему шифрования, предпочтительно на основе потока шифра, который устойчив к повторному использованию NONE. (Например, повторное использование Nonce с AES-CTR, разрушает конфиденциальность вашего сообщения в той степени, что ученик программирования первого года может расшифровать его.)
Существует три основных школы мысли с ногами:
- В симметричной ключевой криптографии: используйте растущий счетчик, заботясь, чтобы никогда не повторно использовать его. (Это также означает использование отдельного счетчика для отправителя и приемника.) Это требует программирования состояния (т.е. хранение NONCE где-то, поэтому каждый запрос не запускается в
1
). - Государственные случайные нон. Создание случайных нон, а затем запоминание его для подтверждения позже. Это стратегия, используемая для поражения атак CSRF, который звучит ближе к тому, что просят здесь.
- Большие случайный без гражданства. Учитывая безопасный генератор случайных чисел, вы почти не можете не повторить одноразовые дважды в вашей жизни. Это стратегия, используемая Наклон для шифрования.
Так что с этим в виду главные вопросы спрашивать:
- Какие из вышеуказанных школ мысли наиболее актуальны к проблеме, которую вы пытаетесь решить?
- Как вы генерируете нон?
- Как вы подтверждаете нон?
Генерируя нон
Ответ на вопрос 2 для любого случайного NONE - использовать CSPRNG. Для проектов PHP это означает один из:
random_bytes()
Для проектов PHP 7+- Paragonie / Random_Compat., полифилл PHP 5 для
random_bytes()
- Ircmaxell / RandomLib, который является швейцарским армейским ножом коммунальных услуг случайности, которые большинство проектов, которые имеют дело с случайностью (например, пароль Filter), следует учитывать использование вместо того, чтобы прокатиться
Эти два морально эквивалентны:
$factory = new RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$_SESSION['nonce'] [] = $generator->generate(32);
а также
$_SESSION['nonce'] []= random_bytes(32);
Проверяние одноразового
Господство
Государственные нельзя простые и рекомендуемые:
$found = array_search($nonce, $_SESSION['nonces']);
if (!$found) {
throw new Exception("Nonce not found! Handle this or the app crashes");
}
// Yay, now delete it.
unset($_SESSION['nonce'][$found]);
Не стесняйтесь заменить array_search()
с базой данных или MEMCACHED и т. Д.
Без гражданства (здесь будут драконы)
Это сложная проблема для решения: вам нужен способ предотвратить повторные атаки, но ваш сервер имеет общую амнезию после каждого HTTP-запроса.
Единственное вменяемое решение было бы аутентифицированию даты / времени срока действия, чтобы минимизировать полезность атак воспроизведения. Например:
// Generating a message bearing a nonce
$nonce = random_bytes(32);
$expires = new DateTime('now')
->add(new DateInterval('PT01H'));
$message = json_encode([
'nonce' => base64_encode($nonce),
'expires' => $expires->format('Y-m-d\TH:i:s')
]);
$publishThis = base64_encode(
hash_hmac('sha256', $message, $authenticationKey, true) . $message
);
// Validating a message and retrieving the nonce
$decoded = base64_decode($input);
if ($decoded === false) {
throw new Exception("Encoding error");
}
$mac = mb_substr($decoded, 0, 32, '8bit'); // stored
$message = mb_substr($decoded, 32, null, '8bit');
$calc = hash_hmac('sha256', $message, $authenticationKey, true); // calcuated
if (!hash_equals($calc, $mac)) {
throw new Exception("Invalid MAC");
}
$message = json_decode($message);
$currTime = new DateTime('NOW');
$expireTime = new DateTime($message->expires);
if ($currTime > $expireTime) {
throw new Exception("Expired token");
}
$nonce = $message->nonce; // Valid (for one hour)
Осторожно отметит, что это в основном, не соответствует стандарту, соответствующий вариант JSON WEB TOKENS..
Один вариант (который я упомянул в комментарии), является запись геймплея и воспроизвести его в безопасной среде.
Другое дело - случайно, или в некоторые указанные времена записывают некоторые, казалось бы, невинные данные, которые позже можно использовать для проверки его на сервере (например, вдруг живут от 1% до 100%, или оценка от 1 до 1000, что указывает на чит ). С достаточным количеством данных, возможно, просто не осуществится для обмана, чтобы попытаться подделать его. А потом, конечно, реализует тяжелое запрещение :).
Это очень простое нон изменяет каждые 1000 секунд (16 минут) и может использоваться для избежания XSS, где вы публикуете данные в и из того же приложения. (Например, если вы находитесь в приложении к одной странице, где вы публикуете данные через JavaScript. Обратите внимание, что у вас должен быть доступ к одному и тому же генератору семян и нон, от поста и приемной стороны)
function makeNonce($seed,$i=0){
$timestamp = time();
$q=-3;
//The epoch time stamp is truncated by $q chars,
//making the algorthim to change evry 1000 seconds
//using q=-4; will give 10000 seconds= 2 hours 46 minutes usable time
$TimeReduced=substr($timestamp,0,$q)-$i;
//the $seed is a constant string added to the string before hashing.
$string=$seed.$TimeReduced;
$hash=hash('sha1', $string, false);
return $hash;
}
Но путем проверки предыдущего NONE, пользователь будет обеспокоен только, если он ждал более 16,6 минуты в худшем случае и 33 минуты в лучшем случае. Установка $ q = -4 даст пользователю не менее 2,7 часа
function checkNonce($nonce,$seed){
//Note that the previous nonce is also checked giving between
// useful interval $t: 1*$qInterval < $t < 2* $qInterval where qInterval is the time deterimined by $q:
//$q=-2: 100 seconds, $q=-3 1000 seconds, $q=-4 10000 seconds, etc.
if($nonce==$this->makeNonce($seed,0)||$nonce==$this->makeNonce($seed,1)) {
//handle data here
return true;
} else {
//reject nonce code
return false;
}
}
Семена $, могут быть любые функции вызова или имя пользователя и т. Д., Используемые в процессе.
Невозможно предотвратить мошенничество. Вы можете сделать только это сложнее.
Если кто-то пришел сюда ищет библиотеку NONECE PHP: я рекомендую не использовать первый данный Ircmaxwell.
Первый комментарий на веб-сайте описывает недостаток дизайна:
NONCE хорош в одном определенном окне времени, то есть то, ближе к пользователю доходит до конца этой Windows, тем меньше, чем он или она должна отправить форму, возможно, менее одной секунды
Если вы ищете способ создавать неисполнения с четко определенной жизнью, посмотрите на Несея-php..
Отказ от ответственности: Я автор несевто-PHP