Trampa o interrupción del servicio al modificar el código del lado del cliente

10

Un pirata informático razonablemente de sombrero blanco ha demostrado la capacidad de insertar texto de su propia elección en la comunicación entre un applet de Java y un servidor basado en web. No es un simple ataque MITM, pero utiliza una herramienta como "JavaSnoop" para acceder a las comunicaciones dentro de la estructura de clase del applet de Java.

Creo que en última instancia no hay defensa contra este tipo de ataque (y aquí me gustaría que me contradijeran): en principio, podría sustituir a un cliente completo de su elección. y, por supuesto, el servidor debe estar blindado contra todo tipo de entradas maliciosas.

El ejemplo canónico de esto sería hacer trampa en un juego en línea al alterar el cliente o las comunicaciones entre el cliente y el servidor.

¿Hay algo mejor que la seguridad por oscuridad para hacer que este proceso sea lo más difícil posible?

    
pregunta ddyer 10.08.2013 - 03:28
fuente

7 respuestas

10

JavaSnoop es una herramienta para explotar vulnerabilidades como CWE-602: Cumplimiento del lado del cliente de la seguridad del lado del servidor . Incluso los clientes pesados no pueden ser confiables, y si un sistema distribuido expone las funciones confidenciales a los clientes pesados, entonces eso es una vulnerabilidad . No tiene sentido defender contra "JavaSnoop" o incluso "Firebug" o "eructar", estas son solo herramientas. El sistema en su conjunto debe tomarse en consideración, y un servidor debe ser examinado por vulnerabilidades de explotación remota que sean accesibles por cualquier medio.

El proceso para enumerar estos tipos de vulnerabilidades no es diferente a cualquier otra vulnerabilidad. Un equipo de evaluación o un evaluador de penetración analizará la funcionalidad expuesta y probará esta funcionalidad para detectar vulnerabilidades comunes, como Inyección de SQL o problemas de límites de confianza.

    
respondido por el rook 10.08.2013 - 03:48
fuente
5

Seamos más específicos acerca de tu ejemplo y digamos que este es un juego de póquer en línea. El servidor contiene datos que representan el centro de la mesa (incluido el bote, el mazo boca abajo y la "comunidad" de cartas), pero el software del cliente controla su "esquina" de la mesa (el alijo del jugador, su mano, y sus decisiones).

La suposición es que el software cliente es el mismo software lanzado por el autor del juego, sin modificaciones de ningún tipo, por lo que el software cliente se ha hecho responsable de realizar un seguimiento preciso de sus fondos y de sus manos; el servidor "reparte" las tarjetas al cliente, y tal como lo haría el verdadero crupier del casino, "olvida" (o nunca sabe) qué tarjeta se repartió.

Esto no es una suposición segura; alguien que pueda manipular el programa cliente, o incluso solo los mensajes que se envían desde y hacia él, puede elegir su mano modificando los mensajes sobre las tarjetas que el servidor ha enviado y puede multiplicar sus ganancias reales (o incluso ignorar las pérdidas girando) "pierdes" en "ganas $ 1000").

La solución no es permitir que el software cliente tenga nada que se aproxime a este nivel de control. El modelo a seguir es el de un "terminal tonto"; trate el software cliente como nada más que un cable largo realmente que conecta su teclado y monitor a la computadora del servidor. El cliente no sabe nada más que lo que dice el servidor, y no hace nada más que transmitir la entrada del usuario al servidor y viceversa. No tiene una "lógica de negocios" propia, solo muestra el juego al usuario.

