🔐Ciberseguridad

Introducción al pentesting web: metodología y primer laboratorio

Felipe••16 min de lectura
Aprende una metodología de pentesting web con OWASP WSTG, Burp y ZAP. Monta Juice Shop localmente, analiza HTTP y documenta un fallo de autorización.

Una aplicación puede funcionar correctamente en sus recorridos habituales y fallar cuando alguien cambia una petición. El trabajo de una prueba de penetración consiste en formular esas preguntas, comprobarlas de forma controlada y explicar qué consecuencias tienen los resultados.

En este artículo construiremos un primer laboratorio con OWASP Juice Shop, una aplicación deliberadamente vulnerable. Observaremos sus peticiones HTTP y comprobaremos si una cuenta puede leer el carrito de otra cuenta de prueba. El objetivo es aprender un método que produzca evidencia útil para corregir software.

Todo el ejercicio se realiza en tu equipo, con cuentas ficticias y una instancia propia. No necesitas probar una web pública ni utilizar la demo compartida de Juice Shop.

Qué es una prueba de penetración

Una prueba de penetración, o pentest, evalúa si una debilidad puede aprovecharse para vulnerar un control de seguridad y qué impacto permite demostrar dentro del alcance acordado. Combina conocimiento de la aplicación, observación y pruebas dirigidas.

No equivale a ejecutar una herramienta y exportar sus alertas. Tampoco exige llevar cada fallo hasta su consecuencia más dañina: una evidencia mínima puede bastar para confirmar el problema.

La introducción de OWASP Web Security Testing Guide sitúa el pentesting dentro de un programa más amplio que también incluye revisión de código y pruebas durante el desarrollo. Un pentest tiene límites de tiempo y cobertura; no encontrar fallos no demuestra que no existan.

Análisis de vulnerabilidades y pentesting

AspectoAnálisis de vulnerabilidadesPrueba de penetración
FocoIdentificar y valorar debilidadesComprobar escenarios de abuso e impacto
Trabajo habitualInventario, configuración, versiones, herramientas y revisión manualHipótesis, peticiones controladas y validación de controles
EntregaDebilidades detectadas, evidencia y prioridadesHallazgos reproducibles con alcance e impacto demostrado

Hay solapamientos. Un análisis de vulnerabilidades puede incluir validación manual y un pentest puede utilizar escáneres. La diferencia práctica está en la pregunta y la profundidad de la comprobación, no en dividir todo entre «automático» y «manual».

Una alerta sobre una dependencia desactualizada es un punto de partida. Demostrar que una cuenta puede leer datos privados de otra responde una pregunta concreta sobre el comportamiento de la aplicación.

Antes de enviar peticiones: alcance y autorización

En un trabajo profesional, deja por escrito quién autoriza la prueba, qué activos incluye, en qué fechas y con qué restricciones. Tener una cuenta, conocer una URL o trabajar para una organización no define por sí solo ese permiso.

Un acuerdo operativo debería identificar los sistemas incluidos y excluidos, las cuentas de prueba, las acciones admitidas, los límites de tráfico, el contacto para incidentes y las condiciones para detenerse. También debe definir cómo conservar y entregar la evidencia.

Para este laboratorio usaremos este alcance concreto:

ElementoLímite del ejercicio
ObjetivoTu contenedor Juice Shop en http://127.0.0.1:3000
IdentidadesDos cuentas ficticias creadas por ti
AccionesNavegar, registrar cuentas, añadir productos propios y repetir lecturas HTTP
Fuera de alcanceOtras webs, otras máquinas, cuentas ajenas y servicios enlazados por la tienda
ExclusionesFuerza bruta, escaneos masivos, pagos y cambios sobre el carrito de la otra cuenta
FinalizaciónGuardar evidencia depurada y detener el contenedor

Estas son reglas para nuestra práctica. La WSTG es una guía técnica; no sustituye el acuerdo de autorización ni convierte sus recomendaciones en obligaciones legales generales.

