suplantación de solicitudes POST / GET en un servicio RESTful

13

Comencé a trabajar en una aplicación que se conecta a un servicio RESTful para autenticación y datos. El usuario envía el nombre de usuario y la contraseña a / token endpoint. Una vez que inician sesión correctamente, obtienen un token de portador que luego agregan al encabezado de Autorización en las llamadas subsiguientes a diferentes recursos protegidos.

Mi pregunta es qué impide a los usuarios interceptar su publicación regular desde la aplicación (obtener el token) y, posiblemente, enviar un montón de solicitudes POST (utilizando algo como cartero o violinista) para crear una gran cantidad de publicaciones o artículos falsos o lo que sea. de lo contrario la aplicación lo hace.

¿Cuáles son algunas formas posibles de protegerse de esto? ¿El hecho de que el tráfico hacia el servicio finalmente se realice a través de TLS hace que esto no sea un problema?

    
pregunta ska-dev 13.11.2017 - 16:40
fuente

10 respuestas

30
  

Mi pregunta es qué impide a los usuarios interceptar su aplicación de correo regular (obtener el token) y luego posiblemente enviar un montón de solicitudes POST (utilizando algo como cartero o violinista) para crear una gran cantidad de mensajes o artículos falsos o lo que sea de lo contrario la aplicación lo hace.

Nada

  

¿El hecho de que el tráfico al servicio finalmente se realice a través de TLS hace que esto no sea un problema?

Esto no hace ninguna diferencia.

  

¿Cuáles son algunas formas posibles de protegerse de esto?

El más común es la limitación de velocidad. Es decir. Si alguien publica en un nivel mucho más alto de lo previsto, rechace la publicación. Hay varios enfoques para esto: cuándo publicaron por última vez, el promedio acumulado en N minutos, etc. Si no desea falsos positivos, los usuarios perderán el contenido de la publicación y luego volverán a autenticarse para continuar.

Otro enfoque es captchas. Es decir, intentar que el usuario demuestre que son humanos.

Otro está intentando detectar contenido generado automáticamente mediante filtros de spam o AI.

    
respondido por el Hector 13.11.2017 - 16:56
fuente
12
  

Mi pregunta es qué impide a los usuarios interceptar su publicación regular desde la aplicación

Nada.

  

¿El hecho de que el tráfico al servicio finalmente se realice a través de TLS hace que esto no sea un problema?

Si lo haces para una plataforma móvil (Android / iOS), eso lo hace mucho más difícil (pero no imposible).

Si lo haces para el navegador, esto no agrega mucha protección.

  

¿Cuáles son algunas formas posibles de protegerse de esto?

Es difícil protegerse contra las solicitudes automáticas, pero una cosa que puedes hacer es limitar la tasa.

    
respondido por el Ruben_NL 13.11.2017 - 16:54
fuente
6
  

Mi pregunta es qué impide a los usuarios interceptar su publicación regular desde la aplicación (obtener el token) y, posiblemente, enviar un montón de solicitudes POST (utilizando algo como cartero o violinista) para crear una gran cantidad de publicaciones o artículos falsos o lo que sea. de lo contrario la aplicación lo hace.

     

¿Cuáles son algunas formas posibles de protegerse de esto?

No lo haces. Es decir, no se protege contra esto : desde el punto de vista de la autenticación y la autorización, aquí no se produce ningún ataque, solo el tráfico es perfectamente legítimo.

El problema, en cambio, es "¿Cómo evito que los usuarios envíen correo no deseado a mi servicio?" (o similar), y eso es completamente ortogonal a la cuestión de los tokens de autenticación . De manera similar, un usuario podría hacer spam de forma manual a través de la aplicación.