Dado este modelo, la manipulación de las comunicaciones no es buena para el atacante; Las comunicaciones desde el servidor y los números y tarjetas en la pantalla se pueden cambiar al contenido del corazón del atacante, pero cualquier acción basada en los datos incorrectos del cliente se hace realidad con un ruido sordo por parte del servidor. El cliente no puede decir "Yo levanto 50 mil"; el servidor simplemente responderá "solo tienes $ 20 en tu pila; inténtalo de nuevo". El cliente no puede decir "Soy Bob y llamo"; El servidor, al ver que la solicitud llegó a una sesión segura que pertenece a Bill, dirá "No, eres Bill, siéntate y cállate hasta que Bob haya tomado su turno". Incluso los ataques de repetición, donde un cliente puede escuchar la conversación segura entre otro cliente y el servidor, y repetir la comunicación para ejecutar cualquier comando contenido en ella, se detectan e ignoran muy fácilmente. Dada la suficiente cantidad de estas comunicaciones descabelladas, el servidor puede decir "Me estás perdiendo el tiempo, adiós" y expulsar al cliente del juego.

La desventaja, como se mencionó, es la latencia. La estrategia en el ideal funciona para un juego de póquer, donde todos actúan por turnos y, por lo tanto, hay mucha espera de todos modos, y es trivial que el servidor realice un seguimiento de todo lo que sucede a la vez. No funciona tan bien para un FPS o RTS, donde la interacción entre todos los jugadores debe ser en tiempo real o muy cerca, y hay un lote de cálculo de proyectiles y cuerpos que se mueven, vuelan, chocan, etc. Causa problemas cuando la latencia es de más de unos pocos milisegundos (independientemente de la velocidad de datos); si todos tienen un ping de 150 ms a un servidor de juegos, entonces todos están viendo dónde estaban todos los demás hace 300 ms (al menos) y si alguien aprieta el gatillo cuando la cabeza de un oponente está en la mira, el servidor cree que estás disparando a donde la persona estaba en realidad hace medio segundo y dice "te lo perdiste". Eso requiere que los jugadores se "atrasen", disparando frente a sus objetivos por una distancia basada en su latencia combinada, incluso cuando la física del juego dicta que el viaje de bala es instantáneo.

Para compensar esto, el servidor necesariamente cede algo de control y permite que los clientes digan "Le disparé a Bob en la cabeza" cuando el jugador aprieta el gatillo mientras la cabeza de Bob aparece en su punto de mira en la pantalla. Sin embargo, un jugador con un mod de juego que puede "ignorar" estratégicamente los datos entrantes sobre las posiciones de otros jugadores puede manipular esta cantidad de confianza del cliente para realizar el truco de "congelar el cuadro"; desactiva los datagramas entrantes, y todos los demás se congelan en su lugar, lo que permite al atacante un buen disparo en la cabeza. Si el servidor cree la reclamación del cliente, porque nadie más afirma que le disparó primero a ese tipo, el otro hombre está muerto, incluso si su propio cliente lo muestra a salvo fuera de la línea de fuego.

Para este tipo de cosas, realmente no hay mejor respuesta; En cualquier lugar que coloque el control sobre la toma de decisiones de tipo "árbitro" que cambian el juego, los jugadores acusarán a otros de hacer trampa porque vaciaron un clip en el tipo que estaba en el punto en blanco y el servidor dice que tienen éxito, o porque el servidor dijo " Bill está muerto, Bob le disparó "dos segundos completos después de que Bill pensara que había despejado la línea de fuego de Bob detrás de un obstáculo.

    
respondido por el KeithS 15.08.2013 - 00:37
fuente
4

Por lo que puedo ver, está destacando un problema perenne en los juegos en línea: confiar en el cliente. Para resumir brutalmente los años de investigación y experiencia:

  • Usted, el operador del servidor, no puede controlar al usuario, su computadora, su red o lo que deciden hacer con el software de su cliente.
  • Por lo tanto, no puede ocultar sus comunicaciones o las respuestas del cliente a la entrada.
  • Por lo tanto, debe asumir que, en algún momento, alguien resolverá la manera de falsificar las opiniones de los usuarios
  • Por lo tanto, debe validar todo en el servidor.

