Resolución del LAB – IDOR: escalada al panel de admin en Hackers Labs Store
Reconocimiento
El reto es Hackers Labs Store, la tienda ficticia de siempre, esta vez con backend en Flask. Nada más pedir la raíz sin credenciales de plataforma, la aplicación corta en seco: cualquier ruta responde 401 not logged mientras no viaje la cookie de sesión de la plataforma.
curl -sk "$URL/"HTTP/2 401
not loggedGuardamos esa cookie en cookies.txt y la pasamos con -b en todo lo que sigue. Con ella puesta, la tienda se sirve normal: una portada con productos y un menú de /login y /register. La parte interesante está detrás del registro, así que nos creamos una cuenta cualquiera.
curl -sk -b cookies.txt -c app.txt -i \
--data "username=osk&[email protected]&password=Passw0rd123" \
"$URL/register"HTTP/2 302
location: /user/panel?id=27
set-cookie: session=.eJwl...; HttpOnlyEl registro nos autentica de una y nos redirige a nuestro panel. El detalle que salta a la vista está en la propia URL de destino: /user/panel?id=27. El identificador de cuenta no vive en la sesión, viaja en un parámetro de la query string a la vista de todos.
Identificación de la vulnerabilidad
Nuestra cuenta quedó guardada en app.txt. Pedimos nuestro propio panel con esa sesión y confirmamos qué pinta tiene: usuario, email, rol user y una biografía. Todo cuadra con id=27.
curl -sk -b cookies.txt -b app.txt "$URL/user/panel?id=27"La pregunta es obvia: si el id lo elijo yo en la URL, ¿comprueba el servidor que ese id es el de mi sesión antes de servirme el panel? Bajamos el número y pedimos el id=1 con la misma sesión de siempre.
curl -sk -b cookies.txt -b app.txt "$URL/user/panel?id=1"Usuario player
Email [email protected]
Rol user
Biografía Just a regular user exploring the platform.
ID: 1Ni rastro de nuestra cuenta: el panel que vuelve es el de player, un usuario que no somos nosotros. El servidor sirve el registro que pida el parámetro id sin cruzarlo contra el usuario en sesión. Es un IDOR de manual (Insecure Direct Object Reference): la referencia al objeto la controla el cliente y nadie valida la propiedad. Un par de valores más lo confirman.
for id in 2 3; do curl -sk -b cookies.txt -b app.txt "$URL/user/panel?id=$id"; doneid=2 -> alice [email protected] Rol user "Alice loves CTFs."
id=3 -> bob [email protected] Rol user "Security researcher."Explotación
Todos los perfiles que van saliendo son user normales. En una tienda así el premio está en la cuenta de administración, así que recorremos el rango de identificadores buscando el rol admin. El panel de id=23 es el que cambia de color.
curl -sk -b cookies.txt -b app.txt "$URL/user/panel?id=23"Usuario admin
Email [email protected]
Rol admin
Biografía Platform administrator. Flag: THL{XXXXXX}
ID: 23Flag
El panel de administración se abre con la misma sesión de usuario raso con la que empezamos: solo hubo que cambiar un número en la URL. La flag venía escrita en la biografía de la cuenta admin, enmascarada aquí como THL{XXXXXX}.
El fallo no es de autenticación: la sesión es real y válida. El fallo es de autorización. La aplicación autentica quién eres al entrar, pero cuando pides /user/panel?id=23 se limita a buscar el registro 23 y devolverlo, sin volver a preguntarse si ese registro es tuyo. La frontera que cae no es la de la contraseña, es la de asumir que un identificador que viaja en la URL solo lo va a poner quien tiene derecho a ese objeto.
La tienda te daba tu panel por tu id; nunca comprobó que el id que pedías fuera el tuyo, y el 23 llevaba dentro las llaves de la casa.