La limitación de la tasa por cuenta de usuario, la limitación de la tasa por dirección IP, el uso de cookies o identificadores de dispositivos para vincular varias cuentas entre sí con el límite de la tasa por dispositivo, los términos de las listas negras, las heurísticas de spam, etc. son métodos comunes para tratar el spam. Pero sea lo que sea su cosa real, es lo que está tratando de evitar, eso es lo que debería estar estudiando, no evitar que los usuarios modifiquen las cosas del lado del cliente (que siempre podrán hacer).

    
respondido por el Xiong Chiamiov 14.11.2017 - 22:33
fuente
4

El token que le da al cliente debe contener un tiempo de caducidad firmado que se verifique del lado del servidor (por ejemplo, limitado a un tiempo de sesión de usuario típico que esperaría para su aplicación). Esto no evitará que se vuelva a publicar, pero limitará el período dentro del cual podría realizarse después de la autenticación. Al expirar, el usuario tendrá que volver a autenticarse. Esto se implementa comúnmente utilizando Token web JSON .

Sin embargo, está hablando de un uso indebido malintencionado por parte de un usuario legítimo (a menos que un atacante ya haya puesto en peligro el dispositivo del usuario legítimo y pueda interceptar claramente el tráfico): este uso indebido es muy difícil de evitar sin hacer que la aplicación casi inutilizable como otros anotaron (por ejemplo, al hacer que los usuarios se autentiquen en cada solicitud). Almacenar las credenciales en el dispositivo y reenviarlas en silencio es un GRAN NO-NO.

    
respondido por el Sasha K 13.11.2017 - 19:41
fuente
2

Correcto, que un token de sesión solo no asegura que un pirata informático no pueda interceptar un paquete y reutilizarlo para sus propios fines ... al menos mientras el token sea válido. La mayoría de los tokens de sesión tienen un límite de tiempo, aunque eso depende del método de autorización utilizado para validar el token en el extremo del servidor.

El tiempo es una forma de protegerse contra esto, aunque no es infalible. Ya que está escribiendo la aplicación, debe tener una idea razonable de la rapidez con la que se puede operar la aplicación y una tasa esperada de llamadas de servicio. Si su aplicación, en uso típico, no puede enviar una llamada de servicio más de una vez por segundo, y el servicio recibe 100 solicitudes en un segundo, es claramente un hacker en el trabajo.

Sin embargo, esto supone que un pirata informático bombardeará su servicio con solicitudes. Un pirata informático podría darse cuenta de eso después de algunos fallos y reducir su tasa de solicitudes. Tan pronto como vean que el servicio rechaza lo que creen que es un token de sesión válido, comenzarán a ver lo obvio, como la sincronización.

Otra forma de protegerse contra esto es exigir SSL para acceder al servicio. Eso hará que los paquetes y el token de autorización sean difíciles de extraer. Necesitarán mucho más que un rastreador de paquetes. Un pirata informático con un conocimiento especial podría intentar indagar en el binario de la aplicación, pero eso es mucho trabajo, especialmente en plataformas móviles. Tendría que comprar un certificado SSL para el servidor, pero eso es un seguro barato.

Un método con el que he estado experimentando es agregar un número de secuencia al token de sesión, con hash para que no parezca un número de secuencia. El servicio de autorizaciones mantiene un recuento que se incrementa cada vez que se valida un token. Elimina los bytes de la secuencia antes de validar el token y luego verifica el número de secuencia.

Se espera que el cliente comience en cero cuando reciba inicialmente el token de la sesión, e incremente el recuento agregado en uno cada vez que se realice una llamada. Por lo tanto, cuando el servidor recibió por última vez la secuencia 250, y aparece otra secuencia, es la secuencia 135 ... ignorar la solicitud, tal vez bloquear la IP de origen y enviar a los administradores un aviso de que puede haber un intento de pirateo.

Sin embargo, eso agrega cierta complejidad a la aplicación cliente, y también podría ir en contra de paquetes descartados o paquetes devueltos descartados. Solo algo con lo que he estado experimentando.

Y, sí, un pirata informático podría eventualmente ser capaz de darse cuenta de eso, pero solo después de muchos inicios falsos ... dando a los administradores alguna advertencia de que se está realizando un intento de intrusión.

    
respondido por el tj1000 14.11.2017 - 06:59
fuente
1

