Prueba interna de nuestra propia API con tarifa limitada

117

Visión general:

Mi empresa ha desarrollado una API de tasa limitada. Nuestro objetivo es doble:

  • R: Cree un ecosistema de desarrolladores sólido en torno a nuestro producto.
  • B: Demuestre el poder de nuestra API usándola para impulsar nuestra propia aplicación.

Aclaración: ¿Por qué el límite de tasa?

Limitamos nuestra API porque la vendemos como una adición a nuestro producto. El acceso anónimo a nuestra API tiene un umbral muy bajo para las llamadas API por hora, mientras que a nuestros clientes pagos se les permite más de 1000 llamadas por hora o más.

El problema:

Nuestra API de tasa limitada es excelente para el ecosistema de desarrolladores, pero para que podamos probarla, no podemos permitir que se restrinja a la misma limitación de tasa. El front-end de nuestra API es todo JavaScript, que realiza llamadas Ajax directas a la API.

Entonces la pregunta es:

¿Cómo se asegura una api para que se pueda eliminar la limitación de velocidad en los lugares del proceso para eliminar dicha limitación de velocidad no se pueda falsificar fácilmente?

Soluciones exploradas (y por qué no funcionaron)

  1. Verifique la referencia con el encabezado del host. - Defectuoso porque el referente se falsifica fácilmente.

  2. Use un HMAC para crear una firma basada en la solicitud y un secreto compartido, luego verifique la solicitud en el servidor. - Defectuoso porque el secreto y el algoritmo se determinarían fácilmente examinando el JavaScript frontal.

  3. Aproveche la solicitud y firme la solicitud en el proxy: aún tiene fallas, ya que el propio proxy expone la API.

La pregunta:

Estoy mirando a las mentes brillantes de Stack Overflow para presentar soluciones alternativas. Como resolverías este problema?

Jason Waldrip
fuente
13
No puedes. Si su propio uso de la API que no desea que se restrinja a la limitación de velocidad proviene de páginas web públicas, entonces no puede hacer nada seguro desde esas páginas web públicas porque, como parece que ya sabe, hay sin secretos en las páginas web públicas. Entonces, lo que puede hacer en sus páginas web, también puede hacerlo cualquier otra persona.
jfriend00
28
¿Está seguro de que tiene un problema de limitación de velocidad que resolver en su uso de comida para perros? Cada usuario que usa su sitio y sus páginas web debe parecer un usuario completamente diferente a su código de limitación de velocidad. Por lo tanto, solo asegúrese de que cada página web se rija por las reglas normales de limitación de velocidad por sí misma y debería estar bien. Suponiendo que su límite de velocidad es por cliente, un usuario no tendrá nada que ver con ningún otro usuario.
jfriend00
6
¿Por qué no considera una solución de administración de API que proporcione limitación de velocidad y aceleración en un ámbito por usuario, por función / permiso o por aplicación? Por ejemplo, wso2 api manger
MiddlewareManiac
3
Posible duplicado de la tasa que limita una API con una excepción especial
gastador
28
Su prueba interna descubrió un problema significativo con su API pública (que es que el límite de velocidad es demasiado bajo) y, en lugar de solucionarlo, está tratando de evitarlo. ¿Por qué comer perros si vas a ignorar los problemas que encuentres?
user253751

Respuestas:

93

Dado que su propio cliente JavaScript accede directamente a la API, cualquiera podrá ver lo que está haciendo e imitarlo, incluido el uso de la misma clave de API. Puede intentar hacerlo más difícil, por ejemplo, ocultando su código o poniendo varios obstáculos en el camino, pero usted y la persona que está tratando de restringir tienen fundamentalmente el mismo acceso. En lugar de intentar crear una diferencia en los privilegios, deberá construir un sistema en el que esté totalmente bien que el cliente no oficial use todo el acceso en su alcance, pero el sistema está organizado de tal manera que el uso oficial en todos los clientes es mayor.

Esto se hace a menudo con tokens de acceso por usuario, a diferencia de un token para toda la aplicación. El límite de cada token debe ser suficiente para el uso típico de su API, pero restrictivo para alguien que intente abusar de él. Por ejemplo, 100 llamadas por minuto pueden ser más que suficientes para respaldar la navegación típica, pero si quiero rasparlo, no puedo hacerlo de manera efectiva con ese presupuesto.

Siempre habrá una carrera armamentista: puedo superar el límite creando muchas cuentas de usuario de bot. Eso, sin embargo, es un problema bastante resuelto si solo agrega un captcha a su flujo de registro, a un pequeño costo para el humano real. Cuando se adentra en estos escenarios, todo es solo una compensación entre conveniencia y restricción. Nunca encontrarás algo totalmente a prueba de balas, así que concéntrate en hacerlo lo suficientemente bueno y espera hasta que alguien te explote para saber dónde estaban los agujeros.

