Skip to main content

Attacking Jenkins with Shared Libraries

What is Jenkins Shared Library ?

Jenkins shared library is popular where large number of jenkins jobs or pipelines uses a repeated code in pipeline script. The developers creates certain modular functions containing the repetitive code and then reuses across various projects/pipelines/jobs. It is commonly seen in enterprise or organizations where teams work on multiple projects that shares common patterns in every pipelines. Imagine a function to send notifications to Slack about a build passed/failed can be used by many jobs.

These shared functions are often kept in some SCM like github and may or maynot be publicly accessible. As they are helper functions and does not carry any customer data/code, the scm repository is usually not private sometimes. 

What does the project structure of Jenkins Shared Library looks like?


As copied from ( https://www.jenkins.io/doc/book/pipeline/shared-libraries/ )

(root)
+- src                     # Groovy source files
|   +- org
|       +- foo
|           +- Bar.groovy  # for org.foo.Bar class
+- vars
|   +- foo.groovy          # for global 'foo' variable
|   +- foo.txt             # help for 'foo' variable
+- resources               # resource files (external libraries only)
|   +- org
|       +- foo
|           +- bar.json    # static helper data for org.foo.Bar

Most of the groovy code for these wrappers are usually placed in the vars directory. Hence if you write some wrapper code, you would place it in vars directory

You can have a look at this repository for reference https://github.com/darinpope/github-api-global-lib

Note : As an attacker if you find any codebase or SCM repository of the similar pattern, then you can confirm that you have found a Jenkins Shared Library.

Why as an attacker this could be interesting to us ?


As discussed above, the shared libraries are used in organization where there lots of jobs are running for lot of projects. Each project can have multiple jobs running against each pull request. This explains there is a great volume of jobs running. As an attacker we can get very creative here, like :

  • We can exfiltrate data from each of the build environment.
  • We can inject malicious build pipeline to put a backdoor in the artifacts.
  • Most importantly, we can compromise on large scale and remain stealthy, depending on how many jobs are executing the shared-library in their build.


Attack Methodologies 


We will discuss couple of ways by which we can attack Jenkins using the shared library.  


Attack Methodology 1 : By directly modifying the Shared Library Code

Imagine you got some credentials or access tokens that gave you access to SCM and then you got write access to a SCM repository containing the shared library code. You can navigate inside the vars directory and backdoor the groovy code from the existing library. Here for example I have added little exfiltration to helloWorld function call.

This is the original code

def call(Map config = [:]) {
            sh "echo Hello ${config.name}. Today is ${config.dayOfWeek}."
}

This is the backdoored code


We need to ensure the backdoor code fulfils some properties. 

  • The backdoor code should not break the pipeline ( should always be successful ).
  • Should leave as little footprint as possible.
In the example we have used the set +x command to suppress the bash output for each of the steps. Next we also used curl to run in silent mode to avoid those extra debug outputs.

Attack Methodology 2 : By changing the shared library location

Assume you got access to Jenkins console by some exploit or credentials. If you can see some build logs and have enough access to update configuration this method will still work. Remember, sometimes you can still get access rights to update configuration inspite of not being an Administrator. 

At first we will try to find the location of the shared library from the build logs.



Assume in this case you don't have write access to the SCM repository but you can view the code in the SCM repository. In such case what you can do is,

Create a new SCM repo, copy the code, modify the code and then update the shared library location in Jenkins with the new repository link and branch name.

Manage Jenkins -> Configure System -> Global Pipeline Libraries


Analyzing the results.

Each of the projects had a different pipeline script and each of the script executed our malicious shared-library code. All green checks represents the last build was successful.

Here is the pipeline script of  Job 1 project

@Library("shared-libraries") _
pipeline{
    agent any
    stages {
        stage("example"){
            steps{
                sh "echo Just a job1"
                helloWorld(name:"User1",dayOfWeek:"Monday")
            }
        }
    }
}

Here is the pipeline script of  Job 2 project

@Library("shared-libraries") _
pipeline{
    agent any
    stages {
        stage("example"){
            steps{
                sh "echo Just a job2"
                helloWorld(name:"User2",dayOfWeek:"Tuesday")
            }
        }
    }
}


Here is the pipeline script of  Job 3 project

@Library("shared-libraries") _
pipeline{
    agent any
    stages {
        stage("example"){
            steps{
                sh "echo Just a job3"
                helloWorld(name:"User3",dayOfWeek:"Wednesday")
            }
        }
    }
}


Now we can review our request catcher output window


We found the requests initiated by the curl and exfiltrated the environment variables. We can decode the base64 values and get the data.

What else can we do ?

Say for example we have a Java Enterprise Project. We can modify the Shared Library to add some pipeline script to download some JSP backdoor and add them to the project locations. In this way we will get a backdoored artifact.

What can be done for prevention?

  • All users should not have roles to change the configuration of the Shared Library Location.
  • Maintain logs and audit trails and trigger alert whenever there is a change in the Shared Library Location placeholder.
Resources:
  • https://github.com/darinpope/github-api-global-lib
  • https://www.jenkins.io/doc/book/pipeline/shared-libraries/

Popular posts from this blog

KringleCon : Sans Holiday Hack 2018 Writeup

SANS HOLIDAY HACK 2018 Writeup , KRINGLECON The objectives  Orientation Challenge  Directory Browsing  de Bruijn Sequences  Data Repo Analysis  AD Privilege Discovery  Badge Manipulation  HR Incident Response  Network Traffic Forensics  Ransomware Recovery  Who Is Behind It All? First I go to Bushy Evergreen and try to solve the terminal challenge . Solving it is fairly easy , Escape_Key followed by  ":q" without quotes After this we move to the kiosk and solve the questions The question were based on the themes of previous Holiday Hack Challenges. Once we answer it correctly we get the flag. For this I visited Minty Candycane and I tried to solve the terminal challenge.  The application has command injection vulnerability , so injecting a system command with the server ip allows execution of the command. So first I perform an `ls` operation to list of the directory contents , followed by a cat of t

Linux Privilege Escalation : SUID Binaries

After my OSCP Lab days are over I decided to do a little research and learn more on Privilege Escalation as it is my weak area.So over some series of blog post I am going to share with you some information of what I have learnt so far. The methods mentioned over here are not my own. This is something what I have learnt by reading articles, blogs and solving CTFs SUID - Set User ID The binaries which has suid enabled, runs with elevated privileges. Suppose you are logged in as non root user, but this suid bit enabled binaries can run with root privileges. How does a SUID Bit enable binary looks like ? -r- s r-x---  1 hack-me-bak-cracked hack-me-bak         7160 Aug 11  2015 bak How to find all the SUID enabled binaries ? hack-me-bak2@challenge02:~$ find / -perm -u=s 2>/dev/null /bin/su /bin/fusermount /bin/umount /usr/lib/openssh/ssh-keysign /usr/lib/eject/dmcrypt-get-device /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/gpasswd /usr/bin/newgrp /usr/bin

Bluetooth Low Energy : Build, Recon,Enumerate and Attack !

Introduction In this post I will try to share some information on bluetooth low energy protocol. Bluetooth Low Energy ( BLE ) is Bluetooth 4.0.It has been widely used in creating "smart" devices like bulbs that can be controlled by mobile apps, or electrical switches that can be controlled by mobile apps. The terms Low Energy refers to multiple distinctive features that is operating on low power and lower data transfer. Code BLE Internals and Working The next thing what we need to know is a profile. Now every bluetooth device can be categorized based on certain specification which makes it easy. Here we will take a close look into two profiles of Bluetooth which is specifically designed for BLE. Generic Access Profile (GAP) - This profiles describes how two BLE devices defines discovery and establishment of connection with each other. There are two types of data payload that can be used. The Advertising Data Payload and Scan Response Payload . The GAP uses br