Muchas otras personas han dicho "nada" en respuesta a la primera pregunta sobre "qué impide ..." y es cierto; En última instancia, nada realmente derrota a alguien absolutamente determinado.

También pediste estrategias que puedan contrarrestar esto; Tj1000 lo tocó, y pensé en lanzar una idea similar a la refriega, basada en el trabajo que solía hacer con los terminales de tarjetas de crédito.

Hace mucho tiempo, cuando era un dev menor, me entregaron una tarea que se consideraba demasiado difícil como para que valiera la pena resolverla los pro devs (creo que eso demuestra un poco lo que me pagaron); teníamos miles de terminales de tarjetas de crédito que llamaban a través de un antiguo enlace pre-isdn, hacían algunas autentificaciones, registraban una transacción, obtenían una aprobación o rechazo del servidor y pasaban a la siguiente transacción. La parte bonita es que nunca hubo otro mensaje de seguimiento desde el terminal si la transacción se anuló después de que la aprobáramos (esto fue en los días de las firmas, antes de que la identidad del usuario fuera autorizada previamente por un chip y un pin), pero no no necesita ser

Estas transacciones fueron protegidas y confirmadas por lo que se denominó un código de autenticación de mensaje MAC. El hardware del terminal incluía una clave hash, única por terminal, del fabricante. El fabricante compartiría con nosotros cuál era la clave de hash, y cuando apareció el terminal presentando su ID única, pudimos buscar la clave de hash. Los bytes del mensaje que formó el terminal serían procesados por el terminal, con la mitad del hash anterior o inicial que se adjunta al mensaje. La otra mitad se usaría para actualizar la clave hash utilizada para el siguiente mensaje. En el lado del servidor, haríamos el mismo hash para saber si el mensaje había sido manipulado, y al mismo resultado, también sabríamos que lanzar la clave de hash con la misma mitad de residuo que teníamos, Pero también haríamos un seguimiento del hashkey anterior. La próxima vez que llegó un mensaje, una de dos cosas fue el caso. Si la transacción anterior había tenido éxito y se iba a acumular en los totales diarios, el terminal usaría su nueva clave hash enrollada para enviar el último mensaje. Si la transacción anterior se revirtió (usuario cancelado, firma incorrecta, etc.), el terminal reutilizaría la clave hash anterior. Al copiar el mensaje con la última clave enrollada y no encontrar ninguna coincidencia, pero al mezclar la clave anterior y encontrar una coincidencia, sabíamos que el destino de la transacción anterior era fallido y lo eliminábamos de los totales diarios.

Las claves hash ocasionalmente se desincronizan; cuando esto sucediera, ninguna de nuestras claves almacenadas produciría un hash correspondiente para el mensaje. Hay una clave más que probar: la clave inicial (los usuarios supervisores podrían restablecer la clave a la inicial, y algunos usuarios parecieron hacer esto ante cualquier problema, creyendo que era algo así como un reinicio), rara vez es el caso y causaron más problemas que ellos. resuelto pero ..). Si la clave inicial funcionó, no podríamos decir con certeza qué sucedió con la transacción anterior, pero por lo general los acumulamos (cobramos en las cuentas de las personas) según la teoría de que las personas se quejarían si no se reembolsaran a su vencimiento, pero no si Se les devolvió algo que habían comprado ...

Si la clave inicial no funcionó, entonces el terminal se volvió realmente inútil, ya que la pérdida de sincronización de la clave significa que ya no pueden funcionar más mensajes. No teníamos la autoridad para decirle al terminal que reinicie su clave, pero podríamos poner un mensaje en la pantalla pidiéndole al usuario que lo haga

En pocas palabras, no tiene que usar el mismo token, si le preocupa que los tokens se capturen y reproduzcan como una contraseña almacenada como alternativa. Otros han señalado opciones para hacer que los tokens expiren después de un tiempo; este método es esencialmente el vencimiento del token después de cada solicitud (similar a otra mención sobre la adición de un número secuencial al token), con una forma interna conocida de calcular un token nuevo en cada lado que debe realizarse en el paso.