Una metodología que puedas repetir

Usaremos referencias de WSTG v4.2, la edición estable indicada por el proyecto OWASP. Los enlaces versionados permiten identificar qué documento seguimos aunque la guía continúe evolucionando.

El recorrido será:

flowchart TD
  A[Definir alcance y autorización] --> B[Reconocer funciones y peticiones]
  B --> C[Establecer una respuesta de referencia]
  C --> D[Probar una hipótesis dentro del alcance]
  D --> E[Validar y conservar evidencia mínima]
  E --> F[Documentar impacto y corrección]
  F --> G[Repetir la prueba tras corregir]

Reconocimiento: comprender la aplicación

En este contexto, reconocer significa identificar funciones, roles, rutas y entradas. Navega primero como un usuario normal: registra una cuenta, busca un producto y abre el carrito.

Anota qué peticiones aparecen, qué parámetros identifican objetos y qué operaciones necesitan sesión. No confundas la ruta visible en una aplicación SPA con la petición que recibe el servidor: /#/basket es una ruta del cliente, mientras que los datos pueden llegar mediante otra URL.

WSTG-INFO-06: Identify Application Entry Points propone estudiar estos intercambios y sus entradas. Un mapa pequeño puede contener método, ruta, autenticación, parámetros y función observada.

Interceptación HTTP: observar antes de modificar

Un proxy de interceptación se coloca entre el navegador y la aplicación. Permite revisar solicitudes y respuestas y, cuando lo decides, detener una petición antes de enviarla.

La captura del historial y la interceptación con pausa son funciones distintas. Puedes navegar con la interceptación desactivada y seguir registrando el tráfico. Después eliges una petición concreta para repetirla y comparar respuestas.

En HTTP, revisaremos método, ruta, cabeceras y cuerpo. Si aparece Authorization: Bearer ..., ese valor es una credencial de la sesión: no debe terminar en capturas públicas o informes sin depurar.

Autenticación, sesión y autorización

La autenticación comprueba la identidad presentada. La sesión permite asociar peticiones posteriores con esa identidad. La autorización decide si puede realizar una operación sobre un recurso.

La WSTG dedica secciones diferentes a autenticación y gestión de sesiones. Algunas preguntas iniciales son:

  • ¿Se rechaza una contraseña incorrecta?
  • ¿Qué credencial se emite al iniciar sesión y dónde se envía después?
  • ¿Una operación privada rechaza peticiones sin esa credencial?
  • ¿Qué ocurre con una credencial anterior después de cerrar sesión o vencer su vigencia?
  • ¿Una cuenta autenticada puede acceder a objetos de otra cuenta?

La comprobación del cierre de sesión requiere observar una respuesta nueva del servidor, no solo una pantalla guardada en caché. WSTG-SESS-06 desarrolla esa prueba. En este primer laboratorio nos centraremos en login, ausencia de token y acceso entre dos cuentas; no evaluaremos toda la recuperación de contraseñas, los tiempos de sesión o los mecanismos de bloqueo.

Si el token es un JWT, recuerda que decodificarlo no equivale a validarlo. Ver información en su payload no demuestra por sí solo una vulnerabilidad.

Burp Suite Community y ZAP: cuál usar para empezar

Ambas herramientas permiten observar tráfico web. Para este ejercicio basta con una de ellas.

NecesidadBurp Suite CommunityZAP
Proxy e historial HTTPIncluidosIncluidos
Repetir una petición manualmenteRepeaterEditor/reenvío de peticiones, según la interfaz instalada
Escaneo automático de vulnerabilidadesEl scanner de Burp corresponde a ProfessionalDispone de análisis pasivo y escaneo activo
DistribuciónEdición gratuita con funciones limitadasGratuito y de código abierto
Uso en esta prácticaNavegación, historial y RepeaterExploración manual y revisión del tráfico

