logo

Port 9090 – Prometheus (Monitoring Server, Web UI & HTTP API)

Service:

Prometheus serverCockpit web console (cockpit-ws)Openfire admin

Protocol:

TCP

Port:

9090

Used for:

Serving the Prometheus monitoring server's web UI and HTTP metrics API, and also the Cockpit Linux web console, Openfire admin, and other management dashboards

Port 9090 is best known as the default port for Prometheus, the open-source monitoring and time-series database — it serves Prometheus’s web UI (/graph), its scrape target for its own metrics (/metrics), and the full HTTP API under /api/v1/. But 9090 is not exclusively Prometheus: Red Hat’s Cockpit Linux web console defaults to 9090, the Openfire XMPP server’s admin console listens there over plain HTTP, OpenShift’s console and various dev servers and SOCKS proxies use it too. So on an open 9090 the first job is to identify which service is answering — and if it’s Prometheus, the headline issue is that Prometheus ships with no authentication and no TLS at all. Its own documentation states that it is designed to be run behind a reverse proxy, so an internet-facing 9090 typically means every metric, every scrape target, and the whole API are readable by anyone who can reach the port.

Why It’s Open

The dominant occupant of port 9090 is Prometheus. It binds 9090 out of the box for its web interface and API and is a core component of nearly every modern observability stack — Kubernetes clusters, DevOps pipelines, and cloud-native platforms almost always run one. Because Prometheus scrapes metrics from dozens or hundreds of exporters (host metrics from node_exporter on port 9100, application metrics, database exporters), its config and target list are effectively a map of the entire internal environment, which is exactly why an exposed 9090 is so valuable to an attacker.

Port 9090 is also a shared admin/console default:

  • Cockpit — the RHEL/Fedora/Debian web console (cockpit-ws) — serves its management UI on 9090 (usually redirecting to HTTPS), giving browser-based root-level control of a Linux host.
  • Openfire (the XMPP/Jabber server) exposes its admin console on 9090 over plain HTTP by default, with HTTPS on the adjacent 9091.
  • OpenShift, Cherokee Admin, some Qlik deployments, SOCKS proxies, and internal dev servers also pick 9090.

Because so many different things listen here, an open 9090 has to be fingerprinted before it’s assessed — a Prometheus server, a Cockpit console, and an Openfire admin panel are three completely different attack surfaces sharing one port number.

Common Risks

  • No authentication or TLS by default (Prometheus). Prometheus has zero built-in access control and no encryption. The upstream docs are explicit that it must sit behind a reverse proxy; left open, the entire UI and API are unauthenticated and in cleartext.
  • Full metrics and topology disclosure. /metrics, /federate, and /api/v1/query will happily dump every time series — internal hostnames, service names, container/pod labels, versions, and sometimes secrets, tokens, or credentials that got embedded in metric labels or command-line arguments captured by exporters.
  • Configuration and target leakage. /api/v1/status/config, /api/v1/status/flags, and /api/v1/targets reveal the scrape configuration, runtime flags, storage paths, and the address of every monitored service — a ready-made blueprint of the internal network for lateral movement.
  • Admin and lifecycle API abuse. If the server was started with --web.enable-admin-api, an unauthenticated attacker can call /api/v1/admin/tsdb/delete_series (destroy monitoring data) or /api/v1/admin/tsdb/snapshot; with --web.enable-lifecycle, /-/reload and /-/quit allow config reloads and a clean denial-of-service shutdown.
  • Query-driven resource exhaustion. Broad or repeated PromQL queries against an open API can pin CPU and memory and take the monitoring server (and your visibility) down.
  • Wrong-service, wrong-risk. If the listener is Cockpit or Openfire rather than Prometheus, the risk shifts entirely — Cockpit is a root-capable host console and Openfire an admin panel, each with its own login and its own CVEs (see below).

Want to save time on reporting?

Let PentestPad generate, track, and export your reports - automatically.

logo-cta

Enumeration & Testing

The whole game on 9090 is identifying the service first, then — if it’s Prometheus — walking the unauthenticated API.

Detect the service and version

Terminal window
nmap -sV -p 9090 <target>
nmap -sV -p 9090 --script "http-title,http-headers,http-enum" <target>

Fingerprint which app is answering

Terminal window
curl -sI http://<target>:9090/

A Server: Cockpit header (usually with a 301 to HTTPS) means the Linux web console; an Openfire login page or a redirect to /login.jsp points to Openfire; a page titled Prometheus Time Series Collection and Processing Server or a working /graph confirms Prometheus.

Confirm Prometheus and read its build info

Terminal window
curl -s http://<target>:9090/api/v1/status/buildinfo
curl -s http://<target>:9090/metrics | head

Pull the config, flags, and scrape targets

Terminal window
# Runtime config: scrape jobs and target URLs (inline secrets show as <secret>, but hostnames leak)
curl -s http://<target>:9090/api/v1/status/config
# Command-line flags: exposes --web.enable-admin-api, --web.enable-lifecycle, storage.tsdb.path, etc.
curl -s http://<target>:9090/api/v1/status/flags
# Every monitored endpoint and its health - a map of the internal estate
curl -s http://<target>:9090/api/v1/targets

