Jak tworzyć i używać nonces

Prowadzę stronę internetową i istnieje system punktacji, który daje punkty za ilość razy grasz w grę.

Używa hashowania, aby udowodnić integralność żądania http dla punktacji, więc użytkownicy nie mogą niczego zmienić, jednak, jak się obawiałem, może się zdarzyć, ktoś zorientował się, że nie muszą go zmieniać, po prostu musieli uzyskać wysoki wynik i zduplikować żądanie http, nagłówki i wszystko.

Poprzednio zakazano mi ochrony przed tym atakiem ponieważ uznano to za mało prawdopodobne. Jednak teraz, kiedy to się stało, mogę. Żądanie http pochodzi z gry flash, a następnie jest zatwierdzane przez php i php wprowadza je do bazy danych.

Jestem prawie pewien, że nonces rozwiąże problem, ale nie jestem do końca pewien, jak je wdrożyć. Jaki jest powszechny i bezpieczny sposób konfiguracji systemu nonce?

Author: Malfist, 2010-11-10

4 answers

To całkiem proste... Jest kilka bibliotek, które zrobią to za Ciebie:

  1. PHP Nonce Library
  2. Biblioteka OpenID Nonce

Lub jeśli chcesz napisać swój własny, jest to dość proste. Wykorzystanie strony Wikipedii jako punktu wyjścia, w pseudo-kodzie:

Po stronie serwera potrzebne są dwie funkcje wywoływalne przez klienta

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

I po stronie klienta:

sendData($data) {
    $nonce = getNonceFromServer();
    $cnonce = hash('sha512', makeRandomString());
    $hash = hash('sha512', $nonce . $cnonce . $data);
    $args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash);
    sendDataToClient($args);
}

Funkcja makeRandomString naprawdę tylko musi zwrócić losową liczbę lub ciąg znaków. Im większa losowość, tym większe bezpieczeństwo... Zauważ również, że ponieważ jest on wprowadzany bezpośrednio do funkcji hash, szczegóły implementacji nie mają znaczenia od żądania do żądania. Wersja klienta i wersji serwera nie muszą się zgadzać. W rzeczywistości jedynym bitem, który musi pasować w 100%, jest funkcja hash używana w hash('sha512', $nonce . $cnonce . $data);... Oto przykład dość bezpiecznej funkcji makeRandomString...

function makeRandomString($bits = 256) {
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}
 55
Author: ircmaxell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 06:10:11

Nonces to puszka robaków.

Nie, naprawdę, jedną z motywacji dla kilku Caesar wpisów było zaprojektowanie uwierzytelnionego schematu szyfrowania, najlepiej opartego na szyfrze strumieniowym, odpornym na ponowne użycie. (Ponowne użycie nonce z AES-CTR, na przykład, niszczy poufność Wiadomości do stopnia student pierwszego roku programowania może ją odszyfrować.)

Istnieją trzy główne szkoły myśli z niecesami:

  1. w symetrycznym kluczu kryptografia: używaj zwiększającego się licznika, dbając o to, aby nigdy nie używać go ponownie. (Oznacza to również użycie oddzielnego licznika dla nadawcy i odbiorcy.) Wymaga to programowania stanowego (tzn. przechowywania nonce gdzieś, aby każde żądanie nie zaczynało się od 1).
  2. Stateful random nonces. Wygenerowanie losowej nonce, a następnie zapamiętanie jej do weryfikacji później. jest to strategia używana do pokonywania ataków CSRF, która brzmi bliżej tego, o co tu się prosi.
  3. Duży bezpaństwowe przypadkowe nonces. Biorąc pod uwagę Bezpieczny generator liczb losowych, możesz prawie zagwarantować, że nigdy nie powtórzysz nonce dwa razy w życiu. Jest to strategia używana przez NaCl do szyfrowania.
Tak więc, mając to na uwadze, główne pytania, które należy zadać, to:]}
  1. które z powyższych szkół myślenia są najbardziej istotne dla problemu, który próbujesz rozwiązać?
  2. Jak generujesz nonce?
  3. Jak sprawdzasz nonce?

Generowanie Nonce

Odpowiedź na pytanie 2 dla dowolnego losowego nonce jest użycie csprng. W przypadku projektów PHP oznacza to jeden z:

Te dwa są moralnie równoważne:

$factory = new RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$_SESSION['nonce'] [] = $generator->generate(32);

I

$_SESSION['nonce'] []= random_bytes(32);

Walidacja Nonce

Stateful

Stateful nonces są łatwe i zalecane:

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

Zastąp array_search() bazą danych lub wyszukiwaniem memcached, itp.

Stateless (here be dragons)

Jest to trudny problem do rozwiązania: potrzebujesz sposobu, aby zapobiec atakom powtórek, ale twój serwer ma całkowitą amnezję po każdym HTTP Prośba.

Jedynym rozsądnym rozwiązaniem byłoby uwierzytelnienie daty/godziny wygaśnięcia, aby zminimalizować użyteczność ataków powtórkowych. Na przykład:

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

Uważny obserwator zauważy, że jest to w zasadzie niezgodny ze standardami wariant JSON Web Tokens.

 17
Author: Scott Arciszewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-07 19:23:48

Jedną z opcji (o której wspomniałem w komentarzu) jest nagrywanie rozgrywki i odtwarzanie jej w bezpiecznym środowisku.

Inną rzeczą jest losowo, lub w określonym czasie, zapisanie pozornie niewinnych danych, które później mogą być użyte do walidacji na serwerze (jak nagle live przechodzi od 1% do 100%, lub wynik od 1 do 1000, co wskazuje na oszustwo). Przy wystarczającej ilości danych może to po prostu nie być możliwe, aby cheater spróbował go sfałszować. A potem oczywiście wprowadzić ciężki zakaz :).

 1
Author: Maurycy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-10 14:45:27

Nie można zapobiec oszustwom. Możesz tylko to utrudnić.

Jeśli ktoś tu szukał biblioteki PHP Nonce: polecam nie używać pierwszej podanej przez ircmaxwell.

Pierwszy komentarz na stronie opisuje wadę projektu:

Nonce jest dobre dla jednego określonego okna czasowego, tzn. im bliżej użytkownik dostaje do końca tego okna, tym mniej czasu musi Prześlij formularz, ewentualnie mniej niż jeden second

Jeśli szukasz sposobu na wygenerowanie Nonceutil-PHP o ściśle określonym czasie życia, zajrzyj do NonceUtil-PHP .

 0
Author: Timo Stamm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-29 11:33:27