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
prometheus-unix-socket-dial — Prometheus v3.15.0 - High - Remote - SSRF - http_sd __unix_socket__ unsanitized Dial leftover of UDS scrape | Kitploit
Tools/GitHubGitHub/abraxas/prometheus-unix-socket-dial
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringPenetration TestingLabs & Practice
GitHubabraxas/prometheus-unix-socket-dial

prometheus-unix-socket-dial

Prometheus v3.15.0 - High - Remote - SSRF - http_sd __unix_socket__ unsanitized Dial leftover of UDS scrape

View Repository
13 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 - prometheus-unix-socket-dial

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  prometheus-unix-socket-dial

prometheus-unix-socket-dial

Class: SSRF Reach: Remote

Prometheus v3.15.0 (5241a27) - CNCF / Prometheus

v3.15.0 added Unix Domain Socket scrape (#12024 / #18091). The path is a target label __unix_socket__, not an operator allowlist. http_sd and file_sd copy that label through as-is. PopulateLabels never validates it. newUnixSocketScrapeClient then calls DialContext(ctx, "unix", socketPath) with no filepath.Clean, no allowlist, and no reject of ../ or Linux abstract @ names.

TCP scrape cannot do this. CheckTargetAddress still drops __address__ values that contain /, so unix:///var/run/docker.sock as an address is rejected. The new label is the hole.

Stock config does not set the label. Unauth HTTP to Prometheus cannot add jobs. This is SD-gated.

IDno CVE yet
ClassSSRF (unsanitized unix Dial from SD labels)
ReachRemote (SD-gated: writer of http_sd / file_sd)
CWECWE-918, CWE-22
CVSSHigh: 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N
ProductPrometheus
Affectedv3.15.0 (5241a27fe3c6983549fccc32f6e65917408c63cd), image prom/prometheus:v3.15.0
AuthSD-gated: writer of http_sd / file_sd labels (or a relabel that copies untrusted meta into __unix_socket__)
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Control of http_sd JSON (or writable file_sd) is enough. The SD URL is operator config. The leftover is that group labels may set __unix_socket__ and Prometheus will Dial it.

PrivilegeMethod / sinkLab-proven or inferred
Connect to a host unix socket the Prometheus UID can openclientForTarget -> DialContext(ctx, "unix", socketPath) from __unix_socket__Lab-proven. Path /sockets/jail/../oracle.sock from http_sd; scrape health up
Follow ../ in that pathno filepath.Clean / no .. rejectLab-proven. Kernel resolved the traversal to /sockets/oracle.sock
Dial a Linux abstract socketsame Dial of @nameLab-proven. __unix_socket__=@prom-lab-oracle; scrape health up
HTTP GET on that socket as the Prometheus UIDscrape is GET; __metrics_path__ is the request pathLab-proven. GET /fs-traversal and /abstract; User-Agent Prometheus/; lab_witness ingested
Reach sockets TCP scrape cannot nameCheckTargetAddress rejects / in __address__Lab-proven. unix:///var/run/docker.sock as __address__ logged is not a valid hostname; not an active target; prometheus_target_sync_failed_total=1
GET Docker Engine / kubelet HTTP APIs if those sockets are in scope__unix_socket__=/var/run/docker.sock plus a Docker API pathInferred. Same unsanitized Dial. This lab does not mount a real engine socket. JSON APIs usually fail exposition parse, so the High is the connect/GET, not TSDB exfil of Docker JSON
Mutate Docker (create container, write)scrape verbsClosed. Scrape is GET-only
Add scrape jobs over unauth Prometheus HTTP/-/reload, admin APIClosed. Both flags default off; reload has no body
Use this on default example config__unix_socket__ unset; example scrapes localhost:9090 over TCPClosed. In-tree k8s/consul/docker SD emit __meta_* only; those prefixes are deleted after relabel

Vendor security model already lets SD choose TCP scrape targets. The new primitive is host IPC that __address__ could not name.

How I found it

I pinned prometheus/prometheus v3.15.0 after the 3.15 FEATURE line for UDS scrape. Default OSS on this pin has admin API, lifecycle HTTP, remote-write receiver, and OTLP receiver off. PopulateDiscoveredLabels copies every http_sd group label. __unix_socket__ is not __meta_*, so it survives the meta wipe. PopulateLabels checks __address__ only.

func (sp *scrapePool) clientForTarget(t *Target) *http.Client {
	socketPath := t.labels.Get(UnixSocketLabel)
	if socketPath == "" {
		return sp.client
	}
	client, err := newUnixSocketScrapeClient(socketPath, ...)
func newUnixSocketScrapeClient(socketPath string, ...) (*http.Client, error) {
	optFuncs = append([]config_util.HTTPClientOption{config_util.WithDialContextFunc(
		func(ctx context.Context, _, _ string) (net.Conn, error) {
			return (&net.Dialer{}).DialContext(ctx, "unix", socketPath)
		},
	)}, optFuncs...)

CheckTargetAddress still rejects / in the address. URL() keeps scheme/host/path from __scheme__ / __address__ / __metrics_path__; the socket is dial-only.

Wrong turns already recorded: scoring this as in-model NONE because SD already chooses TCP targets (the new primitive is host IPC); treating unix:///var/run/docker.sock as __address__ as the hole (it is rejected); claiming default example config is this leftover. Theatre: a reverse shell. The oracle is scrape health up on sockets the SD JSON named.

Lab

python3 prometheus-unix-socket-dial-Abraxas-Labs.py

or

cd lab
./run.sh

prom/prometheus:v3.15.0 shares a netns with a Python sidecar. Sidecar serves http_sd at 127.0.0.1:8080/targets.json and two unix HTTP oracles: filesystem /sockets/oracle.sock and abstract @prom-lab-oracle. Prometheus is published at 127.0.0.1:19390. Admin API and lifecycle stay off.

SUCCESS prometheus-unix-socket-dial sd=http_sd fs-traversal=yes abstract=yes tcp-slash-rejected=yes how=sd-labels PROMETHEUS-UNIX-SOCKET-DIAL-WITNESS

IOC: scrapeUrl=http://localhost:1/fs-traversal and /abstract, both health up. TCP slash never became an active target.

The fix

Do not Dial __unix_socket__ from SD until it is a sanitized absolute filesystem path. Reject empty values, NUL, Linux abstract @ names, relative paths, and any .. after filepath.Clean. An allowlist of prefixes from scrape YAML is stronger. Dropping the label from PopulateDiscoveredLabels unless it came from operator config also closes the SD injection.

References

  • github.com/prometheus/prometheus tag v3.15.0 (5241a27fe3c6983549fccc32f6e65917408c63cd)
  • scrape/scrape.go · scrape/target.go · config/config.go
  • UDS scrape #18091
  • CWE-918 · CWE-22

License

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

Download Tool