For full details on this research, see the X-Force Red whitepaper “Controlling the Source: Abusing Source Code Management Systems”. This material is also being presented at Black Hat USA 2022.

Source Code Management (SCM) systems play a vital role within organizations and have been an afterthought in terms of defenses compared to other critical enterprise systems such as Active Directory. SCM systems are used in the majority of organizations to manage source code and integrate with other systems within the enterprise as part of the DevOps pipeline, such as CI/CD systems like Jenkins. These SCM systems provide attackers with opportunities for software supply chain attacks and can facilitate lateral movement and privilege escalation throughout an organization.

This blog post will review a background on SCM systems, along with detailing ways to abuse some of the most popular SCM systems including GitHub Enterprise, GitLab Enterprise and Bitbucket to perform various attack scenarios. These attack scenarios include reconnaissance, manipulation of user roles, repository takeover, pivoting to other DevOps systems, user impersonation, and maintaining persistent access. X-Force Red’s source code management attack toolkit (SCMKit) will also be shown to perform and facilitate these attacks. Additionally, defensive guidance for protecting these SCM systems will be outlined.

Background

There are many ways to interact with and track source code, along with compiled source code assets. Some of the common terms used in this process are source control, version control, and source code management. The terms “source control” and “version control” are often used interchangeably with each other. However, there are differences between these two terms. Source control is specifically for tracking changes in source code, whereas version control also includes tracking changes for binary files and other file types. An example of this would be version control tracking changes to compiled executables, whereas source control would be tracking the changes to the underlying C# or C++ source files that were compiled into that executable. Git is a popular source control tool, and Subversion is a popular version control tool.

To use source control in a practical manner as part of the development process, source code management (SCM) systems are used. These systems allow tracking changes to source code repositories and allow developers to resolve conflicts when merging code commits from multiple people concurrently. Some of these SCM systems are more popular than others and have been adopted by enterprises, as they integrate into the development process in a more reliable manner. Some of the popular SCM systems include GitHub Enterprise, GitLab Enterprise and Bitbucket. Due to the role and importance of these SCM systems, they can be abused to facilitate software supply chain attacks and lateral movement within an organization.

SCM Systems and the DevOps Pipeline

SCM systems are heavily used during the “build” phase of a project in the DevOps pipeline, as shown in the below diagram. All other phases depend on the source code that is developed and maintained within the SCM system. Once a source code project is ready to be compiled and built, it will get pushed to a Continuous Integration (CI) server. After that, it will be tested, scanned, and deployed for use in production.

DevOps Pipeline Diagram

Software Supply Chain Attacks

An attack that has been gaining popularity recently is software supply chain attacks. In this attack, an attacker injects itself into the development process at one of the phases to deploy malicious code into production. This is typically performed in the “build” phase. For organizations that provide software to other organizations, this can enable the compromise of multiple organizations. One of the most notable software supply chain attacks was the SolarWinds breach, which impacted many organizations in the private and public sector.

The below diagram shows the opportunities an attacker has during the development process to implement a software supply chain attack. This research focuses on the highlighted areas of “B” and “C”, as it relates to the compromise of SCM systems. However, the compromise of these SCM systems can also lead to other scenarios such as “D” where an attacker can use an SCM system to compromise a build platform system.

Software Supply Chain Attack Opportunity Diagram

Lateral Movement to Other DevOps Systems

SCM systems can be used as an initial access point to other DevOps systems that are used in separate phases of the DevOps lifecycle. Being able to pivot to the build system to compromise the CI/CD platform or pivoting to the package repository system to compromise the distribution platform are other scenarios where an attacker could perform a software supply chain attack. Two detailed examples of this are shown in the whitepaper.

Attack Scenarios

The below attack scenarios are notable for an attacker to attempt against GitHub Enterprise, GitLab Enterprise, and Bitbucket. These have been useful as a part of X-Force Red’s Adversary Simulation engagements. This is not an exhaustive list of every single attack path available to execute on these SCM systems. The table, below, lists the attack scenarios that are detailed in the whitepaper. A few of these scenarios will be shown in subsequent sections.

SCM System Attack Scenario Sub-Scenario Admin Required?
GitHub Enterprise Reconnaissance -Repository
-File
-Code
No
GitLab Enterprise Reconnaissance -Repository
-File
-Code
No
Bitbucket Reconnaissance -Repository
-File
-Code
No
GitHub Enterprise Maintain Persistent Access -Personal Access Token
-Impersonation Token
-SSH Key
No

Yes

No

GitLab Enterprise Maintain Persistent Access -Personal Access Token
-Impersonation Token
-SSH Key
No

Yes

No

