Posted in

Pentesting en APIs (Parte 3) – OWASP Top 10

En esta serie de entradas, repasaremos algunas técnicas para realizar pentesting sobre APIs. En esta tercera entrada revisaremos los siguientes cinco riesgos del OWASP Top 10 2023 para APIs y veremos algunos escenarios prácticos.

Antes de comenzar, si estás viendo este contenido por primera vez, te recomendamos ver las partes anteriores para entender los fundamentos y los primeros cinco riesgos de OWASP:

Bien, ahora sí, comencemos:

El contenido teórico de este artículo ha sido tomado en su mayoría de la página de OWASP. Si deseas profundizar en el entendimiento de algún escenario, puedes consultar directamente en el sitio de owasp.org .

API 6 Unrestricted Access to Sensitive Business Flows

El desarrollo de APIs se realiza generalmente con el propósito de que una organización o negocio exponga algún servicio que será consumido por sus clientes o por otras aplicaciones, dentro del contexto de una aplicación. Cuando se crean endpoints, es importante entender esos flujos de negocios que serán expuestos, ya que algunos son más sensibles que otro.

Para que este escenario de riesgo sea aprovechado, un atacante debe entender cuales son los endpoints que se utilizan en un determinado flujo, y como trabajan juntos, a fin de bypassear los controles que puedan existir. Si logra conseguirlo, podría causar que esa lógica del flujo se rompa, y aprovecharlo para realizar acciones no legítimas o no contempladas por el negocio.

Veamos un ejemplo de este escenario:

  • Utilizando nuestro entorno rest-api-goat, vamos a consultar la lista de clientes del Banco 1. Vemos que la consulta nos arroja los saldos de los clientes Juan y Attahua:
  • Bien, dentro de las funcionalidades de esta implementación, está la transferencia de dinero. El proceso tiene 3 endpoints: transfer, process_transfer y confirm_transfer. En el primero se ordena la transferencia, en el segundo se procesa si es que no hay errores en la primera petición, y la tercera finalmente se confirma la transferencia. Veamos un ejemplo:
API Endpoint transfer
API Endpoint process_transfer
API Endpoint confirm_transfer
  • Como pudimos ver, hemos transferido la cantidad de 100 del usuario 5 (Ataahua) a usuario 3 (Juan), el monto era válido, y Ataahua dispone de fondos, por lo que la operación se procesa sin errores con ID 3 y finalmente se confirma. Veamos ahora como se movieron los saldos:
  • Ok, hasta aquí no hay ningún problema. Pero veamos que sucede si alteramos la lógica funcional, considerando un monto negativo, lo cual, no debería ser aceptado:
Petición con monto negativo
Transferencia procesada sin errores
Transferencia confirmada
  • Vimos que la transacción se proceso y se confirmo de manera correcta. Ahora veamos que sucedió con los saldos:
  • Aunque la transferencia debería ser de Ataahua hacia Juan. Vemos que finalmente Ataahua aumentó su saldo en 500 soles, extrayendo dinero de la cuenta de Juan.
  • Vayamos un paso más allá y hagamos una transferencia del usuario Robert al usuario Juan, excediendo los límites de su saldo:
  • Como vemos, el procesamiento es erroneo, puesto que Robert tiene solo 1024 de saldo, y estamos tratando de transferir 2000. Nada fuera de lo normal. Cualquier aplicación controlaría esto. Sin embargo, veamos que pasa si en vez de poner 2000 en el monto, hacemos dos peticiones de 1000 cada una. Este monto ya se encuentra dentro de los límites:
Primera petición de transferencia con ID 7
Segunda petición de transferencia con ID 8
  • Aunque esto no debería ser posible, se está evadiendo la regla de negocio que seguramente busca que el origen disponga de fondos suficientes para realizar una transferencia. Procesamos y confirmamos la transacción, y vemos que pasa sin errores:
  • Ahora consultamos los saldos de Robert y Juan, y veamos lo que ha sucedido:
  • Al inicio, Juan tenía 851.2 y ahora cuenta con 2000 más, dando un total de 2851.2, mientras que Robert ahora tiene saldo negativo, lo cual es inconsistente.

API 7 Server Side Request Forgery

Las arquitecturas tecnológicas que soportan una aplicación, no están conformadas por un único servicio. Es usual encontrar múltiples servicios que permiten que una aplicación funcione, y estos servicios pueden estar en recursos internos que normalmente no son accesibles por un usuario o aplicación.

La vulnerabilidad de Server Side Request Forgery, que también está presente en e OWASP Top 10 para aplicaciones, consiste en aprovechar las APIs expuestas para comprometer esos servicios internos. En términos simples, el atacante usa las APIs como un «puente» para afectar a otros sistemas/servicios, ya sea dentro de la misma red o en internet. Esto puede ocurrir debido a que las APIs consumen servicios internos sin procesar adecuadamente lo que ha sido ingresado por el usuario o aplicación.