Kristján
fuente
8
Aceptando esto como la mejor respuesta. La ruta que hemos decidido tomar es utilizar tokens JWT con un vencimiento menor y aumentar el límite de velocidad de esas llamadas. Codificaremos información adicional en el token para que el backend conozca el límite de velocidad más alto. Dado que estos tokens están firmados de forma segura en el backend, no debería haber ningún problema con la suplantación de identidad. Alguien aún podría usar el token, pero caducaría después de unos días y, por lo tanto, sería más difícil mantener cualquier tipo de bot.
Jason Waldrip
33

Si esto le está causando un problema, su ecosistema putativo de desarrolladores será un problema (por ejemplo, cuando intenten desarrollar una interfaz de usuario alternativa). Si realmente está comiendo su propia comida para perros, haga que la API (y la limitación de velocidad) funcionen para su aplicación. Aquí hay algunas sugerencias:

  • No limite la tasa por dirección IP. Más bien, límite de velocidad por algo asociado con el usuario, por ejemplo, su ID de usuario. Aplicar el límite de velocidad en la etapa de autenticación.

  • Diseñe su API para que los usuarios no necesiten llamarla continuamente (por ejemplo, realice una llamada de lista que devuelva muchos resultados, en lugar de una llamada repetida que devuelva un elemento cada vez)

  • Diseñe su aplicación web con las mismas limitaciones que espera que tenga su ecosistema de desarrolladores, es decir, asegúrese de que puede diseñarla con tasas de limitación razonables.

  • Asegúrese de que su back-end sea escalable (preferiblemente horizontalmente) para que no necesite imponer una limitación a niveles tan bajos que en realidad cause un problema en una interfaz de usuario.

  • Asegúrese de que su estrangulamiento tenga la capacidad de hacer frente a las ráfagas, así como de limitar el abuso a largo plazo.

  • Asegúrese de que su limitación realice acciones sensatas adaptadas al abuso que desea eliminar. Por ejemplo, considere hacer cola o retrasar a los abusadores leves en lugar de rechazar la conexión. La mayoría de las interfaces web solo abrirán cuatro conexiones simultáneas a la vez. Si retrasa un intento de abrir un quinto, solo encontrará el caso en el que estén usando una CLI al mismo tiempo que el cliente web (o dos clientes web). Si retrasa la enésima llamada a la API sin un intervalo en lugar de fallar, el usuario final verá que las cosas se ralentizan en lugar de romperse. Si combina esto con solo poner en cola llamadas N API a la vez, solo llegará a las personas que están paralelizando un gran número de llamadas API, que probablemente no sea el comportamiento que desea, por ejemplo, 100 llamadas API simultáneas, entonces una brecha de una hora suele estar lejos peor que 100 llamadas API secuenciales durante una hora.

¿No respondió esto a su pregunta? Bueno, si realmente necesita hacer lo que está pidiendo, limite la tasa en la etapa de autenticación y aplique un límite de tasa diferente según el grupo en el que encaja su usuario. Si está utilizando un conjunto de credenciales (utilizado por sus desarrolladores y el equipo de control de calidad), obtiene un límite de tasa más alto. Pero puede ver de inmediato por qué esto lo llevará inevitablemente a que su ecosistema vea problemas que su equipo de desarrollo y control de calidad no ve.

abligh
fuente
11

Compre su producto. Conviértete en un cliente pago de ti mismo.

"El acceso anónimo a nuestra API tiene un umbral muy bajo para las llamadas a la API por hora, mientras que a nuestros clientes pagos se les permite más de 1000 llamadas por hora o más".

Esto también ayuda a probar el sistema desde la perspectiva del cliente.

jkdev
fuente
1
La respuesta obvia. ¡No hay trampas ni falsificaciones aquí!
wizzwizz4
9

Desafortunadamente, no existe una solución perfecta para esto.

El enfoque general es típicamente para proporcionar una falsificablesforma para que los clientes se identifiquen (por ejemplo, un identificador, versión y clave de API, por ejemplo), para que los clientes registren información sobre sí mismos que se puede utilizar para limitar el acceso (por ejemplo, el cliente es un servidor en un rango de direcciones IP determinado, por lo tanto, solo permita las personas que llaman en ese rango; por ejemplo, el cliente es JavaScript, pero se entrega solo a una categoría específica de navegador, por lo que solo permita el acceso a solicitudes HTTP que especifiquen ciertas cadenas de agentes de usuario, etc.), y luego use aprendizaje automático / patrón reconocimiento para detectar un uso anómalo que probablemente sea un cliente falsificado y luego rechazar el tráfico de estos clientes falsificados (o confirmar con los clientes que estos usos no provienen del cliente legítimo, reemplazar sus credenciales falsas y luego deshabilitar el tráfico adicional utilizando el credenciales falsificadas).