Cuando digo validar todo, quiero decir todo . Dio el ejemplo de un juego de disparos, donde un usuario malintencionado podría agregar más balas. El servidor debe saber qué arma tiene el jugador, qué tan rápido puede disparar, cuántas rondas puede disparar antes de volver a cargar, etc. Dado esto, y la hora en que el usuario presionó el botón de disparo, el servidor puede decir cuántas balas hay. debiera ser. El cliente no controla las balas; le dice al servidor que el jugador está disparando y que el servidor genera balas. El cliente es libre de simular viñetas en el supuesto de que el servidor haga esto, pero cuando se llega a esto, en cualquier desacuerdo es la versión del servidor de las cosas que se destaca.

La lección general es que el cliente nunca determina los resultados de nada; simplemente informa al servidor de las acciones del usuario y muestra los resultados enviados por el servidor. Si hay alguna decisión que afecte la forma en que se desarrollan las cosas, el servidor toma esa decisión. Esto se reduce a lo básico: el cliente no dice "la pistola está disparando", sino que dice "el gatillo se tira". Es posible que su cliente tenga un retraso al volver a cargar, pero un cliente malintencionado puede ignorarlo y enviar el mensaje de "activación" inmediatamente. Su servidor no debería permitir esto.

  • El usuario hace una entrada
  • El cliente envía la entrada al servidor
  • El cliente muestra el resultado asumido de la acción

Mientras tanto, el mensaje llega al servidor ...

  • El servidor valida esa entrada; verifique los límites de cuántas veces y con qué frecuencia se puede realizar esta acción, y si se puede realizar en la situación actual.
  • El servidor activa la acción
  • El servidor determina el resultado de la acción
  • El servidor informa al cliente del resultado

Cuando el mensaje vuelve al cliente ...

  • El cliente descarta los resultados asumidos con los que estaba trabajando
  • El cliente muestra el resultado del servidor

Esta es la razón por la que ve que el retraso causa efectos extraños; por ejemplo, cuando parece que se teletransporta, se debe a que el cliente recibió el comando "caminar hacia adelante" y mostró el resultado supuesto de que avanzó un poco. El servidor no recibió el comando, por lo que le dice al cliente "no, estás aquí", y como El servidor siempre tiene la razón, el cliente tiene que obedecer y te encuentras de repente en otro lugar. En general, sin embargo, el servidor y el cliente estarán de acuerdo, por lo que esta simulación de resultados asumidos por el cliente permite que el juego funcione sin problemas; por ejemplo, puede estar ejecutando el juego a 80 cuadros por segundo cuando las actualizaciones del servidor solo llegan 30 veces por segundo. Para esos dos marcos entre las actualizaciones, las suposiciones del cliente son lo suficientemente cercanas como para que el jugador no note la diferencia.

La etapa de validación en ese proceso es donde atrapas a los tramposos. Cualquier persona que envíe comandos repetidamente que no deberían estar permitidos está probablemente intentando hacer trampa. Es posible que tengan una conexión realmente terrible y que el servidor simplemente esté recibiendo las cosas fuera de orden o que falten bits, pero hay formas de determinar esto (TCP hace esto de forma inmediata, pero los juegos a menudo usan UDP porque TCP puede ser más lento, por lo que es posible que tengas que implementar esto por tu cuenta).

    
respondido por el anaximander 15.08.2013 - 11:15
fuente
2

La solución adecuada dependerá de la aplicación: cómo evitar el uso indebido depende de lo que significa el uso indebido en su contexto.

Pero en el sentido general, la solución al mal comportamiento del lado del cliente es la validación del lado del servidor. Esto puede significar muchas cosas, así que permítanme dar algunos ejemplos:

  • Con las aplicaciones web, la validación con Javascript no se considera una verdadera medida de seguridad; todas las comprobaciones de seguridad realizadas en el lado del cliente deben realizarse de nuevo después de enviar la respuesta.

  • De nuevo con las aplicaciones web, no asumes que tu entrada será producida por un navegador de buen comportamiento. Por ejemplo, un navegador no enviará una URL que contenga /../ , pero la filtrará de todas formas.

  • Con los juegos de FPS en línea como Team Fortress et.al, el servidor observa cuidadosamente las métricas, como la rapidez con la que se mueve el jugador, la altura de su salto, la precisión con la que apunta, etc. no puede ser producido por un cliente que se comporte correctamente.