Si está interesado en los detalles aburridos de la forma en que lo hace el mundo de las tarjetas de crédito en el Reino Unido, busque el Libro 2 y el Libro 5 de APACS 70 Standard. No están disponibles de forma gratuita. miembro para recibir una copia de las nuevas publicaciones, pero es posible que encuentre el contenido de las versiones anteriores flotando en la web

    
respondido por el Caius Jard 14.11.2017 - 11:53
fuente
1

Así que ... no hay nada que pueda hacer para proteger la máquina cliente para mantener el token seguro en su extremo, pero hay algunas mejores prácticas para la seguridad de JWT:

  1. Implemente tokens de actualización y emita tokens de acceso de corta duración: esto agrega complejidad a cualquier ataque + la forma en que he implementado el token de actualización es con una tabla SQL ... que puede administrar (por ejemplo, arranque instantáneo) .

  2. Elimine el token del cliente al cerrar sesión (este es obvio).

  3. Puedes cifrar el token, pero el cifrado es reversible, nuevamente lo hace más difícil.

  4. Use una clave secreta para firmar sus tokens y gírela según sea necesario (por ejemplo, por lanzamiento). Cambiar la clave secreta invalida todos los tokens anteriores.

También, lee: enlace

Si necesita más seguridad, necesita más mecanismos para proteger al cliente específicamente: incluir en la lista blanca las IP de los usuarios, garantizar que los usuarios tengan capacitación en AV y anti-phishing, etc. ...

    
respondido por el RandomUs1r 15.11.2017 - 00:39
fuente
1

TL; DR un usuario capacitado que esté satisfecho con una tasa de spam razonable seguirá llegando, si no es por otro medio, ingresando su spam a mano .

Haga que la aplicación autentique cada solicitud de forma independiente. Definitivamente no es infalible, y aumenta el tráfico, pero es factible.

De una manera: una publicación de mensaje ya no es una publicación única, sino un GET seguido de POST. El GET suministra un nonce (podría ser la marca de tiempo actual), y el POST debe suministrar el nonce junto con el p. Ej. MD5 del nonce, salado con una aplicación secreta. Por supuesto, debe almacenar las fuentes emitidas para evitar los ataques de reproducción.

También puede proporcionar un número de sesión al iniciar sesión y usarlo durante toda la sesión (por supuesto, el usuario puede interceptarlo y copiarlo en una segunda aplicación de correo no deseado, una vez que haya eliminado el secreto de la aplicación). Sin embargo, esto no es una mejora significativa de la cookie de autenticación.

O puede agregar silenciosamente una validación a todas las solicitudes de la aplicación, en la forma de la marca de tiempo actual más el hash de dicha marca de tiempo incluida en el secreto de la aplicación. La exclusividad se puede garantizar mediante la prevención de dos publicaciones en el mismo segundo cliente.

El servidor luego verifica que la marca de tiempo no esté muy lejos de ahora () y que el hash coincida. Incluso puede omitir la marca de tiempo si es aceptable que el servidor la aplique de manera bruta (para timestamp = now () - 60 to now () + 60; if hash (secret + timestamp) ...).

Ahora, el usuario tiene que hackear el secreto de su aplicación, que es más difícil que solo interceptar el tráfico de la red. Si las cadenas / datos son fácilmente reconocibles en la aplicación, puede agregar un poco de seguridad a través de la oscuridad enviando la marca de tiempo y el hash del secreto más la marca de tiempo de siete segundos antes de 1 . Esto requiere que el usuario realice una ingeniería inversa de la aplicación por completo.