Bitbucket Maintain Persistent Access -Personal Access Token
-SSH Key
No
GitHub Enterprise User Impersonation -Impersonate User Login
-Impersonation Token
Yes
GitLab Enterprise User Impersonation -Impersonate User Login
-Impersonation Token
Yes
GitHub Enterprise Promoting User to Site Admin N/A Yes
GitLab Enterprise Promoting User to Admin Role N/A Yes
Bitbucket Promoting User to Admin Role N/A Yes
Bitbucket Modifying CI/CD Pipeline N/A No
GitLab Enterprise Modifying CI/CD Pipeline N/A No
GitHub Enterprise Repository Takeover N/A Yes
GitHub Enterprise Management Console Access N/A Yes
GitLab Enterprise SSH Access N/A Yes

Table of SCM attack scenarios

Repository Takeover

Using administrative access (specifically site admin role), an attacker can give themselves write access to any repository within GitHub Enterprise. In the below example, we are attempting to view a repository in GitHub Enterprise that our compromised administrative user (adumbledore) does not have access to.

Viewing locked repository

Using the site admin role, you can choose to unlock the repository via the “Unlock” button shown below. This will unlock the repository for the user for two hours by default.

Viewing screen to unlock repository

You must provide a reason to unlock the repository, and this reason is logged along with the request.

Adding reason to unlocking repository

Now you can see we have successfully unlocked the repository, and it is unlocked for two hours for the adumbledore user account. Code within this repository can then be accessed or modified.

Showing repository has been unlocked

User Impersonation

There are two options an attacker has if they have administrative access to GitLab Enterprise or GitHub Enterprise and would like to impersonate another user. The first option is to impersonate a user login via the web interface, and the second option is to create an impersonation token. This will be shown specifically with GitLab Enterprise.

Impersonate User Login

When viewing a user via the admin area in GitLab Enterprise, there is a button available in the top right-hand corner labeled “Impersonate”.

Impersonate user button in hpotter profile

After clicking the “Impersonate” button, you will be logged in as the user you are wanting to impersonate. In this instance, we are impersonating the hpotter user account.

Showing impersonation of hpotter

Impersonation Token

An attacker with admin access to GitLab Enterprise can also impersonate another user by creating an impersonation token. This can be performed via the web interface or the Users REST API. Using the web interface as an admin, you can navigate to the “Impersonation Tokens” section for the user account that you would like to impersonate; add the details for your token including name, expiration date, and scope of permissions.

Creating impersonation token

After you have created your impersonation token, the token value will be listed for use. The user that is impersonated cannot see this impersonation token when accessing GitLab Enterprise as themselves; it is only visible to other admin users.

Showing created impersonation token

An attacker can also create an impersonation token via the Users REST API as shown with the example curl command, below.

curl -k --request POST --header "PRIVATE-TOKEN: apiToken" --data "name=someName-impersonate" --data "expires_at=" --data "scopes[]=api" --data "scopes[]=read_user" --data "scopes[]=read_repository" --data "scopes[]=write_repository" --data "scopes[]=sudo" "https://gitlabHost/api/v4/users/userIDNumberToImpersonate/impersonation_tokens"

Output after creating impersonation token via API

Modifying CI/CD Pipeline

In Bitbucket, there is a feature called Bamboo that can be installed and configured to facilitate a CI/CD pipeline. If a repository is using a CI/CD pipeline with Bamboo, it will contain a directory named “bamboo-specs” within the root of the repository, along with a Bamboo configuration file. This configuration file will either be a YAML file (bamboo.yaml) or a Java spec file (pom.xml). If an attacker would like to discover any repositories that are configured with a CI/CD pipeline via Bamboo, they can search for “bamboo-specs” in either the web interface or REST API.

Discovering repos with CI/CD integration via Bamboo

If you have write access or admin access to a repository, the Bamboo configuration file can be modified. In this case, we are modifying the bamboo.yaml file to add our SSH key to the server where the Bamboo agent is running. This can be performed via the Git command line tool as well to commit the changes to the Bamboo configuration file.

Modifying Bamboo yaml file

This will immediately trigger the CI/CD pipeline to run as shown below.

Showing successful job status

When viewing the output from the pipeline, we can see our SSH key was added, and it printed the hostname of the server where the SSH key was added. At this point, we would be able to perform lateral movement to that server via our SSH key.

Viewing pipeline logs

Maintain Persistent Access

An attacker has three primary options in terms of maintaining persistent access to SCM systems. This can be performed either by creating a personal access token, impersonation token, or adding a public SSH key. All these options are detailed in the whitepaper.