Dump all metric series (topology, labels, secrets)

Terminal window
# {__name__=~".+"} = match every metric
curl -s 'http://<target>:9090/api/v1/query?query=%7B__name__%3D~%22.%2B%22%7D'
# Federation endpoint: bulk-export the full metric set
curl -s 'http://<target>:9090/federate?match%5B%5D=%7B__name__%3D~%22.%2B%22%7D'

Probe for the admin and lifecycle APIs

Terminal window
# 200 => --web.enable-lifecycle is on (reload is a soft-DoS lever; /-/quit shuts it down)
curl -s -o /dev/null -w "%{http_code}\n" -XPOST http://<target>:9090/-/reload
# Not 404 => --web.enable-admin-api is on (snapshot / delete_series are reachable)
curl -s -XPOST http://<target>:9090/api/v1/admin/tsdb/snapshot

Record every open 9090, the exact service and version you fingerprinted, and any config, target list, or secret you pull, so the evidence lands in the pentest report instead of a scratch terminal you’ll lose.

What to Look For

Checkpoint What it means
/graph loads or /api/v1/status/buildinfo returns JSON Confirmed Prometheus server — walk the unauthenticated API
Server: Cockpit header / 301 to HTTPS Cockpit host console, not Prometheus — a root-capable login surface
Openfire login page / redirect to /login.jsp Openfire admin console — assess as an XMPP admin panel
/api/v1/status/config returns data with no login No authentication — full config and scrape targets exposed
/api/v1/targets lists internal hostnames Network map handed to an attacker for lateral movement
Secrets/tokens visible in metric labels or process_* args Credential leak straight out of /metrics or /federate
/-/reload returns 200 or admin tsdb endpoints exist Lifecycle/admin API enabled — data deletion and DoS are possible
Reachable from the internet Prometheus behind no reverse proxy — the design’s worst case

Known CVEs and Exploits

The honest headline for Prometheus is that its biggest risk is a design decision, not a single RCE: it ships with no authentication and no TLS, so an exposed 9090 is dangerous even when the binary is fully patched. That said, the Prometheus server itself has had verified web-layer CVEs, and the other services that squat on 9090 (Cockpit especially) have serious ones of their own.

Prometheus server (the actual port-9090 service):

  • CVE-2019-3826 — Stored, DOM-based cross-site scripting in the Prometheus web UI before 2.7.1. A crafted URL sent to an authenticated user leads to persistent execution of arbitrary script in their browser. CVSS 6.1.
  • CVE-2021-29622 — Open redirect in the /new endpoint of Prometheus 2.23.0–2.27.0 (fixed in 2.26.1/2.27.1, endpoint removed in 2.28.0). A crafted URL redirects victims to an attacker-controlled site for phishing or malware delivery. CVSS 6.1.

Cockpit (also defaults to 9090 — verify which service you actually hit):

  • CVE-2026-4631 — Cockpit’s remote-login feature passes user-supplied hostnames and usernames to the SSH client without sanitisation, enabling unauthenticated OS command injection / RCE on the host via a single crafted HTTP request. Rated critical (CVSS 9.8).
  • CVE-2024-2947 — Command injection in Cockpit 270 and newer: deleting a sosreport with a crafted name via the web UI runs attacker commands, leading to privilege escalation. CVSS 7.3.
  • CVE-2020-35850 — Server-side request forgery in Cockpit 234: the login page can be used to probe internal ports/hosts. Real but vendor-disputed (Cockpit maintainers don’t consider it a meaningful risk); included for completeness. CVSS 6.5.

There is no Metasploit or Nmap NSE module specific to Prometheus — attacking an exposed instance is plain curl against the unauthenticated API, so don’t expect a canned exploit; the impact comes from what the API freely hands over.

CVEs removed from the previous version of this page. The old stub listed three CVEs that do not belong to the Prometheus server on port 9090: CVE-2023-40577 is an XSS in Alertmanager (a separate binary that defaults to port 9093, not the Prometheus server on 9090); CVE-2025-3454 is a Grafana improper-authorization bug (Grafana runs on port 3000) that happens to touch Prometheus datasources but is a Grafana flaw; and CVE-2025-3145 is a memory-corruption bug in MindSpore, a machine-learning framework with no connection to Prometheus or Grafana at all. All three were mislabeled and have been removed. Always confirm the affected product on the NVD record before trusting a CVE.

