← Back to Feed CACHED · 2026-07-01 01:32:33 · CACHE_KEY CVE-2025-59088
CVE-2025-59088 · CWE-918 · Disclosed 2025-11-12

If kdcproxy receives a request for a realm which does not have server addresses defined in its configuration

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A Kerberos concierge who'll dial any phone number a stranger scribbles on a napkin

kdcproxy is a small WSGI app from the latchset project that lets clients tunnel Kerberos over HTTPS to a KDC — commonly fronted by Apache/mod_wsgi on FreeIPA and Red Hat Identity Management servers. When a client asks for a realm that isn't hard-coded in kdcproxy.conf, the default behavior is to resolve _kerberos._tcp.<REALM> via DNS SRV and connect wherever those records point. An unauthenticated attacker who controls a DNS zone can publish SRV records that resolve to 127.0.0.1:22, 169.254.169.254:80, or any internal RFC1918 host and port, and the kdcproxy server will happily open a TCP connection on their behalf. Affected: all python-kdcproxy versions prior to the latchset PR #68 fix; Red Hat has shipped errata (RHSA-2025:21142, :21748, :21820, :21821) for RHEL 8/9/10 and IdM.

The vendor HIGH / 8.6 score comes from AV:N/AC:L/PR:N/UI:N/S:C/C:H — unauth network reach, scope-change, high confidentiality. That vector is technically defensible (it *is* unauth SSRF crossing a trust boundary), but the C:H reading is generous: kdcproxy speaks a Kerberos wire protocol, so exfiltrating arbitrary HTTP responses back to the attacker requires the target service to happen to speak something kdcproxy will forward and echo. In practice you get *blind* SSRF suitable for internal port scanning, topology mapping, and hitting side-effectful GET endpoints — a real bug, but MEDIUM territory once you audit the friction. Blast radius does not reach fleet compromise from this bug alone.

"Textbook SSRF in a niche Kerberos proxy — real impact is internal port scanning, not the fleet-scale disaster the 8.6 implies."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Reach an internet-exposed kdcproxy endpoint

Attacker locates a public HTTPS endpoint running kdcproxy (typically /KdcProxy on an IdM/FreeIPA front-end or Apache with mod_proxy_kdcproxy). Shodan/Censys queries for the KDC-PROXY-MESSAGE content-type or IdM banners are the usual discovery path.
Conditions required:
  • kdcproxy WSGI app reachable over the network
  • no auth gate in front of /KdcProxy
Where this breaks in practice:
  • Most IdM deployments are internal-only; kdcproxy on the public internet is uncommon
  • Some deployments front kdcproxy with client-cert auth or IP allowlists
Detection/coverage: Shodan/Censys can fingerprint kdcproxy via HTTP headers; external ASM tools catch it as python-kdcproxy service
STEP 02

Register an attacker-controlled DNS zone with malicious SRV records

Attacker owns a domain (e.g. evil.example) and publishes _kerberos._tcp.EVIL.EXAMPLE SRV records pointing to target-host:target-port — where target is inside the victim's network (loopback, RFC1918, cloud metadata IP). Tooling: dig, any authoritative DNS provider, or a custom nameserver via dnslib.
Conditions required:
  • Ability to publish authoritative DNS records for a chosen realm name
  • kdcproxy config lacks explicit [REALM] entries for the crafted realm
Where this breaks in practice:
  • Requires attacker to own or delegate a DNS zone — trivial but leaves an audit trail (registrar records, WHOIS)
Detection/coverage: Passive DNS providers (Farsight, DomainTools) log the SRV publication
STEP 03

Send a crafted AS-REQ for the attacker-controlled realm

Attacker POSTs a Kerberos AS-REQ wrapped in the KDC-PROXY-MESSAGE ASN.1 envelope to /KdcProxy naming realm EVIL.EXAMPLE. kdcproxy sees no config entry, falls back to use_dns=true (the default), resolves the SRV record, and connects to the internal target. A one-liner in Python with impacket.krb5.asn1 or the PoC in latchset/kdcproxy PR #68 is enough.
Conditions required:
  • use_dns at default (true)
  • Egress from kdcproxy host to the chosen internal address:port is not firewalled
Where this breaks in practice:
  • Egress filtering from the kdcproxy host to RFC1918 / loopback varies wildly
  • Some hardened builds pin use_dns=false
Detection/coverage: Web-server access logs show POST /KdcProxy with unusual realm; DNS query logs on the kdcproxy host show SRV lookups for third-party zones
STEP 04

Enumerate internal services / hit side-effectful endpoints

