La factura 2041 y la 2042
Pagas un recibo en la web de una empresa y la dirección de la página acaba en 2041. Por curiosidad la cambias por 2042.
La página te enseña el recibo de otra persona: su nombre, su dirección, lo que compró. No rompiste nada. La web nunca comprobó de quién era ese recibo.
La regla única
Advertencia
Este laboratorio es una tienda insegura a propósito. Ataca solo tu copia privada, que no tiene salida a internet. Atacar un sistema que no es tuyo, o que no tienes permiso para probar, es delito en casi todos los países.
Al final de esta lección
Nota
Puedo decir si una petición debió permitirse.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Autenticación | comprobar quién eres | |
| Autorización | comprobar qué puedes hacer | |
| Rol | grupo de permisos que se da a una persona | admin |
| Identificador | número o nombre que señala un registro | /pedidos/2041 |
| Código de estado | número con que una web resume cómo fue una petición | 404 |
| Token | texto firmado que el navegador envía para probar que ya has iniciado sesión |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Dos preguntas distintas
La autenticación pregunta: ¿quién eres? La autorización pregunta: ¿puedes hacer esto? Son dos comprobaciones separadas.
Muchas webs débiles hacen la primera y olvidan la segunda. Saben que eres cliente, así que te enseñan lo que pidas, incluso lo de otros clientes.
Ejemplo resuelto: dos comprobaciones
| Situación | Autenticación | Autorización |
|---|---|---|
| Lucía abre su propio pedido | Correcta | Permitida: el pedido es suyo |
| Lucía abre el pedido de Mario | Correcta | Debe negarse: no es suyo |
| Un visitante abre un pedido | No hay sesión | Debe negarse |
| Una administradora abre cualquier pedido | Correcta | Permitida por su rol |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un código de estado resume la petición
Toda respuesta empieza con un código de estado. 200 significa que aquí está. 401 significa que la web no sabe quién eres. 403 significa que lo sabe y la respuesta es no.
Los tres comandos de abajo piden cosas a la tienda de tu laboratorio sin iniciar sesión. Fíjate en qué entrega.
Una página para todos: un producto
curl -s -o /dev/null -w "%{http_code}\n" http://juice-shop:3000/api/Products/1Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Una página para quien inició sesión: usuarios
curl -s -o /dev/null -w "%{http_code}\n" http://juice-shop:3000/api/UsersSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué dice la tienda cuando niega
curl -s http://juice-shop:3000/rest/basket/1 | grep -o "<title>[^<]*</title>"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejemplo resuelto: leer las tres respuestas
| Petición | Estado | Qué te dice |
|---|---|---|
| /api/Products/1 | 200 | Un producto es público, así que cualquiera lo lee |
| /api/Users | 401 | La tienda quiere saber quién pregunta antes de listar personas |
| /rest/basket/1 | 401 | Una cesta es privada. La tienda pide antes un token |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un número en la dirección no autoriza
Si una dirección lleva /pedidos/2041, la web debe comprobar que el pedido es de quien lo pide. Esconder el número no protege: cualquiera puede probar el siguiente.
La comprobación va en el servidor, en cada petición, comparando la cuenta de la sesión con el dueño del registro.
Un error frecuente
Advertencia
Mucha gente cree que basta con no poner un enlace a la página de administración. No es así. El enlace oculto sigue existiendo y se puede escribir a mano. Protege la página con una comprobación de rol en el servidor, y no confíes en lo que el navegador muestre u oculte.
Leer un registro de peticiones
Un registro anota quién pidió qué. Para decidir si una petición debió permitirse necesitas tres datos: quién pidió, qué pidió y de quién es el recurso.
Con eso aplicas una regla: el dueño puede, la administración puede y nadie más.
Una regla de acceso en Python
OWNER = {"2041": "lucia", "2042": "mario"}
ADMINS = ["sofia"]
# Cambia user y order, pulsa Run y mira si se permite.
user = "lucia"
order = "2042"
if user in ADMINS or (order in OWNER and OWNER[order] == user):
print("permitido")
else:
print("negado")
Para ir más allá: un rol de soporte
El equipo de soporte necesita leer cualquier pedido para atender reclamaciones, pero nunca debe entrar en /admin/.
En la regla de Python de arriba, añade SUPPORT = ["pablo"] y cambia la condición para que pablo lea el pedido 2041. Después escribe en una frase por qué un rol nuevo es más seguro que hacer administrador a pablo.