Mitigation

  • Never expose Prometheus directly. Follow the upstream guidance and put it behind a reverse proxy that adds authentication (Basic Auth, OAuth2 proxy, or SSO) and TLS on 443; recent Prometheus builds also support native basic-auth and TLS via a web.yml config file.
  • Bind to localhost or an internal interface. Start with --web.listen-address=127.0.0.1:9090 (or an RFC 1918 address) and let only the proxy reach it, rather than the default 0.0.0.0:9090.
  • Firewall 9090 to the monitoring/VPN subnet, and audit cloud security groups, Kubernetes Services, and container port mappings for an accidental public 0.0.0.0:9090.
  • Leave the admin and lifecycle APIs off. Don’t set --web.enable-admin-api or --web.enable-lifecycle unless you truly need them, and never on an internet-reachable instance.
  • Keep secrets out of metrics. Don’t put credentials or tokens in labels, scrape URLs, or process arguments that exporters expose; treat /metrics and /federate as public if the port is.
  • Identify and harden the right service. If 9090 is actually Cockpit or Openfire, patch it (Cockpit’s CVE-2026-4631 is a critical unauth RCE), restrict the console to a management network, and enforce strong admin credentials and HTTPS.
  • Patch and rescan. Keep Prometheus, Cockpit, and any front-end like Grafana updated, then confirm the port is closed or authenticated with nmap -p 9090 <target>.

Real-World Example

The canonical port-9090 incident isn’t a memory-corruption exploit — it’s an open Prometheus doing exactly what it was designed to do, for the wrong audience. Because Prometheus has no authentication or TLS by default, Shodan and Censys routinely index thousands of internet-facing 9090 instances, and each one is a self-service intelligence briefing. An attacker hits /api/v1/status/config and /api/v1/targets to enumerate every service the organisation monitors — internal hostnames, ports, database and cache endpoints, cloud metadata — then queries /metrics and /federate to pull labels and, frequently, secrets that leaked in as label values or in the command-line arguments node_exporter captured. If the instance was launched with --web.enable-admin-api or --web.enable-lifecycle, the same unauthenticated attacker can delete the time-series data or issue /-/quit to blind the defenders entirely. No CVE, no exploit binary, no login prompt — just the default configuration reachable from the internet, which is why the Prometheus project’s own security documentation tells you to put it behind a reverse proxy.

FAQ

What is port 9090 used for?

Port 9090 is the default port for Prometheus, the monitoring and time-series database — it serves Prometheus’s web UI, its /metrics endpoint, and the full /api/v1/ HTTP API. It is not exclusive to Prometheus, though: Red Hat’s Cockpit Linux web console, the Openfire XMPP admin console, OpenShift’s console, and assorted dev servers and proxies also default to 9090. On an open 9090, identify which of these is answering before assessing it.

Why is port 9090 open on my server?

Most commonly because Prometheus is running as part of a monitoring or Kubernetes stack. It can also be the Cockpit web console (very common on RHEL/Fedora/Debian hosts), an Openfire admin panel, or a development tool. If you didn’t deploy monitoring and see 9090 open, fingerprint it with curl -sI http://<host>:9090/ to find out what it is before trusting it.

Is it dangerous to expose Prometheus on port 9090?

Yes. Prometheus has no built-in authentication and no TLS, so an internet-facing 9090 exposes every metric, the scrape configuration, the list of monitored targets, and the full API to anyone. That leaks your internal topology and often secrets, and — if the admin or lifecycle APIs were enabled — allows data deletion and denial of service. Prometheus should always sit behind an authenticating reverse proxy.

How do I know whether 9090 is Prometheus or Cockpit?

Check the HTTP response. Prometheus loads a /graph UI and returns JSON from /api/v1/status/buildinfo; Cockpit sends a Server: Cockpit header and usually a 301 redirect to HTTPS with a login page; Openfire shows an admin login (often redirecting to /login.jsp). nmap -sV -p 9090 <host> plus curl -sI will usually settle it in one step.

Does Prometheus on 9090 have known CVEs?

Yes, but they’re web-layer issues rather than remote code execution: a stored DOM-based XSS before 2.7.1 (CVE-2019-3826) and an open redirect in 2.23.0–2.27.0 (CVE-2021-29622). The far bigger risk is the no-authentication-by-default design. Note that Cockpit — which also uses 9090 — has had a critical unauthenticated RCE (CVE-2026-4631), so confirm which service you’re actually looking at.

How do I secure or close port 9090?

Put Prometheus behind a reverse proxy with authentication and TLS (or enable native basic-auth/TLS via web.yml), bind it to localhost or an internal interface instead of 0.0.0.0, and firewall 9090 to your monitoring/VPN network. Don’t enable --web.enable-admin-api or --web.enable-lifecycle on anything reachable from untrusted networks. If it’s Cockpit or Openfire, patch it and restrict the console to a management subnet. Rescan with nmap -p 9090 <host> to confirm.

TL;DR

  • Service: primarily Prometheus (monitoring server web UI + HTTP API); also Cockpit Linux console, Openfire admin, OpenShift, and other dashboards — fingerprint before you assess
  • Default port: 9090/TCP
  • Biggest risk: an unauthenticated, internet-exposed Prometheus — no auth or TLS by default, so it leaks all metrics, internal topology, config, and targets, with admin/lifecycle API abuse (data deletion, DoS) if those flags are on. On Cockpit, watch for the critical unauth RCE CVE-2026-4631
  • Mitigation: run Prometheus behind an authenticating reverse proxy with TLS, bind to localhost/internal, firewall 9090 to trusted subnets, keep the admin/lifecycle APIs off, patch Cockpit/Openfire, and rescan to confirm