(1) Una vez rompí un esquema de salado probando todas las secuencias de 1 a 32 bytes en un programa, fijadas y con sufijo en la marca de tiempo en hexadecimal, binario y decimal, con un conjunto de separadores que incluyen el no - separador, y verificando si el resultado fue la respuesta al desafío. Esto me permitió no depurar el binario, algo que no habría podido hacer, y tardó veinte minutos en configurarse y dos en ejecutarse. Si la marca de tiempo se hubiera confundido al agregar una constante conocida, no habría tenido éxito. Si la constante fuera grande, no sería práctico ni siquiera saber el truco.

    
respondido por el LSerni 15.11.2017 - 09:08
fuente
1

Como otros lo han mencionado, básicamente no hay nada que puedas hacer una vez que el código se ejecuta en el dispositivo de un usuario. Si se ejecuta en el navegador, la ingeniería inversa del proceso del token es trivial. Si se ejecuta en una aplicación, puede hacer que sea mucho más difícil realizar ingeniería inversa, pero aún es posible.

Para las aplicaciones móviles, el atacante tiene dos opciones:

1) Invierta la ingeniería del protocolo. El enfoque más simple es detectar el tráfico de red. Hay ofuscaciones que puedes poner para hacer eso más difícil (certificado de seguridad, MAC + clave secreta + rotación) pero cualquier atacante determinado eventualmente las atravesará. Sin embargo, si utiliza la fijación de certificados y / o el enfoque de clave secreta, el atacante no podrá simplemente rastrear paquetes para aplicar ingeniería inversa al protocolo. Necesitará descompilar el binario para deshabilitar el anclaje de certificados y / o ubicar la clave secreta en la memoria.

2) Trate la aplicación como una caja negra y automatice la interacción con ella. Esto se podría hacer con una granja de dispositivos físicos (mucho más fácil si iOS con jailbreak / Android rooteado), o con una granja de servidores emuladores Desde la perspectiva de un atacante, este podría ser un enfoque más confiable, ya que sería resistente a cualquier actualización que empuje.

Para protegerse contra el # 1 (descompilación binaria) tiene muchas opciones, pero todas se reducen a la dificultad de la ingeniería inversa, no lo impiden por completo. La fruta de baja altura es la ofuscación binaria y la detección del depurador. Para la ofuscación, puede ofuscar las tablas de símbolos y / u ocultar la lógica de cifrado en funciones de aspecto mundano (o escribirlas directamente en ensamblaje). Para la detección del depurador, existen diferentes técnicas para determinar si un depurador se está ejecutando; Si atrapas uno, puedes bloquear la aplicación o jugar juegos con el atacante.

Protegerse contra el # 2 (emulador / conjunto de dispositivos) es un poco más difícil, pero nuevamente, puede dificultar el trabajo del atacante. Una opción es verificar si el dispositivo tiene jailbreak (esto también se defendería contra # 1) y bloquear la aplicación si lo está. Otra opción, al menos para Android, es el servicio de certificación de Google. Eso debería evitar el escenario de la granja de emuladores, pero no una granja física. Para iOS, Apple lanzó una API de comprobación de dispositivo similar en iOS11, aunque tiene un alcance mucho más limitado.

Si quieres ejemplos de esto en la naturaleza, compra Snapchat.app, que ha implementado muchas de estas características.

    
respondido por el formicophobia 15.11.2017 - 14:16
fuente
0

Si una aplicación está diseñada para autenticar (nombre de usuario / contraseña) una vez y luego emplear un sistema de token para la autorización de los servicios REST, esa aplicación ha creado su propio acceso por la puerta trasera.

Estoy seguro de que esta solución me va a azotar, pero básicamente necesitas autenticarte en cada punto final RESTful.

Puede elegir molestar a sus usuarios y solicitar una contraseña en cada solicitud REST, pero esto puede hacer que su aplicación sea propensa a convertirse en un error.

La otra opción es almacenar las credenciales del usuario en la memoria de la aplicación al iniciar sesión y enviar las credenciales en silencio a los puntos finales REST.

    
respondido por el MonkeyZeus 13.11.2017 - 18:44
fuente

Lea otras preguntas en las etiquetas