Veamos un caso práctico de este tipo de vulnerabilidad.

  • Para demostrar este escenario, vamos a utilizar nuestro entorno preparado de DVGA. Esta aplicación permite publicar «pastes», y como parte de sus funcionalidades, se puede importar un paste de una ubicación remota:
  • Veamos ahora, como se ejecuta esta acción a través de la petición, utilizando GraphQL. Para nuestro ejemplo, ingresaremos como parámetros el servicio que tenemos implementado de rest-api-goat:
  • Como vemos, se ha importado el contenido de la página de rest-api-goat con normalidad. Esto ocurre porque el servicio res-api-goat está expuesto públicamente, pero ¿qué pasaría si en vez de agregar un servicio expuesto, apunto al localhost para traer información de un servicio que es interno, cuyo propósito es diferente?.
  • Para hacer esto, levantaremos un pequeño servicio HTTP, pero que correrá en modo localhost dentro del contenedor:
  • Este servicio no puede ser consultado desde fuera:
  • Pero aprovecharemos las capacidades de nuestra API Graph para importar el contenido que corre internamente en el servicio 8880:
  • El contenido se importó con éxito:

API 8 Security Misconfiguration

Tal como su nombre lo indica, este escenario de riesgo está asociado a una inadecuada configuración de seguridad. Tengamos en cuenta que, las APIs y los sistemas que las soportan, necesitan configuraciones (muchas veces complejas) para que puedan ser utilizadas de manera segura. Cuando no se han seguido los pasos correctos, se dejan puertas abiertas que pueden ser aprovechadas por los atacantes. Una API podría ser vulnerable si:

  • No existe un adecuado proceso de hardening sobre el stack de la API o si hay permisos configurados incorrectamente en los servicios en la nube.
  • Faltan los últimos parches de seguridad o los sistemas están desactualizados
  • Se habilitan funciones innecesarias (por ejemplo, verbos HTTP, funciones de registro)
  • Existen discrepancias en la forma en que los servidores procesan las solicitudes entrantes en la cadena de servidores HTTP
  • Falta la seguridad de la capa de transporte (TLS)
  • Las directivas de seguridad o control de caché no se envían a los clientes
  • Falta una política de uso compartido de recursos de origen cruzado (CORS) o está configurada incorrectamente.
  • Los mensajes de error incluyen seguimientos de pila o exponen otra información confidencial

Veamos un ejemplo de esto:

  • Utilizando Tiredful, vemos que existe un endpoint que permite consultar ISBNs de libros. Nos da también algunos ISBN válidos:
  • Veamos que pasa si ingresamos un ISBN inexistente o incorrecto:
  • Como podemos observar, la aplicación no contiene los errores, sino que los muestra de manera explicita, revelando la versión de Python usada y los frameworks y librerías que se usan como parte de la implementación.

Ahora veamos otro ejemplo:

  • Desde DVGA, vamos a ejecutar un query sobre la API graphql, que como sabemos, nos permite crear o importar pastes, pero esta vez, ingresaremos como parte del cuerpo de la query, el término system:
  • Vemos que en vez de restringirnos, nos arroja un mensaje indicándonos sugerencias de comandos. Utilizaremos systemDebug:
  • Como vemos, nos da información sobre el proceso que está levantando el servicio, además del tiempo que lleva ejecutándose.

API 9 Improper Inventory Management

Este escenario de riesgo, está asociado a la ausencia de un inventario adecuado de las APIs que se exponen como parte de un servicio, lo cual permite tener un mayor nivel de control sobre ellas. Un inventario adecuado de hosts y versiones de API implementadas también es fundamental para mitigar problemas como versiones de API obsoletas y endpoints de depuración expuestos.

Otro punto importante que suele representar un riesgo, es la falta de documentación clara y actualizada sobre las APIs. Esto puede causar que ante la rotación del equipo de desarrollo, se tengan esfuerzos adicionales (lo cual incrementa el costo), para su corrección o actualización.

API 10 Consumo inseguro de APIs

Este escenario ocurre cuando se parte de la premisa que el consumo de una API es «más seguro» si la petición la origina una aplicación y no un usuario final. Asumir que los datos de una aplicación tercera no necesita los mismos niveles de seguridad que los datos proporcionados por un usuario, ya que estos deberían darse bajo un formato específico, es un error, ya que recordemos que un atacante no solo explorará directamente el servicio expuesto de una organización, sino también sus integraciones con terceros, y podría conducir el ataque desde allí.

Veamos un escenario. Aunque no es directamente una representación del riesgo que acabamos de explicar, nos ayudará a entender el concepto:

  • Supongamos que en nuestra aplicación DVGA, la importación de pastes es restringida a otras capas de aplicación, por lo que ahora, asumimos que tanto el host, como el path van a ser siempre direcciones válidas. Al decidir no incluir validaciones adicionales, podría suceder que un atacante, comprometa esta integración y pueda ejecutar peticiones malformadas:
  • Como vemos, no se está validando que el Path este sanitizado, por lo que al añadir el comando uname -a, el servidor nos arroja una respuesta con salida de dicho comando.

Bien, eso es todo en esta serie de entradas. Esperemos que les haya sido de utilidad

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *