Doce hallazgos y seis familias
Una consultora prueba la web de un cliente y escribe doce hallazgos. Parecen distintos: una página de error, un enlace raro, un nombre de archivo en una dirección.
Una buena analista lee la lista y ve seis familias. Cada familia tiene una causa y un arreglo. Esta lección te enseña a ordenar hallazgos en familias.
La regla única
Advertencia
Este laboratorio es una web 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 unir una página vulnerable con la familia de fallo que muestra.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Familia de fallo | grupo de debilidades que comparten una causa | |
| Inyección | texto escrito que se lee como parte de una orden o consulta | |
| Recorrido de ruta | nombre de archivo que sale de la carpeta donde debía quedarse | ../ |
| Redirección abierta | enlace que lleva al visitante a la dirección que se le dé | |
| Entrada | todo lo que un visitante escribe o envía a una página | |
| Destino (sink) | el punto del programa donde un valor se usa por fin |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Sigue la entrada hasta su destino
Casi todos los fallos siguen un patrón. Un valor entra desde el visitante. Viaja por el programa. Llega a un destino, donde se usa.
La familia del fallo depende del destino. Hazle una pregunta a cualquier página: ¿dónde acaba lo que escribo?
Ejemplo resuelto: destino y familia
| Dónde acaba el valor | Familia | El arreglo en una línea |
|---|---|---|
| Dentro de una consulta a la base | Inyección SQL | Enviarlo como parámetro |
| Dentro de la página que dibuja el navegador | Cross-site scripting | Escaparlo al mostrarlo |
| Dentro de un nombre de archivo que abre el servidor | Recorrido de ruta | Permitir solo nombres de una lista |
| Dentro de una orden que ejecuta el servidor | Inyección de órdenes | No montar órdenes con texto |
| Dentro de una dirección a la que se envía al visitante | Redirección abierta | Permitir solo direcciones propias |
| Como identificador sin comprobar el dueño | Control de acceso roto | Comprobar el dueño cada vez |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Cada familia deja una señal en la petición
Muchas veces se adivina la familia con una sola petición. Un nombre de archivo con ../ apunta al recorrido de ruta. Una etiqueta dentro de un valor apunta al XSS. Un redirect= con una dirección completa apunta a una redirección abierta.
No hace falta ejecutar nada para clasificar. Lees la petición y preguntas para qué sirve el valor.
Ejemplo resuelto: cinco peticiones inventadas
| Petición | Familia |
|---|---|
| /ver?archivo=../../etc/hosts | Recorrido de ruta |
| /saludo?nombre=<i>Bo</i> | Cross-site scripting |
| /ir?redirect=http://otro.example | Redirección abierta |
| /buscar?id=5 UNION SELECT 1 | Inyección SQL |
| /herramientas?host=a.example; cat notas | Inyección de órdenes |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Mira la web de tu laboratorio
Tu laboratorio ejecuta Mutillidae, una web con muchos fallos a propósito. Arráncalo y ejecuta estos tres comandos en orden. El primero inicia sesión con la cuenta del propio laboratorio y guarda la sesión en un archivo. El segundo consulta esa misma cuenta por su nombre y su contraseña. El tercero consulta un nombre que la web no tiene. Los tres son uso normal.
Inicia sesión con la cuenta del laboratorio
curl -s -c jar -d "username=admin&password=adminpass&login-php-submit-button=Login" -o /dev/null -w "%{http_code} %{redirect_url}\n" "http://www/index.php?page=login.php"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Consulta una cuenta
curl -s -b jar -c jar -G "http://www/index.php" --data-urlencode "page=user-info.php" --data-urlencode "username=admin" --data-urlencode "password=adminpass" --data-urlencode "user-info-php-submit-button=View Account Details" | grep -o "[0-9]* records found"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Consulta un nombre que no existe
curl -s -b jar -c jar -G "http://www/index.php" --data-urlencode "page=user-info.php" --data-urlencode "username=nadie" --data-urlencode "password=nada" --data-urlencode "user-info-php-submit-button=View Account Details" | grep -o "[0-9]* records found"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué te dicen las tres respuestas
El primero imprime 302 y una dirección que acaba en AU1: la web aceptó el acceso. El segundo imprime 1 records found y el tercero 0 records found.
La página cuenta las filas que devuelve su consulta, así que es un destino: el nombre que escribes llega a una consulta a la base. ¿Con qué familia la probarías? Compara tu respuesta con la tabla de arriba.
Un error frecuente
Advertencia
Mucha gente cree que un solo filtro detiene todas las familias de fallo. No es así. Cada destino necesita su propia defensa: un parámetro para la consulta, un escapado para la página, una lista para los archivos. Un filtro único deja huecos en las demás.
Las defensas se apoyan unas en otras
Un buen diseño no depende de una sola defensa. Valida la entrada, usa la herramienta correcta en cada destino y da a cada cuenta solo los permisos que necesita.
Así, si una defensa falla, la siguiente limita el daño.
Para ir más allá: una orden encadenada
En una orden del sistema, && ejecuta la segunda parte si la primera sale bien. Codificado, & es %26, así que /ping?host=10.0.0.5%26%26id es una inyección de órdenes. Las reglas del ejercicio la llaman normal.
Cuando tu ejercicio pase, copia classify en un bloque de código propio. Añade lo necesario para que la detecte, y explica por qué un solo & no puede contar como señal.