La comparación de funciones procede de PortSwigger y de la documentación de ZAP. ZAP, frecuentemente referido como OWASP ZAP, se presenta actualmente como un proyecto independiente de código abierto.

Para explicar el laboratorio seguiremos Burp Community. Es una elección didáctica: Repeater permite cambiar una sola parte de la petición y observar qué ocurre.

En ZAP, Safe Mode sirve para comenzar observando, pero impide interceptar y reenviar peticiones. Para esas acciones debes definir el contexto y el alcance local y utilizar Protected Mode. No selecciones ATTACK, que activa escaneos sobre nuevos nodos del alcance. Estas diferencias están documentadas en los modos de ZAP.

El análisis pasivo revisa mensajes que pasan por la herramienta; el activo envía peticiones de prueba. Una alerta pasiva necesita interpretación y validación: no es automáticamente un hallazgo confirmado.

Preparar OWASP Juice Shop en local

Necesitas Docker en funcionamiento, un navegador y Burp Suite Community o ZAP. Utiliza una instalación de Docker actualizada, con Engine 28 o superior. La documentación de Docker advierte de limitaciones en versiones anteriores al restringir puertos publicados a localhost.

Fijaremos Juice Shop v20.3.0, la versión utilizada en esta práctica, para que un cambio de latest no modifique el ejercicio sin aviso.

En una terminal Bash o Zsh:

docker pull bkimminich/juice-shop:v20.3.0

docker run --detach --rm \
  --name uncodigo-juice-shop-lab \
  --publish 127.0.0.1:3000:3000 \
  bkimminich/juice-shop:v20.3.0

La publicación explícita en 127.0.0.1 evita exponer ese puerto en todas las interfaces del equipo con la configuración habitual de Docker. No la sustituyas por 3000:3000. Tampoco añadas túneles públicos, montajes de carpetas personales o acceso al socket de Docker.

El contenedor no es una garantía de aislamiento absoluto. Aquí lo usamos como entorno desechable y limitado, siguiendo la instalación oficial de Juice Shop. No hacen falta servicios externos de IA, Web3 ni credenciales de proveedores para este ejercicio.

Comprueba la publicación y espera a que la aplicación responda:

docker port uncodigo-juice-shop-lab

curl --fail --silent --show-error \
  --output /dev/null \
  --write-out '%{http_code}\n' \
  http://127.0.0.1:3000/

El mapeo debe mostrar 3000/tcp -> 127.0.0.1:3000 y la comprobación HTTP debe terminar en 200. Si acabas de iniciarlo y aún no responde, consulta docker logs uncodigo-juice-shop-lab y vuelve a comprobar. Si el puerto o el nombre ya están ocupados, identifica el proceso o contenedor existente antes de continuar; no lo elimines a ciegas.

Puedes registrar también el digest de la imagen descargada para conservar una referencia más precisa que la etiqueta:

docker image inspect bkimminich/juice-shop:v20.3.0 \
  --format '{{index .RepoDigests 0}}'

Capturar el recorrido normal

Configurar el proxy

En Burp Community, inicia un proyecto temporal y abre Proxy → Intercept → Open Browser. Deja Intercept off durante la navegación inicial y visita únicamente http://127.0.0.1:3000.

En Target → Site map, añade ese origen al alcance mediante Add to scope y filtra el historial para mostrarlo. Comprueba que el alcance corresponde a HTTP, 127.0.0.1 y el puerto 3000. El filtro ayuda a organizar el trabajo; no debe tratarse como un cortafuegos que autoriza cualquier petición enviada desde Repeater.

Los pasos se basan en la documentación de PortSwigger sobre interceptación y alcance, adaptados a nuestra instancia local. No necesitas visitar los objetivos de sus tutoriales para seguir este artículo.

Si eliges ZAP, usa Quick Start → Manual Explore con la URL local y su navegador configurado. No pulses Automated Scan para esta práctica. El HTTP local evita tener que instalar una autoridad certificadora en tu navegador personal; no es una configuración para desplegar una aplicación real.

