Enviar un puntaje alto del lado del cliente a un servidor de forma segura [duplicado]

39

Estoy creando una aplicación web que contiene un juego javascript simple. Una vez que el jugador terminó de jugar, la puntuación más alta se envía al servidor y se guarda.

Después de un período específico, el jugador con la mejor puntuación recibe un premio.

¿Hay una manera de enviar el puntaje alto de manera segura y evitar que el cliente envíe puntajes altos "falsos"?

Actualmente estamos usando:

  • Https.
  • El token aleatorio del servidor antes de cada juego y se envía una vez finalizado el juego junto a la puntuación.
pregunta StationaryTraveller 15.01.2017 - 10:45
fuente

6 respuestas

111

El servidor no puede confiar completamente en los datos que recibe del cliente, por lo que es difícil validar los puntajes altos.

Aquí hay algunas opciones:

  1. Ofusque el código del lado del cliente y el tráfico al servidor. Esta es la opción más fácil: aún será posible hacer trampa, pero probablemente no valdrá la pena para nadie.

  2. Envía una reproducción completa o parcial del juego al servidor para su validación. Los movimientos del jugador pueden ejecutarse en el servidor para determinar el puntaje legítimo. Esto funcionará para algunos juegos y no para otros.

  3. Mueve la lógica del juego y la validación al servidor. El cliente simplemente transmite cada movimiento al servidor, donde se valida y se actualiza el estado del juego.

Se trata de cómo funciona tu juego, qué tan probable es que la gente haga trampa y cuánto te importa si lo hacen.

    
respondido por el grc 15.01.2017 - 11:54
fuente
27

Si su atacante fuera un atacante de hombre en el medio en la capa de red, entonces https sería suficiente. Pero desafortunadamente su atacante es el cliente, por lo que esto no tiene sentido.

Regla número uno de los juegos de prueba de trucos: ¡Nunca confíes en el cliente! El cliente está en manos del enemigo.

Los juegos de Javascript se ejecutan en el navegador web del usuario. Como usted, como desarrollador web, seguramente sabrá, cada navegador web hoy en día viene con un depurador integrado que puede ver y cambiar todas las variables mientras se ejecuta una aplicación. El usuario puede simplemente usar el depurador para cambiar su puntaje antes de enviarlo. No hay nada que puedas hacer para prevenir eso. Con los juegos basados en navegador, ni siquiera se puede abofetear con una herramienta de terceros para hacer trampas (que son de dudoso valor y éticamente cuestionables).

La única contramedida es implementar todas las mecánicas del juego que vale la pena manipular en el servidor. El cliente no debe hacer nada más que reenviar los comandos del usuario al servidor y visualizar el juego en función de los mensajes del servidor. El juego real debería ocurrir en el servidor donde está fuera del alcance de los tramposos.

Sí, esto significa que tendrás que rediseñar la arquitectura de software de tu juego desde cero. También significa que tendrá que agregar algún código de predicción e interpolación para que el retardo de la red sea menos visible. Y también significa que necesitará un hardware de servidor mucho mejor y una mejor conexión a Internet para su (s) servidor (es). Pero cuando quieres un juego en línea sin trampas, esa es la única opción.

    
respondido por el Philipp 15.01.2017 - 11:54
fuente
17

Para lograr la puntuación más alta en el juego seguro, lo que necesita es una " prueba de trabajo " O, más bien, más adecuadamente llamado prueba de juego.

Una prueba de trabajo / juego es cualquier dato que sea difícil de calcular antes de finalizar el juego, pero que sea fácil de calcular una vez que finalice el juego y que el servidor pueda verificarlo fácilmente. Por ejemplo, para un juego de Sudoku, una prueba de trabajo es la solución al rompecabezas.

Desafortunadamente, no hay una forma genérica de integrar el sistema adecuado de prueba de juego en muchos juegos. No siempre es posible integrar una prueba de juego sin modificar o renovar el juego, o limitar el alcance de la tabla de clasificación solo a elementos en los que puede incluir una prueba de juego lo suficientemente segura.

La prueba de juego en un juego comienza cuando el servidor emite la semilla para el RNG del juego. El cliente entonces tendrá que encontrar una prueba de juego que coincida con la semilla que el jugador había emitido. En muchos juegos, se puede formar una prueba de juego al enviar la solución del juego al servidor con el envío de puntaje alto; en otros, puede ser necesario grabar toda la sesión del juego en varios niveles de detalles, dependiendo del juego y la prueba de juego que estás usando.

Una prueba de juego debe ser resistente a la repetición (un jugador no debe poder usar el juego terminado de otro jugador para que su propia prueba de juego sea más fácil de calcular). Esto limita la prueba de juego a los juegos en los que existe cierta aleatoriedad de que los jugadores no pueden simplemente reutilizar la prueba de juego de otro jugador, pero tampoco puede tener demasiados comportamientos no deterministas hasta el punto en que sea imposible verificar el juego.