Es absolutamente, completamente y, por lo demás, totalmente imposible asegurar que el cliente en el otro extremo de la línea sea su software, esté configurado correctamente, sin modificaciones y libre de otras formas de manipulación.

Es absolutamente necesario validar todo lo que es importante del lado del servidor. Puedes estar seguro, eso no está en cuestión. Puedes evitar muchos tipos de trampas. Pero no lo hace asegurándose de que el cliente no esté modificado. En su lugar, tienes que proteger el servidor.

    
respondido por el tylerl 17.08.2013 - 10:17
fuente
1

JavaSnoop se puede ver como un "depurador para applets". Permite a un usuario manipular el código (Java) que se ejecuta en his machine, dentro de his . La posibilidad de hacer eso siempre ha sido conocida; JavaSnoop es solo una herramienta que lo hace un poco más fácil.

El problema genérico es lo que @Rook señala: el código que se ejecuta en la máquina atacante no es confiable. Esa es su máquina, él puede hacer que haga lo que quiera. Por lo tanto, las aplicaciones que se basan en el código que se ejecuta en el sistema del usuario para imponer las propiedades de seguridad contra el usuario no pueden ser sólidas en última instancia. En el mejor de los casos, ofuscación de código puede ralentizar un poco al atacante (por ejemplo, algunas horas o días) ), y puede haber algunas mitigaciones que intentarán eliminar a algunos atacantes de bajo poder.

En el contexto de los juegos en línea, donde las reglas impuestas por el cliente son muy comunes (debido a que la aplicación del lado del servidor conduciría a una latencia intolerable u otras razones técnicas similares), el desalojo del 90% de los tramposos ya es una ganancia neta y los vendedores y operadores de juegos ya están acostumbrados a la idea de que nunca erradicarán las trampas; solo pueden esperar mantener la actividad de los tramposos en niveles tolerables. No se puede decir lo mismo de cualquier otro contexto.

Como se explicó anteriormente, el punto es que el código se ejecuta en la máquina del atacante (es decir, el usuario, visto como el posible atacante). Esto apunta a una solución "simple": deje que la máquina ya no sea la máquina del atacante. Esto es lo que hacen las consolas de juegos: la consola ejecuta un sistema operativo que está firmado por el proveedor de la consola, y no acepta la actualización o el arranque a una versión del sistema operativo que no esté firmada. El sistema operativo también se negará a ejecutar aplicaciones sin firmar. Aunque una consola de juegos es realmente una computadora, la capacidad de ejecutar el código proporcionado por el usuario está cerrada.

Por supuesto, cualquier agujero de seguridad en el sistema operativo o en una "aplicación confiable" (un juego) puede ser objeto de abuso para evitar estas protecciones. Esto se ha hecho varias veces. Para la consola PS3, existía el "PS Jailbreak", un dongle USB que explota un error en la forma en que el sistema operativo maneja la información de los dispositivos USB. Luego hubo un sistema operativo falso que se firmó porque Sony no pudo usar correctamente las firmas ECDSA correctamente y reveló su clave privada en el proceso. Sin embargo, tenga en cuenta que Sony, el proveedor de la consola, todavía tiene una palanca poderosa para configurar las cosas "correctamente" (desde su punto de vista), y lo utilizaron: pueden forzar las actualizaciones de firmware, para que no se pueda acceder a todas las cosas "en línea". (y estos incluyen la simple lectura de discos Blu-ray recientes ...).