By varying SRV targets the attacker performs blind port scanning (connection succeeds vs. timeout vs. RST is observable in response latency and error messages). Cloud metadata endpoints (169.254.169.254) and unauthenticated internal admin panels are the high-value targets. Full response exfiltration is limited because kdcproxy expects a Kerberos framed reply.
Conditions required:
  • Internal services listening on predictable addresses/ports
  • kdcproxy returns distinguishable error signals for open vs closed ports
Where this breaks in practice:
  • No response body echo — impact is blind / semi-blind
  • IMDSv2 (AWS) requires PUT with header; SSRF via kdcproxy is GET-style only
Detection/coverage: Egress NetFlow from kdcproxy host to unusual internal destinations; EDR on kdcproxy host sees outbound TCP fan-out
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed as of 2026-07-01 — no GreyNoise tags, no vendor IR reports
KEV statusNot listed in CISA KEV
EPSS0.00397 (~0.4%) — low predicted exploitation probability
Public PoCFix commit + regression tests in latchset/kdcproxy PR #68 demonstrate the primitive; no weaponized exploit in Metasploit/Nuclei yet
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N — unauth network, scope-change, confidentiality-only. C:H is generous given blind-SSRF nature
CWECWE-918 Server-Side Request Forgery
Affected versionsAll python-kdcproxy prior to the latchset upstream fix; RHEL packages fixed via RHSA-2025:21142, :21748, :21820, :21821
Fixed versionsUpstream master post-PR #68; RHEL 8 python3-kdcproxy-1.0-4.el8_10, RHEL 9 python3-kdcproxy-1.0-8.el9_6, RHEL 10 current z-stream; Ubuntu tracked, fix landing per USN
Exposure populationkdcproxy is bundled with FreeIPA / Red Hat IdM; Shodan shows only low hundreds of internet-exposed IdM front-ends globally — the vast majority are intranet-only
ReporterReported via Red Hat Product Security; fix authored by jrisc (latchset maintainers)
Disclosed2025-11-12
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.3/10)

The single most decisive factor is blast radius: this is blind SSRF that yields internal port scanning and topology mapping, not credential theft, not RCE, not identity takeover — the affected component is an auth *proxy* but the bug does not touch Kerberos ticket handling. Combined with the fact that kdcproxy is rarely exposed to the internet (bundled with IdM/FreeIPA, typically intranet-only), the vendor's 8.6 overstates real-world impact.

HIGH vulnerability mechanics and fix availability
HIGH no active exploitation
MEDIUM internet-exposure population estimate

Why this verdict

  • Blind SSRF, not data exfil: kdcproxy expects a Kerberos-framed reply from the upstream, so arbitrary HTTP response bodies do not round-trip cleanly back to the attacker. The vendor's C:H rating is optimistic.
  • Narrow deployment footprint: kdcproxy is an optional component of FreeIPA / Red Hat IdM used to tunnel Kerberos over HTTPS for remote clients. Shodan/Censys populations for internet-facing IdM /KdcProxy endpoints are in the low hundreds globally.
  • Attacker must control a DNS zone, which is trivial but leaves registrar and passive-DNS forensic breadcrumbs — raising cost for repeated / targeted use.
  • Role multiplier — IdM / FreeIPA front-end: kdcproxy runs on an identity server, which IS a high-value role, but the chain here does NOT end in identity compromise. It ends in internal reconnaissance. Floor is not elevated to HIGH because the bug does not yield ticket forgery, credential access, or lateral movement on its own.
  • Trivial config workaround exists: setting use_dns = false or defining explicit [REALM] blocks fully mitigates without a code change — many hardened builds already do this.

Why not higher?

HIGH would require either fleet-scale blast radius or a credible path to credential/identity compromise from this primitive alone. Neither holds: the bug is blind SSRF constrained to Kerberos framing, and there is no evidence in the PoC or vendor advisory of ticket-forgery or LDAP-relay pivots. No KEV listing, EPSS <1%.

Why not lower?

LOW would ignore that this IS an unauthenticated pre-auth primitive against an identity-plane component — cloud metadata endpoints and internal admin panels remain plausible targets, and any IdM box exposed to the internet is a real problem. MEDIUM is the honest bucket.

05 · Compensating Control