Crear dos cuentas y distinguir sus recursos

Usa únicamente datos ficticios. Los menús siguientes corresponden a la interfaz en inglés; puedes seleccionarla desde el control de idioma de Juice Shop.

  1. Cierra el aviso de bienvenida con Dismiss. Ve a Account → Login → Not yet a customer? para registrar a Bea con [email protected].
  2. Elige una contraseña exclusiva de laboratorio y una respuesta ficticia a la pregunta de seguridad. No reutilices datos personales.
  3. Inicia sesión como Bea, añade un producto al carrito y abre Your Basket.
  4. En Proxy → HTTP history, localiza la lectura GET /rest/basket/<id>. Anota el identificador y el producto del carrito de Bea. No presupongas un número fijo.
  5. Cierra sesión. Registra a Ana con [email protected], inicia sesión y añade un producto diferente a su carrito.
  6. Abre el carrito de Ana y localiza su lectura equivalente. Conserva esta petición como referencia mientras Ana sigue autenticada.

El historial debe permitir relacionar la acción en pantalla con su petición HTTP. En esta versión, el inicio de sesión utiliza POST /rest/user/login y la lectura del carrito utiliza GET /rest/basket/<id>.

Para practicar la pausa de una petición, activa Intercept on, vuelve a abrir el carrito y observa la solicitud antes de pulsar Forward. Después vuelve a Intercept off. Si la página parece quedarse esperando, revisa si el proxy está reteniendo peticiones pendientes.

Probar una hipótesis de autorización

Nuestra hipótesis es: el servidor debería permitir a Ana leer su carrito, pero rechazar la lectura del carrito privado de Bea.

Esta prueba corresponde a WSTG-ATHZ-04: Testing for Insecure Direct Object References. Utilizamos dos cuentas propias para conocer los recursos sin enumerar identificadores de otros usuarios.

En Burp:

  1. Envía la lectura del carrito de Ana a Repeater mediante Send to Repeater.
  2. Comprueba que el destino sigue siendo 127.0.0.1:3000, sin TLS. Reenvía la petición sin cambios y confirma que devuelve el carrito de Ana.
  3. Duplica la petición o conserva la respuesta original. Cambia solo el identificador de la ruta por el identificador del carrito de Bea que anotaste antes.
  4. Mantén la credencial de Ana en Authorization. No copies el token de Bea: eso probaría otra cosa.
  5. Envía una vez y compara el cuerpo con el carrito que observaste legítimamente como Bea.

La documentación de Repeater explica cómo conservar y reenviar estas peticiones. Verifica siempre el destino antes de enviarlas; los enlaces externos de la tienda quedan fuera del ejercicio.

En una respuesta no basta con mirar el 200: comprueba el identificador y los productos. Algunas aplicaciones devuelven errores de negocio dentro de respuestas HTTP exitosas; otras muestran solo el HTML de la SPA. Ninguno de esos casos demostraría por sí solo acceso al carrito de Bea.

Como control adicional, duplica la petición y retira la cabecera Authorization y cualquier cookie de autenticación. No cambies el destino ni pruebes otros identificadores.

Qué observamos en esta versión

Al verificar el laboratorio con Juice Shop v20.3.0 se obtuvo:

PeticiónResultado observado
Ana lee su carrito con su token200, datos del carrito de Ana
Bea lee su carrito con su token200, datos del carrito de Bea
Ana solicita el carrito de Bea con el token de Ana200, datos del carrito de Bea
Petición al carrito sin token401
Inicio de sesión con una contraseña incorrecta de prueba401

La navegación, el registro y los carritos se comprobaron en un navegador; las comparaciones HTTP se automatizaron contra la misma instancia local. Las instrucciones de la interfaz de Burp y ZAP se contrastaron con sus manuales oficiales; no son una afirmación de haber ejecutado ambas aplicaciones de escritorio.

El resultado confirma un fallo de autorización por objeto en el escenario probado. La aplicación exige autenticación, pero no impide esta lectura entre usuarios. No demuestra que se puedan modificar carritos ajenos, acceder a todos los datos o controlar el servidor: esas afirmaciones exigirían otras pruebas y otro alcance.

Juice Shop incluye deliberadamente el reto View Basket, descrito en su guía de controles de acceso. Aquí se utiliza como ejercicio, no como un descubrimiento nuevo sobre un sistema de producción.

Si obtienes una respuesta diferente, conserva la evidencia y revisa versión, cuenta activa, token, ruta e identificador. No cambies arbitrariamente de objetivo para conseguir el resultado del artículo.

Convertir evidencia en un hallazgo útil

Un hallazgo debe permitir que otra persona entienda el problema, lo reproduzca dentro del alcance y compruebe la corrección. La sección Reporting de WSTG ofrece una estructura adaptable para comunicar resultados técnicos y sus consecuencias.

Para nuestro laboratorio, una ficha breve sería:

CampoContenido del hallazgo
IdentificadorLAB-01
TítuloUna cuenta autenticada puede leer el carrito de otra cuenta
EntornoJuice Shop v20.3.0, instancia local propia
PrecondicionesDos cuentas de prueba con carritos distintos y sesión válida de Ana
ReproducciónCapturar la lectura de Ana y sustituir solo la referencia al carrito por la de Bea
Resultado esperadoDenegación sin exponer los datos del carrito de Bea
Resultado observadoRespuesta 200 con el carrito y el producto de Bea
Impacto demostradoLectura no autorizada de contenido de otro carrito del laboratorio
Corrección propuestaAutorizar en el servidor la relación entre usuario autenticado y carrito solicitado
Verificación posteriorAna conserva acceso a su carrito; el acceso al de Bea se rechaza

Adjunta las peticiones y respuestas mínimas que respaldan la comparación, con tokens y contraseñas ocultos. Indica la versión, el momento de la prueba y sus limitaciones. No conviertas un informe en un volcado completo del proxy.

La severidad depende del contexto, la exposición y la sensibilidad de los datos. En este laboratorio no asignaremos un valor CVSS ni afirmaremos un impacto económico que no hemos evaluado. En un encargo real, utiliza el criterio acordado y explica por qué corresponde esa prioridad.

La corrección no consiste en ocultar el ID ni en cambiarlo por uno difícil de adivinar. Hay que comprobar quién puede actuar sobre el objeto, como explicamos en RBAC, ABAC y autorización por recurso. Esa comprobación debe integrarse junto con los demás controles de una API REST.

Cerrar y limpiar el laboratorio

Cuando termines, detén únicamente el contenedor de esta práctica:

docker stop uncodigo-juice-shop-lab

Como lo iniciamos con --rm, Docker elimina el contenedor al detenerlo. No hemos montado volúmenes para conservar sus datos. La imagen descargada permanece disponible por si quieres repetir el laboratorio.

Cierra el navegador de pruebas y elimina sus datos locales si vas a empezar de nuevo. Conserva solo la evidencia depurada que necesites y descarta los historiales con credenciales de laboratorio. No uses comandos de limpieza global como docker system prune: podrían afectar a otros proyectos.

Aprender a comprobar, explicar y corregir

Una buena primera práctica termina con algo más útil que una captura de una alerta: una hipótesis, una comparación reproducible y una explicación de lo que realmente ocurrió.

En este caso, el login rechazó una contraseña incorrecta y el endpoint rechazó una petición sin token. Aun así, una cuenta válida pudo leer el carrito de otra. Seguir ese hilo desde la interfaz hasta el informe permite conectar el pentesting con decisiones concretas de desarrollo y con una prueba que deberá pasar después de corregir el control.

Referencias

#pentesting web#OWASP WSTG#OWASP Juice Shop#Burp Suite Community#ZAP#autorización#laboratorio de seguridad

Artículos relacionados