Otro ejemplo es cómo un iPhone o iPad solo ejecutará aplicaciones debidamente aprobadas (aprobadas por Apple, por supuesto), a menos que el dispositivo sea liberado . Apple y los jailbreakers están atrapados en una carrera interminable, Apple produce nuevas versiones de dispositivos y acompaña al sistema operativo a la velocidad de neckbreak, mientras que los ingenieros de ingeniería inversa están trabajando arduamente para encontrar agujeros para abusar. A veces el sistema operativo se rompe el día en que sale; a veces mantiene la línea durante varios meses.

Además de las vulnerabilidades de software, se pueden usar ataques de hardware. Para contrarrestar esto, el hardware debe ser a prueba de manipulaciones. El nombre genérico para este tipo de dispositivo es Trusted Platform Module . Un TPM se puede usar como protección adicional para el usuario, para bloquear algunos tipos de entradas ilícitas (por ejemplo, virus); pero también se puede usar para proteger a contra el usuario, bloqueándolo de su propia máquina.

Sin embargo, nada de esto es realmente aplicable a los applets de Java . El applet de Java, por definición, se extrae del hardware real. Se ejecuta en una máquina virtual que se implementa mediante el complemento de Java, un complemento del cual existe una open-source version que es fácil de modificar para incluir habilidades de depuración similares a JavaSnoop.

La verdadera "solución" a este problema es una no solución: simplemente no hagas esto. No diseñe su aplicación para que el código en la computadora del cliente sea confiable. Simplemente no funcionará a largo plazo; a menos que se encuentre en un contexto que sea lo suficientemente trivial (por ejemplo, juegos en línea), que las "trampas" ocasionales no sean un gran problema y que las medidas de mitigación sean suficientes desde un punto de vista económico. Si debe tener un código confiable del lado del cliente, prepárese para tener que producir su propio hardware a prueba de manipulaciones.

    
respondido por el Thomas Pornin 14.08.2013 - 19:36
fuente
1

Creo que las otras respuestas han cubierto el principio fundamental de que es imposible confiar por completo en una aplicación cliente, por lo tanto, ¿hay algo que puedas hacer para elevar un poco la barra de los trucos de trucos?

Yo diría que hay un par de enfoques que puedes tomar para esto. Para el flujo de tráfico en sí mismo, un enfoque común para la ingeniería inversa es usar un proxy (por ejemplo, eructo ) para interceptar el tráfico. Una forma de hacer esto más difícil es permitir que solo se use un certificado específico en lugar de confiar en cualquier certificado con el CN correcto que fue emitido por una CA "confiable". Esto se conoce comúnmente como fijación de certificados

Un problema mayor es la descompilación de la aplicación cliente, que le permite al atacante ver y modificar su comportamiento. Como dice @thomaspornin, la ofuscación no es una protección completa, pero podría eliminar a algunos atacantes. Se podría usar software como proguard .

Más allá de lo básico, diría que mire su arquitectura, ¿es posible mover las cosas más al lado del servidor para reducir los riesgos potenciales de los ataques del lado del cliente? Otra opción (imperfecta) sería tener un cliente que esté escrito en un lenguaje más amigable para las técnicas de ofuscación y anti-descompilación.

    
respondido por el Rоry McCune 14.08.2013 - 19:59
fuente
1

Este es un ejemplo del tipo de sugerencia que esperaba obtener.

A: use un canal oculto para señalar desde el cliente al servidor que tiene ha sido hackeado Por ejemplo, en un tirador, imponer una "ley no escrita" que cada décimo mensaje de movimiento será a la izquierda. Si la ejecución de esta ley por parte del cliente es suficientemente natural y distribuido, cualquier de los hacks de los usuarios que intentan cambiar, agregar o eliminar movimientos, Probablemente violar la ley. El servidor aprende que se trata de un pícaro y toma la acción apropiada (después de un retraso aleatorio).

El problema con este tipo de hackeo de seguridad es que viola un buen programa diseño, lo que dificulta que el cliente intentado funcione correctamente.

    
respondido por el ddyer 15.08.2013 - 02:11
fuente

Lea otras preguntas en las etiquetas