Page cover

💻Broken Object Level Authorization

Las API web permiten a los usuarios solicitar datos o registros mediante el envío de diversos parámetros, incluyendo identificadores únicos como Universally Unique Identifiers(UUIDs), también conocidos como Globally Unique Identifiers(GUIDs), e identificadores enteros. Sin embargo, no verificar de forma correcta y segura que un usuario posee la propiedad y el permiso para ver un recurso específico object-level authorization mechanisms puede provocar la exposición de datos y vulnerabilidades de seguridad.

Un endpoint API web es vulnerable a Broken Object Level Authorization(BOLA), también conocido como Insecure Direct Object Reference(IDOR), si sus verificaciones de autorización (implementadas en el nivel del código fuente) no logran garantizar correctamente que un usuario autenticado tenga suficientes permisos o privilegios para solicitar y ver datos específicos o realizar ciertas operaciones.

Omisión de autorización mediante clave controlada por el usuario

El punto final contra el que practicaremos es vulnerable a CWE-639: Authorization Bypass Through User-Controlled Key.

Escenario

El administrador de Inlanefreight E-Commerce Marketplace nos ha proporcionado las credenciales htbpentester1@pentestercompany.com:HTBPentester1 y quiere que evaluemos qué vulnerabilidades de API puede explotar el usuario con sus roles asignados.

Dado que la cuenta pertenece a un proveedor, utilizaremos el endpoint /api/v1/authentication/suppliers/sign-in para iniciar sesión y obtener un JWT:

GIF que muestra el uso de Swagger UI para enviar una solicitud a una llamada API.

Para autenticarnos con el JWT, lo copiaremos de la respuesta y haremos clic en el botón Authorize. Observe el icono del candado, actualmente desbloqueado, que indica que no estamos autenticados. A continuación, pegaremos el JWT en el campo Value de la ventana emergente Available authorizations y haremos clic en Authorize. Al finalizar, el icono del candado estará completamente bloqueado, confirmando nuestra autenticación.

GIF que muestra la autorización mediante un token JWT.

Al examinar los endpoints dentro del grupo Suppliers (observe cómo tienen un candado en su extremo derecho, lo que indica que se requiere autenticación), notaremos uno llamado /api/v1/suppliers/current-user:

Interfaz de usuario Swagger para API de proveedores. Puntos finales: Obtener todos los proveedores, obtener proveedores por ID, contar proveedores por nombre, obtener el proveedor actual, obtener todos los informes trimestrales, obtener informes por ID.

Los endpoints que contienen current-user en su ruta indican que utilizan el JWT del usuario autenticado para realizar la operación especificada, que en este caso es recuperar los datos del usuario actual. Al invocar el endpoint, recuperaremos la empresa del usuario actual ID, con un valor Guid: b75a7c76-e149-4ca7-9c55-d9fc4ffa87be

Solicitud GET para /api/v1/supplier-companies/current-user. Sin parámetros. Respuesta: Detalles de la empresa proveedora con ID, nombre "PentesterCompany", correo electrónico y otros atributos.

Recuperemos entonces los roles de nuestro usuario actual. Tras invocar el endpoint /api/v1/roles/current-user, este responde con el rol SupplierCompanies_GetYearlyReportByID:

Solicitud GET para /api/v1/roles/current-user. Sin parámetros. Respuesta: Roles del usuario, incluido "SupplierCompanies_GetYearlyReportByID".

En el grupo Supplier-Companies, encontramos un endpoint relacionado con el rol SupplierCompanies_GetYearlyReportByID que acepta un parámetro GET /api/v1/supplier-companies/yearly-reports/{ID}:

Endpoints de API de empresas proveedoras

Al expandirlo, notaremos que requiere el rol SupplierCompanies_GetYearlyReportByID y acepta el parámetro ID como un entero y no un Guid:

Solicitud GET para /api/v1/supplier-companies/yearly-reports/{ID}. Requiere el rol: SupplierCompanies_GetYearlyReportByID. Parámetro: ID (entero). Respuesta: JSON con mensaje de error.

Si usamos 1 como ID, recibiremos un informe anual perteneciente a una empresa con el ID f9e58492-b594-4d82-a4de-16e4f230fce1, que no es al que pertenecemos, b75a7c76-e149-4ca7-9c55-d9fc4ffa87be:

Solicitud GET para /api/v1/supplier-companies/yearly-reports/1. Respuesta: Informe anual con ID 1, ID de empresa, año 2020, ingresos 794425112 y comentarios de la alta dirección elogiando el rendimiento.

Al probar otras identificaciones, aún podemos acceder a informes anuales de otras empresas proveedoras, lo que nos permite acceder a datos comerciales potencialmente confidenciales:

Solicitud GET para /api/v1/supplier-companies/yearly-reports/13. Respuesta: Informe anual con ID 13, ID de empresa, año 2020, ingresos 588820631 y comentarios de la alta dirección elogiando la dedicación.

Además, podemos abusar masivamente de la vulnerabilidad BOLA y obtener los primeros 20 informes anuales de las empresas proveedoras:

GIF que muestra el abuso masivo de BOLA para obtener los primeros 20 informes anuales.

Los únicos cambios que debemos realizar al comando cURL copiado desde la Swaggerinterfaz son usar un Bash for-loopcon variable interpolation, agregar una nueva línea después de cada respuesta usando el indicador -w "\n", silenciar el progreso usando el indicador -sy canalizar la salida a jq :

Prevención

Para mitigar la vulnerabilidad BOLA, el endpoint /api/v1/supplier-companies/yearly-reports debe implementar una verificación (a nivel de código fuente) para garantizar que los usuarios autorizados solo puedan acceder a los informes anuales asociados a su empresa afiliada. Esta verificación implica comparar el campo companyID del informe con el del proveedor autenticado companyID. El acceso solo se concederá si estos valores coinciden; de lo contrario, se denegará la solicitud. Este enfoque mantiene eficazmente la segregación de datos entre los informes anuales de las empresas proveedoras.


Caso práctico

Explota otra vulnerabilidad de autorización de nivel de objeto roto y envia la flag.

Vamos a Autenthication y en el request body ponemos nuestras credenciales:

Al darle a execute nos devuelve el token JWT:

Copiamos el valor del token y le damos a authorize:

Al ver el endpoint /current-user nos da el ID de la empresa que no es a la que pertenecemos:

Y si vamos a /quarterly-reports/{ID} podemos dumpear informes confidenciales de esa empresa usando un ID entero:

Por lo que usaremos el siguiente script para dumpearlos:

Tenemos la flag!

Última actualización

¿Te fue útil?