What to do — in priority order.

  1. Set use_dns = false in /etc/kdcproxy.conf — Kills the entire SSRF primitive by disabling SRV fallback. Restart the WSGI worker (systemctl restart httpd on IdM). Deploy within the 365-day noisgate MEDIUM window, but do it this week if your kdcproxy is internet-reachable.
  2. Define explicit [REALM] entries for every realm you actually serve — Even with use_dns=true, an explicit realm block short-circuits DNS fallback for that realm. Enumerate every trusted realm and hard-code KDC addresses.
  3. Front /KdcProxy with an allowlist or mTLS at the reverse proxy — In Apache/nginx in front of kdcproxy, restrict /KdcProxy to known client CIDRs or require client certificates. Prevents opportunistic scan-and-exploit.
  4. Egress-filter the kdcproxy host — The kdcproxy service should only need to reach your legitimate KDCs on 88/tcp and 464/tcp. Block loopback aliases, RFC1918 outside the KDC subnet, and 169.254.169.254 at the host firewall (iptables/nftables) or from a network SG.
  5. Apply vendor patch — Install RHSA-2025:21142 / :21748 / :21820 / :21821 for RHEL 8/9/10; Ubuntu USN when available. Under noisgate remediation SLA for MEDIUM, complete within 365 days — but bundle into your next monthly IdM maintenance window.
What doesn't work
  • WAF rules on /KdcProxy — the request body is opaque ASN.1 (KDC-PROXY-MESSAGE); WAFs cannot parse the realm name without a custom decoder.
  • Kerberos pre-auth / PKINIT — pre-auth happens at the KDC, not at kdcproxy; the SSRF fires before any auth exchange completes.
  • Blocking outbound DNS — the SRV lookup uses the host's normal resolver; you can't stop it without breaking legitimate KDC discovery.
06 · Verification

Crowdsourced verification payload.

Run on each IdM / FreeIPA server or any host with python-kdcproxy installed. Requires read access to /etc/kdcproxy.conf and the package manager — typically root. Invoke: sudo bash check-cve-2025-59088.sh.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2025-59088.sh — detects vulnerable python-kdcproxy configurations
# Exit 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN
set -u

CONF=/etc/kdcproxy.conf
STATE=UNKNOWN
REASON=""

# 1. Is kdcproxy installed?
if command -v rpm >/dev/null 2>&1; then
  PKG_VER=$(rpm -q --qf '%{VERSION}-%{RELEASE}\n' python3-kdcproxy 2>/dev/null || rpm -q --qf '%{VERSION}-%{RELEASE}\n' python-kdcproxy 2>/dev/null)
elif command -v dpkg >/dev/null 2>&1; then
  PKG_VER=$(dpkg-query -W -f='${Version}\n' python3-kdcproxy 2>/dev/null)
fi

if [ -z "${PKG_VER:-}" ]; then
  echo "UNKNOWN: python-kdcproxy not installed"
  exit 2
fi

echo "Installed python-kdcproxy: $PKG_VER"

# 2. Config-level mitigation check
if [ -r "$CONF" ]; then
  if grep -Eiq '^[[:space:]]*use_dns[[:space:]]*=[[:space:]]*(false|no|0)' "$CONF"; then
    STATE=PATCHED
    REASON="use_dns explicitly disabled in $CONF"
  fi
fi

# 3. Package-level check — RHEL fixed builds
case "$PKG_VER" in
  1.0-4.el8_10*|1.0-8.el9_6*|1.0-*.el10*)
    STATE=PATCHED
    REASON="${REASON:+$REASON; }package version contains vendor fix"
    ;;
esac

if [ "$STATE" = "PATCHED" ]; then
  echo "PATCHED: $REASON"
  exit 0
fi

echo "VULNERABLE: python-kdcproxy $PKG_VER without use_dns=false and no fixed package detected"
exit 1
07 · Bottom Line

If you remember one thing.

TL;DR
If your IdM / FreeIPA /KdcProxy endpoint is reachable from the internet or from an untrusted network, treat this like a KEV-adjacent finding: add use_dns = false to /etc/kdcproxy.conf and restart httpd today, then schedule the RHSA patch into your next IdM maintenance window. For internal-only IdM (the majority) this is a MEDIUM — noisgate mitigation SLA: no mitigation SLA for MEDIUM, go straight to the noisgate remediation SLA of ≤ 365 days, but bundle it into your next monthly patch cycle so it doesn't rot. Egress-filter kdcproxy hosts to their real KDCs while you're in there — that permanently kills the SSRF class, not just this CVE.

Sources

  1. Red Hat Bugzilla 2393955 — CVE-2025-59088
  2. RHSA-2025:21142
  3. RHSA-2025:21748
  4. RHSA-2025:21820
  5. RHSA-2025:21821
  6. latchset/kdcproxy PR #68 — upstream fix
  7. Ubuntu security tracker — CVE-2025-59088
  8. SecAlerts summary
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.