Predictabilidad de PHPs array_rand

3

En general, se sabe que los métodos como el método array_rand() en PHP no se consideran criptográficamente seguros. Estoy tratando de entender en qué situaciones el resultado generado puede ser predecible.

Si conozco la semilla, los valores en la matriz, un solo valor generado y cuántas veces se ha llamado al método antes de que se generara ese valor, sé que puedo calcular fácilmente todos los valores devueltos posteriormente. Puedo hacerlo escribiendo mi propio script que usa la misma semilla y genera el mismo número de resultados, por lo tanto, poniéndolo en el mismo estado.

Suponiendo que no conozco la semilla o el número de valores generados previamente, ¿cuáles son mis posibilidades / qué tan bajo puedo obtener la probabilidad de predecir valores futuros?

Para definir un ejemplo más concreto y hacer que la pregunta sea menos teórica, supongamos que estamos usando array_rand para generar tokens alfanuméricos que no distinguen entre mayúsculas y minúsculas con una longitud de 12. Esto se hace capturando 12 valores de una matriz de caracteres llamando a array_rand 12 veces, haciendo el token [A-Z\d]{12} . Sé que tengo uno de los mil tokens generados consecutivamente, pero no en qué posición se generó.

¿Puedo predecir el siguiente token (suponiendo que no se haya generado el último token)? Supongo que esto no se puede predecir con una precisión del 100%, pero ¿cuáles son las posibilidades de que Brute fuerce todas las posibilidades para el siguiente token y cuántos serían?

Suponiendo que puedo validar si un token es válido, ¿de qué manera saber 2 tokens consecutivos (24 valores) reduce mis posibilidades de predecir el tercero, etc.

He visto un poco de investigación sobre cómo descifrar el estado de rand , pero los artículos generalmente no tratan con rangos restringidos / truncados.

P.S. Estoy tratando de entender la prueba / matemática detrás de por qué es inseguro, no busco sugerencias de enfoques más seguros.

    
pregunta Peter O'Callaghan 30.07.2016 - 16:12
fuente

3 respuestas

1

En su lugar, podría construir sus datos basándose en el openssl_random_pseudo_bytes() más seguro de la biblioteca OpenSSL. Obviamente, esto implica una conversión básica para obtener el rango requerido, pero no se basa en una tabla aleatoria sembrada como otras funciones (como rand() ).

Tenga en cuenta que el mt_rand() incorporado de PHP es en realidad mucho mejor que el clásico rand() en términos de eficiencia y aleatoriedad (distribución más normal), pero aún está sembrado.

Ambos métodos, cuando se implementan correctamente, requerirán el mismo esfuerzo para la fuerza bruta. La principal diferencia es que una vez que la fuerza bruta es exitosa, puede ser posible que un atacante encuentre más detalles sobre sus patrones de implementación o encuentre la semilla que, por lo tanto, haga que sea más fácil para el próximo ataque.

En la práctica, los casos en los que realmente hará una diferencia real son extremadamente raros, pero ha habido casos en los que se ha abusado de ellos. El mejor (y único) ejemplo que conozco es en una máquina tragamonedas de casino en Montreal, donde este tipo pasó semanas tratando de encontrar patrones y finalmente lo hizo debido a la semilla.

    
respondido por el Julie Pelletier 30.07.2016 - 17:09
fuente
1

Bueno, si quieres saber cómo predecir un PRNG, búscalo en Google. Averigüe qué PRNG se usa para array_rand y búsquelo en Google, por ejemplo, "predict mersenne twister" (sin comillas) me da dos enlaces github (en los 3 primeros resultados) a las personas que han logrado escribir un programa para predecir a continuación. Salidas basadas en las anteriores.

Usted pregunta específicamente después de predecir el PRNG cuando no se proporciona la salida en bruto, por ejemplo. cuando se usa para generar caracteres aleatorios (que solo tienen un rango limitado, por ejemplo, 0-26 para letras minúsculas). Esto lo hace mucho más difícil, pero me imagino que aún se hace con algunas conjeturas si no tiene el código fuente (prueba de caja negra).

En una prueba de caja blanca, donde se conoce el código fuente, debería ser bastante trivial. Uno podría necesitar más salidas para recuperar el estado (si se desecha parte de la salida del PRNG), pero debería ser un proceso muy similar.

No estoy seguro de que haya una prueba matemática, como usted pregunta, que demuestre que todos los que no sean CSPRNG deben ser predecibles. Creo que todos son predecibles, excepto los que están hechos (y quizás probados) para tener ciertas propiedades.

    
respondido por el Luc 30.07.2016 - 17:37
fuente
1

array_rand llama a mt_rand internamente . Este es un algoritmo de Twister de Mersenne con un tamaño de estado de 624 números. Esto significa que si obtiene 624 salidas consecutivas de mt_rand , conoce todo el estado y puede predecir todos los números futuros.

Como indica correctamente, es bastante difícil obtener el resultado de mt_rand en casos de la vida real, ya que normalmente está limitado a algún rango. Esto no es necesariamente un problema para el atacante: si la aplicación llama a mt_rand(0, 8) , el atacante solo conoce tres bits del estado, pero también necesita predecir solo tres bits para predecir la salida de algoritmos.

Otro problema práctico con la ruptura de PRNG es que el atacante necesita solicitar tokens del mismo proceso, ya que los diferentes procesos tienen diferentes estados de PRNG. Normalmente, cuando se conecta a un servidor, la solicitud se maneja mediante un proceso aleatorio. Puede hacer hasta 100 solicitudes en una conexión, pero aún así es menos de las 624 solicitudes que necesita para obtener el estado de mt_rand .

En su ejemplo, llama a array_rand 12 veces, por lo que el atacante no obtiene ninguna salida intermedia de mt_rand . Hay demasiadas combinaciones aquí para la fuerza bruta.

Esto podría ser prácticamente seguro, pero sería riesgoso. Una aplicación que examiné también usé mt_rand para la generación de tokens, y Luego tenía otra página que llamaba mt_srand() . Esto hizo posible sembrar el PRNG con un valor conocido. También escribí algo sobre el craqueo de los PRNG de PHP, aunque no se incluye en mt_rand state cracking.

    
respondido por el Sjoerd 30.08.2016 - 10:04
fuente

Lea otras preguntas en las etiquetas