The persistence option that will be shown is creating a personal access token in GitLab Enterprise. This can be performed via the web interface as a regular user or can be performed via the Users REST API as an administrator. The below screenshot shows creating a personal access token called “persistence-token”.

Creating personal access token for hpotter user

You can see the created personal access token and the token value, below.

Showing token value created

An attacker can also create a personal access token via the Users REST API as shown with the below example curl command. In GitLab Enterprise, this requires admin permissions.

curl -k --request POST --header "PRIVATE-TOKEN: apiToken" --data "name=hgranger-persistence-token" --data "expires_at=" --data "scopes[]=api" --data "scopes[]=read_repository" --data "scopes[]=write_repository" "https://gitlabHost/api/v4/users/UserIDNumber/personal_access_tokens"

Creating access token via API

SCMKit

Background

At X-Force Red, we wanted to take advantage of the REST API functionality available in the most common SCM systems seen during engagements and add the most useful functionality in a proof-of-concept tool called SCMKit. The goal of this tool is to provide awareness of the abuse of SCM systems, and to encourage the detection of attack techniques against SCM systems. SCMKit will be shown at Black Hat USA 2022 Arsenal.

SCMKit allows the user to specify the SCM system and attack module to use, along with specifying valid credentials (username/password or API key) to the respective SCM system. Currently, the SCM systems that SCMKit supports are GitHub Enterprise, GitLab Enterprise and Bitbucket Server. The attack modules supported include reconnaissance, privilege escalation and persistence. Other functionality that are available in the non-public version of SCMKit were not included in consideration for defenders, such as user impersonation and built-in credential searching. SCMKit was built in a modular approach so that new modules and SCM systems can be added in the future by the information security community. The tool and full documentation are available on the X-Force Red GitHub. A few examples will be shown in the next sections.

Reconnaissance

SCMKit has multiple modules available to perform reconnaissance of repositories, files, code, and other resources specific to various SCM systems such as GitLab Runners. The below example shows using the “codesearch” module in SCMKit. In this scenario, we are searching for any code in Bitbucket Server that contains “API_KEY” to try and discover API key secrets within source code.

Code search example for API key with SCMKit

There are several other reconnaissance modules that apply only to certain SCM systems. For example, there is a reconnaissance module to discover GitLab Runners that you have access to via the “runnerlist” module.

GitLab Runner reconnaissance example with SCMKit

Privilege Escalation

Another capability available in SCMKit is to add another regular user to the admin role. The example, below, shows adding a regular user under our control (hgranger, in this case) to the site admin role in GitHub Enterprise via the “addadmin” module.

Adding site admin example via SCMKit

You can see the change that took effect in GitHub Enterprise after performing the site admin addition via SCMKit, as the hgranger user is now a member of the site admins group.

Showing hgranger added as site admin

Persistence

There are two persistence modules within SCMKit that include the use of personal access tokens or SSH keys. This can be useful to maintain access to an SCM system. The below example shows creating an SSH key for the hgranger user account in Bitbucket via the “createsshkey” module.

Creating SSH key example with SCMKit

We can list all active SSH keys for a given user via the “listsshkey” module, as shown below. You will see the SSH key we added for the hgranger user listed.

Listing SSH keys example with SCMKit

Defensive Considerations

SCMKit

There are multiple static signatures that can be used to detect the usage of SCMKit. These can be found in the Yara rule on the SCMKit repository.

A static user agent string is used when attempting each module in SCMKit. The user agent string is “SCMKIT-5dc493ada400c79dd318abbe770dac7c”. A Snort rule is provided on the SCMKit repository.

Additionally, any access tokens or SSH keys that are created in SCM systems using SCMKit will be prepended with “SCMKit-” in the name. This can be filtered in the respective SCM system to indicate an access token or SSH key was created using SCMKit.

SCM Systems

Ensure that the below logs are being sent to your SIEM. This also lists the location of the logs on the server for each respective SCM system.

Log Name Location
Audit Log /var/log/github-audit.log*
Management Log /var/log/enterprise-manage/unicorn.log*
HAProxy Log /var/log/haproxy.log

Logs of interest – GitHub Enterprise

Log Name Location
Application Log /var/log/gitlab/gitlab-rails/application.log

/var/log/gitlab/gitlab-rails/application_json.log

Production Log /var/log/gitlab/gitlab-rails/production_json.log

/var/log/gitlab/gitlab-rails/production.log

API Log /var/log/gitlab/gitlab-rails/api_json.log
Web Log /var/log/gitlab/nginx/gitlab_access.log

Logs of interest – GitLab Enterprise