La prueba de juego también es limitada. Por ejemplo, en un juego de Sudoku, no es posible demostrar la cantidad de tiempo que el jugador tarda en resolver el rompecabezas. La prueba de juego tampoco siempre puede distinguir entre el juego jugado por los mismos jugadores contra el jugador que escribió un guión que jugó el juego para ellos.

    
respondido por el Lie Ryan 15.01.2017 - 17:29
fuente
8

Solo quería mencionar que existe una especie de solución a este problema, pero es probable que no esté disponible para usted; la solución se denomina "cifrado homomórfico" y permite que un cliente realice un cálculo conocido sin saber exactamente con qué valores están computando, y que un servidor compruebe la estructura del valor computado para demostrar que el cliente no solo envíe una cadena aleatoria hacia atrás, pero en realidad la construyó a partir de los diversos valores proporcionados.

El problema es que es lento o incompleto , con "incompleto" lo que significa que "no incorpora una gama completa de primitivas lógicas". Muy a menudo es un sistema parcial que permite algunas operaciones de cifrado y descifrado E (), D (), además de una operación complicada, de modo que

  

D (E (A) ⊕ E (B)) = A + B,

o similar.

Así que veamos cómo esto resuelve el problema para algunos juegos. Considere un juego tipo "luces apagadas" en el que está presionando los hexes N de una cuadrícula hexagonal y cada uno alterna su estado y los estados de quienes lo rodean. Este es un álgebra conmutativa en esas "prensas" y, por lo tanto, no habrá más de N prensas totales en una solución dada, más cada hexágono solo depende del estado inicial más las prensas de su propio hexágono más los 6 hexágonos que lo rodean.

Dado que nuestro esquema de cifrado homomórfico solo permite +, no XOR, le damos a cada hexágono un contador de 3 bits por el número de veces que se ha volteado. (El software del cliente reducirá automáticamente cada doble pulsación de un hexágono a solo una pulsación). Por lo tanto, las acciones de giro reales son vectores de bits que parecen,

001 001 000 000 000 001 001 001 000 001 001 000 000 ... 000 00000000 00000001

En otras palabras, tienen 1s en cada uno de estos campos de 3 bits que voltea, más un 1 en algún contador de 16 bits.

Ciframos todo esto con un esquema de cifrado homomórfico, enviamos cada uno de ellos al cliente, y el cliente nos devuelve un valor cifrado calculado a partir de estos valores cifrados que devolvimos. Luego desciframos esto y el valor Y descifrado con la cadena de bits,

001 001 001 001 ... 001 11111111 00000000

y compárelo con el estado inicial del juego unido a 0 para esos 8 bits de contador.

Si nos envían un valor aleatorio, su probabilidad de que lo aceptemos es 2 - (N + 8) y, por lo tanto, su única forma útil de pasar las pruebas es usar los valores que les dimos. en alguna combinación permitida. Tienen acceso a algunos movimientos que no les estamos permitiendo directamente debido a desbordamientos de enteros, pero siempre podemos hacer que los campos tengan más de 3 bits para hacerlos más costosos para el contador de la derecha. Pero nunca nos transmitieron sus pulsaciones individuales, y mucho menos repetimos la historia: aceptamos un vector que decía "aquí está la forma en que volteé la cuadrícula", que es la "cosa súper insegura" de la que todos te están advirtiendo, pero Lo hizo de tal manera que no puedan hacer las cosas que nos preocupan sin tener acceso a una clave secreta.

En cambio, ves este tipo de cosas en la votación criptográfica, donde quieres tener la seguridad de que una máquina de votación no otorga espontáneamente 1000 votos a Alice.

    
respondido por el CR Drost 15.01.2017 - 19:15
fuente
4

Todo en el lado del cliente se puede falsificar. Así que la respuesta es no.

EDIT Quité el mecanismo de seguridad que escribí aquí porque solo garantiza sesiones legítimas ... pero las puntuaciones falsas se pueden enviar a través de sesiones legítimas. Gracias @Luke Park

    
respondido por el OscarAkaElvis 15.01.2017 - 11:04
fuente
0

Mi recomendación es más una técnica para la ofuscación, y podría ser un obstáculo frustrante para muchos usuarios. Sin embargo, los usuarios avanzados o determinados aún podrían analizar su código fuente para reproducir los resultados.

Use una herramienta como Hashids para crear un hash de la puntuación, y envíe esto en su solicitud del servidor junto con la puntuación de texto sin formato. El valor de la cadena de la ID de usuario podría ser la sal utilizada para codificar un hashid de la puntuación, haciendo que el hash sea inútil si se comparte. En el lado del servidor, podría descodificar este hash y comparar el resultado con la puntuación de texto sin formato que se envió para asegurarse de que coincidan como se esperaba.

    
respondido por el Ben Harrison 18.01.2017 - 17:09
fuente

Lea otras preguntas en las etiquetas