Puede hacer que sea un poco más difícil de falsificar utilizando varias capas de clave. Por ejemplo, proporciona una credencial de mayor duración que reside en un servidor (y que solo se puede usar en un conjunto limitado de rangos de direcciones IP) para realizar una llamada a la API que registra información sobre el cliente (por ejemplo, el agente de usuario) y devuelve una clave del lado del cliente de corta duración que se distribuye en JavaScript para su uso en el cliente para solicitudes de API del lado del cliente. Esto también es imperfecto (un spoofer podría emitir la misma llamada al servidor para obtener la credencial), pero será más difícil si la clave de API devuelta se incluye en JavaScript o HTML ofuscado (y que cambia con frecuencia) (lo que lo haría difícil para extraer de forma fiable de la respuesta). Eso también proporciona una forma de detectar más fácilmente la suplantación de identidad; la clave del lado del cliente ahora está vinculada a un cliente en particular (p. ej.

Michael Aaron Safyan
fuente
8

Suponiendo que la aplicación en cuestión debe estar abierta públicamente, no tiene muchas opciones:

Elija otra forma de demostrar el poder de su API. Por ejemplo, escriba una aplicación de este tipo y comparta su fuente, pero en realidad no ejecute ese código. Sin embargo, asegúrese de que esté bien documentado, para que cualquiera pueda implementarlo y verlo funcionar (sujeto a limitaciones).

La aplicación que ejecute necesitaría ser refactorizada para evitar solicitudes de API del lado del cliente y ser más renderizada por el servidor. Todavía puede probar su API, pero no de una manera obvia: realice solicitudes seguras a la API sin aceleración desde el lado del servidor.

Ajustar la limitación de velocidad para permitir que su aplicación funcione e invierta en la optimización del rendimiento para manejar la carga.

Y sí, tenga la API central libre de aceleración en primer lugar y manténgala dentro de una red privada. Acelere en una capa separada de acceso público.

Anton Strogonoff
fuente
4

¿Puede crear una instancia separada de la interfaz de usuario y la API sin aceleración y luego restringir el acceso a las direcciones IP que provienen de su organización?

Por ejemplo, implemente todo detrás de su firewall corporativo y adjunte la aplicación a la misma base de datos que la instancia pública si necesita compartir datos entre instancias.

Peter Mortensen
fuente
4

Podría intentar generar una ID de sesión única, vinculada a una determinada dirección IP / usuario y con un tiempo de vida limitado. Cuando un usuario descarga el código JavaScript de la interfaz de su aplicación, inyecte el ID de sesión generado en el código fuente de JavaScript. La ID de sesión se adjuntará a cada solicitud a su API y se levantará el límite de velocidad.

La identificación no se puede copiar simplemente para suplantación de identidad, porque solo es válida para una única dirección IP, usuario y un período de tiempo limitado. Por lo tanto, un adversario tendría que llamar a su página y filtrar la clave de su fuente de JavaScript o de interceptar la solicitud Ajax cada vez que un nuevo usuario quiera usarla.

Otra opción:

Configure un proxy para su propia aplicación y use la ofuscación. Las solicitudes de Ajax al proxy utilizan nombres diferentes de las llamadas API reales y el proxy los traduce. Por lo tanto, su aplicación no llamará getDocumenta su API real, pero sí getFELSUFDSKJEa su proxy. El proxy traducirá esta llamada a getDocument y la reenviará a la API de tasa limitada real.

Su API real no limitará las solicitudes por parte del proxy.

Y para que otras personas no utilicen su proxy para su propia aplicación, cambia el esquema de ofuscación a diario. Los nombres de llamada ofuscados se pueden generar automáticamente en su código fuente JavaScript y configurarse en el proxy.

Un cliente que desee usar esto, también necesitará mantenerse al día con su ofuscación cambiante para usar su proxy. Y aún puede usar encabezados de referencia y similares para el registro, para que pueda encontrar personas que usen su proxy. O descárguelos al cambiar el esquema de ofuscación.

Falco
fuente
3
  • Direcciones IP de origen de la lista blanca
  • Usa una VPN , incluya miembros de VPN en la lista blanca
  • La solución de proxy o el complemento del navegador que agrega encabezados HTTP deberían estar bien si puede proteger el proxy y no le preocupa MITM ataques detecten el tráfico.
  • Cualquier solución que involucre secretos puede mitigar el impacto de las filtraciones rotando los secretos a diario.
the8472
fuente
Estas soluciones no se aplican a un cliente web front-end. Perfecto si el acceso a la API estaba en el backend.
Jason Waldrip
@jason todos se pueden aplicar a una interfaz
the8472
2

Configure varias cuentas y elija una de ellas al azar en cada solicitud, o cambie la que usa cada hora aproximadamente. De esta manera, puede distribuir la carga entre las ncuentas, lo que le otorga nlímites hasta veces más altos.

Tenga cuidado con cerrarse accidentalmente si está tratando de encontrar a otros usuarios haciendo esto, si no está permitido para los clientes.

Filip Haglund
fuente