Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
gitlab-webhook-0net-ssrf — Proof-of-concept and lab for a GitLab CE webhook SSRF via the 0.0.0.0/8 this-network range, letting a Maintainer reach loopback and read responses from hook logs. | Kitploit
Tools/GitHubGitHub/abraxas/gitlab-webhook-0net-ssrf
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLabs & Practice
GitHubabraxas/gitlab-webhook-0net-ssrf

gitlab-webhook-0net-ssrf

Proof-of-concept and lab for a GitLab CE webhook SSRF via the 0.0.0.0/8 this-network range, letting a Maintainer reach loopback and read responses from hook logs.

View Repository
15 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - gitlab-webhook-0net-ssrf

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  gitlab-webhook-0net-ssrf

gitlab-webhook-0net-ssrf

GitLab CE 19.4.1 - GitLab Inc.

Gitlab::HTTP_V2::UrlBlocker blocks exact 0.0.0.0, ::, and 127.0.0.0/8. It does not block the rest of 0.0.0.0/8. Linux treats that range as "this network" and will deliver 0.0.0.1 to the local stack. A project Maintainer can create a webhook at http://0.0.0.1:<port>/ while allow_local_requests_from_web_hooks_and_services is off. GitLab stores 8 KB of the response in hook logs.

A Maintainer of their own project can make GitLab POST to loopback via 0.0.0.1 and read the body back out of the hook log.

IDno CVE yet
CWECWE-918
CVSSHigh: 8.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N
ProductGitLab CE
Affected19.4.1-ce.0 (26212baacadb on the v19.4.1-ee tree)
Authauthenticated Maintainer (admin_web_hook)
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

POST /api/v4/projects/:id/hooks with url=http://0.0.0.1:<port>/. Trigger or test. Read response_body from the hook events API. On all-in-one omnibus, Sidekiq shares the container netns with Puma, Workhorse, and exporters. Maintainer of their project should not read those.

http://127.0.0.1/ and http://169.254.169.254/ stay blocked. This is not IMDS via link-local. It is the this-network hole.

Same product, sibling leftovers: Gitea HTTPS import pin drop, Gitaly fetch omits resolved_address.

How I found it

I read url_blocker.rb after the 19.4.1 SSRF fixes. validate_localhost is exact "::" and "0.0.0.0" plus Socket.ip_address_list. validate_loopback is ipv4_loopback? (127.0.0.0/8) and ipv6 loopback. Specs cover octal/hex aliases of 127.0.0.1. They never mention 0.0.0.1.

Webhook is the body sink: WebHookService POSTs and stores 8 KB. Maintainer has admin_web_hook.

I stood up stock gitlab/gitlab-ce:19.4.1-ce.0. Local-requests off. Catcher inside the GitLab netns on 0.0.0.1:18080. Hook create http://127.0.0.1:18080/ and http://169.254.169.254/ : 422 Invalid url given. Hook create http://0.0.0.1:18080/ : 201. Test push events : 201. Hook events response_body contains GITLAB-WEBHOOK-0NET-SSRF-WITNESS.

Wrong turns already recorded: /users/sign_in with Accept: application/json is 404; seed password containing root is WeakPasswords; adding 0.0.0.1 to lo puts it on Socket.ip_address_list so validate_localhost 422s the "positive"; IP_FREEBIND plus ip route add local 0.0.0.1/32 dev lo binds without joining the address list; compose $ in the password needs $$. A reverse shell. Theatre. The oracle is 201 on 0.0.0.1, 422 on 127.0.0.1, witness in the log.

Lab

cd lab
./run.sh

Target only http://127.0.0.1:18420. GitLab CE wants several GB RAM. Authorized lab only.

negative-a 127.0.0.1 blocked
negative-b link-local blocked
positive-hook id=1
SUCCESS GITLAB-WEBHOOK-0NET-SSRF webhook response_body from 0.0.0.1:18080 hook_id=1 GITLAB-WEBHOOK-0NET-SSRF-WITNESS

The leftover

def validate_localhost(addrs_info)
  local_ips = ["::", "0.0.0.0"]
  local_ips.concat(Socket.ip_address_list.map(&:ip_address))
  return if (local_ips & addrs_info.map(&:ip_address)).empty?
  raise BlockedUrlError, "Requests to localhost are not allowed"
end

def validate_loopback(addrs_info)
  return unless addrs_info.any? { |addr| addr.ipv4_loopback? || addr.ipv6_loopback? }
  raise BlockedUrlError, "Requests to loopback addresses are not allowed"
end

Deny 0.0.0.0/8 (and ::ffff:0.0.0.0/104) the same way 127.0.0.0/8 is denied.

References

  • gitlab.com/gitlab-org/gitlab tag v19.4.1-ee
  • url_blocker.rb · web_hook_service.rb · project_hooks.rb
  • Same product: gitlab-gitea-import-ssrf · gitlab-gitaly-fetch-ssrf
  • CWE-918

License

GNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.

Download Tool