Log Name Location
Access Log /var/atlassian/application-data/bitbucket/log/atlassian-bitbucket-access.log
Audit Log /var/atlassian/application-data/bitbucket/log/audit/*.log
Bitbucket Log /var/atlassian/application-data/bitbucket/log/atlassian-bitbucket.log
Bamboo Log $BAMBOO_HOME/logs/atlassian-bamboo.log

Logs of interest – Bitbucket Server

Below are the various filters you can apply to the logs to detect the attacks demonstrated in this research. Use these filters to build a baseline and detect anomalous activity in your environment.

Attack Scenario Log Name Search Filter
Reconnaissance HAProxy Log (‘/search’ OR ‘/api/v3/search’) AND ‘http’
Repository Takeover Audit Log ‘action:repo.staff_unlock’
User Impersonation Audit Log ‘action:staff.fake_login’ OR ‘action:oauth_access.create’ OR ‘action:oauth_authorization.create’
Promoting User to Site Admin Audit Log ‘action:user.promote’ OR ‘action:business.add_admin’
Maintaining Persistent Access Audit Log ‘action:oauth_access.create’ OR ‘action:oauth_authorization.create’ OR ‘action:public_key.create’ OR action:public_key.verify
Management Console Access Management Log ‘authorized-keys’ AND ‘post’

Table of search queries for various attack types – GitHub Enterprise

Attack Scenario Log Name Search Filter
Reconnaissance Production Log

API Log

Web Log

‘get’ AND ‘/search?search’

‘get’ AND ‘/search’

‘get’ AND (‘/search’ OR ‘repository/tree’)

‘search’

User Impersonation Application Log

Production Log

API Log

‘has started impersonating’

‘impersonate’

‘post’ AND ‘impersonation_tokens’

‘impersonation_tokens’

Promoting User to Admin Role Production Log

API Log

‘patch’ AND ‘admin/users’

‘put’ AND ‘”key”:”admin”,”value”:”true”‘

Maintaining Persistent Access Production Log

API Log

‘post’ AND ‘personal_access_tokens’

‘post’ AND ‘profile/keys’

‘post’ AND ‘personal_access_tokens’

‘post’ AND ‘user/keys’

Modifying CI/CD Pipeline Production Log ‘post’ AND ‘/api/graphql’ AND ‘.gitlab-ci.yml’ AND ‘update’

Table of search queries for various attack types – GitLab Enterprise

Attack Scenario Log Name Search Filter
Reconnaissance Bitbucket Log ‘post’ AND ‘search’ AND ‘query’
Promoting User to Site Admin Access Log

Audit Log

‘put’ AND ‘/admin/permissions/users’

‘new.permission’ AND ‘admin’

Maintaining Persistent Access Access Log

Audit Log

‘put’ AND ‘/rest/access-tokens’

‘post’ AND ‘ssh/account/keys/add’

‘personal access token created’

‘user added ssh access key’

Modifying CI/CD Pipeline Bamboo Log ‘change detection found’

Table of search queries for various attack types – Bitbucket Server

Additionally, the below items should be considered when configuring these SCM systems:

  • Disable user impersonation
  • Do not allow users to create personal access tokens or SSH keys with no expiration date
  • Set automatic expiration date on all personal access tokens and SSH keys created/added
  • Limit the number of administrative users. At minimum there should be two, and should not be more unless necessary
  • Operate on a policy of least privilege in terms of access to repositories
  • Require signed commits via GPG keys or S/MIME certificates
  • Enable multi-factor authentication
  • Ensure that code branches are deleted in a timely manner
  • Require at least one approver for each code commit
  • Increase logging level to detect reconnaissance where applicable

Conclusion

Source code management systems contain some of the most sensitive information in organizations and are a key component in the DevOps lifecycle. Depending on the role of an organization, compromise of these systems can lead to the compromise of other organizations. These systems are a high value to an attacker, and need more visibility from the information security community, as they are currently an afterthought compared to other systems such as Active Directory. It is X-Force Red’s goal that this research will bring more attention and inspire future research on defending these critical enterprise systems.

Acknowledgments

A special thank you to the below people for giving feedback on this research and providing whitepaper content review.

  • Chris Thompson (@retBandit)
  • Daniel Crowley (@dan_crowley)
  • Dimitry Snezhkov (@Op_nomad)
  • Patrick Fussell (@capt_red_beardz)
  • Ruben Boonen (@FuzzySec)

more from Software Vulnerabilities

Controlling the Source: Abusing Source Code Management Systems

For full details on this research, see the X-Force Red whitepaper “Controlling the Source: Abusing Source Code Management Systems”. This material is also being presented at Black Hat USA 2022. Source Code Management (SCM) systems play a vital role within organizations and have been an afterthought in terms of defenses compared to other critical enterprise systems such as Active Directory.…