wp_verify_nonce wp_nonce_field texto strip_tags remove quitar para limpiar funcion etiquetas ejemplo php actionscript-3 cryptography nonce

php - wp_nonce_field - Cómo crear y usar nonces



strip_tags() (4)

Estoy ejecutando un sitio web, y hay un sistema de puntuación que te da puntos por la cantidad de veces que juegas un juego.

Utiliza el hash para probar la integridad de la solicitud http de puntuación para que los usuarios no puedan cambiar nada, sin embargo, como temía que sucediera, alguien descubrió que no era necesario cambiarlo, solo necesitaban obtener un puntaje alto y duplicar el solicitud http, encabezados y todo.

Anteriormente, se me había prohibido proteger contra este ataque porque se consideraba poco probable. Sin embargo, ahora que ha sucedido, puedo. La solicitud http se origina en un juego flash, y luego es validada por php y php lo ingresa en la base de datos.

Estoy bastante seguro de que esto resolverá el problema, pero no estoy seguro de cómo implementarlo. ¿Cuál es una forma común y segura de configurar un sistema nonce?


Nonces son una lata de gusanos.

No, realmente, una de las motivaciones para varias entradas de CAESAR fue diseñar un esquema de cifrado autenticado, preferiblemente basado en un cifrado de flujo, que sea resistente a la reutilización nonce. (La reutilización de un nonce con AES-CTR, por ejemplo, destruye la confidencialidad de su mensaje en la medida en que un estudiante de primer año pueda descifrarlo).

Hay tres escuelas principales de pensamiento con nonces:

  1. En la criptografía de clave simétrica: use un contador creciente, teniendo cuidado de no volver a utilizarlo nunca más. (Esto también significa usar un contador separado para el emisor y el receptor.) Esto requiere una programación con estado (es decir, almacenar el nonce en alguna parte, por lo que cada solicitud no comienza en 1 ).
  2. Stateful random nonces. Generando un nonce aleatorio y luego recordándolo para validarlo más tarde. Esta es la estrategia utilizada para derrotar los ataques CSRF, que suena más cercano a lo que se solicita aquí.
  3. Grandes nonces aleatorios sin estado. Dado un generador seguro de números aleatorios, casi puede garantizar que nunca repita un nonce dos veces en su vida. Esta es la estrategia utilizada por CAESAR para el cifrado.

Entonces, con eso en mente, las preguntas principales son:

  1. ¿Cuál de las escuelas de pensamiento anteriores son más relevantes para el problema que estás tratando de resolver?
  2. ¿Cómo estás generando el nonce?
  3. ¿Cómo estás validando el nonce?

Generando un Nonce

La respuesta a la pregunta 2 para cualquier evento aleatorio es usar un CSPRNG. Para proyectos PHP, esto significa uno de:

  • random_bytes() para proyectos PHP 7+
  • paragonie/random_compat , un polyfill de PHP 5 para random_bytes()
  • ircmaxell/RandomLib , que es una navaja suiza de utilidades de aleatoriedad que la mayoría de los proyectos que se ocupan de la aleatoriedad (por ejemplo, reinicios de contraseñas de abeto) deberían considerar el uso en lugar de enrollar los suyos propios

Estos dos son moralmente equivalentes:

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

y

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

Validar un Nonce

Con estado

Los nonces con estado son fáciles y recomendados:

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

Siéntase libre de sustituir el array_search() con una base de datos o una búsqueda de memcached, etc.

Apátridas (aquí hay dragones)

Este es un problema difícil de resolver: necesita alguna forma de prevenir ataques de repetición, pero su servidor tiene una amnesia total después de cada solicitud HTTP.

La única solución sensata sería autenticar una fecha / hora de caducidad para minimizar la utilidad de los ataques de repetición. Por ejemplo:

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

Un cuidadoso observador observará que esta es básicamente una variante que no cumple con los estándares de JSON Web Tokens .


En realidad es bastante fácil de hacer ... Hay algunas bibliotecas que lo pueden hacer por usted:

  1. Biblioteca PHP Nonce
  2. OpenID Nonce Library

O si quieres escribir el tuyo, es bastante simple. Usando la página de WikiPedia como punto de partida, en pseudo-código:

En el lado del servidor, necesita dos funciones llamables por el cliente

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

Y en el lado del cliente:

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

La función makeRandomString realmente solo necesita devolver un número aleatorio o cadena. Cuanto mejor sea la aleatoriedad, mejor es la seguridad ... También tenga en cuenta que, dado que se alimenta directamente en una función hash, los detalles de implementación no importan desde la solicitud hasta la solicitud. La versión del cliente y la del servidor no necesitan coincidir. De hecho, el único bit que debe coincidir al 100% es la función hash utilizada en hash(''sha512'', $nonce . $cnonce . $data); ... Aquí hay un ejemplo de una función makeRandomString razonablemente segura ...

function makeRandomString($bits = 256) { $bytes = ceil($bits / 8); $return = ''''; for ($i = 0; $i < $bytes; $i++) { $return .= chr(mt_rand(0, 255)); } return $return; }


No es posible evitar las trampas. Solo puedes hacerlo más difícil.

Si alguien vino aquí en busca de una biblioteca Nonce de PHP: recomiendo no usar la primera dada por ircmaxwell .

El primer comentario en el sitio web describe un error de diseño:

El nonce es bueno para una ventana de tiempo determinado, es decir, cuanto más se acerca el usuario al final de las ventanas, menos tiempo tiene para enviar el formulario, posiblemente menos de un segundo

Si está buscando una forma de generar Nonces con una vida útil bien definida, eche un vistazo a NonceUtil-PHP .


Una opción (que mencioné en los comentarios) es grabar el juego y reproducirlo en un entorno seguro.

La otra cosa es aleatoriamente, o en algunos momentos específicos, grabar algunos datos aparentemente inocentes, que luego se pueden usar para validarlo en el servidor (como repentinamente en vivo va de 1% a 100%, o puntaje de 1 a 1000 que indican trampa ) Con suficientes datos, podría no ser factible que el tramposo intente falsificarlo. Y luego, por supuesto, implementar prohibiciones pesadas :).