← Back to Feed CACHED · 2026-09-17 09:34:32 · CACHE_KEY tenable:266294
tenable:266294 · CWE-787 · Disclosed 2025-09-30

OpenSSL 1.1.1 < 1.1.1zd Vulnerability

OpenSSL CMS RFC 3211 KEK Unwrap Out-of-Bounds Read/Write

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

It's like finding a flaw in the ejection seat of a car that was never fitted with one

CVE-2025-9230 is an out-of-bounds read and write in OpenSSL's RFC 3211 KEK (Key Encryption Key) unwrap routine, triggered when an application decrypts CMS (Cryptographic Message Syntax) messages protected by password-based encryption (PWRI). The OOB write can corrupt heap memory, theoretically reaching code execution; the OOB read can crash the process for a denial-of-service. It affects every active OpenSSL branch: 1.0.2 before 1.0.2zm, 1.1.1 before 1.1.1zd, 3.0 before 3.0.18, 3.2 before 3.2.6, 3.3 before 3.3.5, 3.4 before 3.4.3, and 3.5 before 3.5.4. FIPS provider modules are not affected because CMS sits outside the FIPS boundary.

Tenable's plugin flags this as High (7.5) using the cve.org CVSS:3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, but that vector only captures the availability impact and assumes unauthenticated network access — which is technically true yet wildly misleading. The OpenSSL project itself rated the flaw Moderate, and Red Hat scored it with AC:H (high attack complexity) at a much lower base. The decisive reality: CMS password-based encryption (RFC 3211 PWRI) is an obscure feature almost nobody uses. The vast majority of OpenSSL deployments — TLS termination, HTTPS, VPN tunnels — never invoke this code path. Tenable's own VPR (Vulnerability Priority Rating) agrees, placing it at 5.0 / Medium in the 94th percentile, well below the base CVSS. This is a textbook case where the CVSS vector's AC:L misrepresents the real-world attack surface.

"Rare CMS code path makes this a scanner noise generator, not a real emergency."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a CMS PWRI consumer

The attacker must find an application that calls CMS_decrypt() or equivalent on CMS enveloped-data using password-based recipient info (PWRI). This is the critical gate — the entire chain fails without it. Typical OpenSSL consumers (nginx, Apache, HAProxy, curl, stunnel) do not process CMS PWRI messages.
Conditions required:
  • Target application must use OpenSSL CMS PWRI decryption
  • Target must accept externally-supplied CMS messages
Where this breaks in practice:
  • CMS password-based encryption is extremely rare in production — S/MIME with PWRI is a niche use case
  • Most OpenSSL consumers use TLS only, never touching the CMS API
  • Identifying a PWRI consumer from the outside is nearly impossible without source code review
STEP 02

Craft a malicious CMS message

The attacker constructs a CMS EnvelopedData structure with a specially crafted PWRI recipient info that triggers the OOB read/write during KEK unwrap. The malformed KEK length field causes OpenSSL to read and write past the allocated buffer. Several GitHub PoC repositories demonstrate the crash path.
Conditions required:
  • Knowledge of the RFC 3211 KEK unwrap internals
  • Ability to deliver the crafted CMS blob to the target application
Where this breaks in practice:
  • Weaponizing the OOB write for RCE requires heap grooming specific to the target's allocator and binary layout — not a generic exploit
  • PoCs available largely demonstrate the DoS/crash, not reliable code execution
STEP 03

Deliver the crafted message to the target

The attacker must get the target application to process the malicious CMS blob. This could be via email (S/MIME), file upload, API endpoint, or any input channel that feeds into CMS_decrypt(). The delivery mechanism is entirely application-specific.
Conditions required:
  • Network or local access to the application's CMS input channel
  • The application must not reject the malformed structure before reaching the vulnerable code
Where this breaks in practice:
  • Email gateways typically strip or quarantine malformed S/MIME
  • Custom applications may validate CMS structure before decryption
  • Firewalls and WAFs do not inspect CMS payloads, but the delivery path itself may be restricted
Detection/coverage: Tenable plugin 266294 detects vulnerable OpenSSL versions. No network-level exploit signature exists because the payload is application-layer CMS, not a TLS handshake attack.
STEP 04

Trigger OOB read/write → crash or RCE

When the application calls into the KEK unwrap routine, the malformed structure causes a heap buffer over-read and over-write. The most likely outcome is a crash (DoS). Achieving code execution requires precise heap manipulation and is architecture- and binary-specific. No public exploit achieves reliable RCE.
Conditions required:
  • Successful delivery of the crafted CMS message
  • No ASLR/stack canary bypass needed for DoS; full bypass needed for RCE
Where this breaks in practice:
  • Modern OS hardening (ASLR, stack canaries, NX) makes heap-based RCE significantly harder
  • OpenSSL is typically compiled with hardening flags on modern distros
  • The crash itself may be caught by a supervisor process (systemd restart, container orchestrator)
Detection/coverage: Process crash logs, core dumps. EDR may detect anomalous heap corruption patterns. No Suricata/Snort signature exists for this specific attack.
03 · Compensating Control

1
Audit for CMS PWRI usage in your codebase — Search your source code and third-party dependencies for calls to CMS_decrypt(), CMS_RecipientInfo_kekri_*, or RFC 3211 references. If none are found, this CVE has zero exploitable surface in your environment. Complete this audit within the noisgate remediation SLA of 365 days.
2
Prioritize OpenSSL 1.1.1 migration to 3.x — OpenSSL 1.1.1 reached public EOL on 2023-09-11. Hosts still running it are accumulating CVEs without free patches. 1.1.1zd requires a premium support contract. Plan migration to OpenSSL 3.3+ as part of your 365-day remediation window.
3
Restrict CMS message ingestion at application boundaries — If you do have CMS-processing applications, validate CMS structure and reject messages with PWRI recipient info types before passing to OpenSSL decryption. This can be done at the application layer.
4
Enable process restart supervision — Ensure services using OpenSSL are supervised by systemd, Kubernetes liveness probes, or equivalent. This limits DoS impact to a brief restart window rather than a sustained outage.
What doesn't work
  • WAF rules — CMS messages are not HTTP-layer constructs; WAFs cannot inspect or block malicious CMS blobs inside application payloads.
  • TLS version pinning / cipher suite hardening — This vulnerability is in the CMS API, not in TLS handshake or record processing. Hardening your TLS config has zero effect.
  • FIPS mode — While the FIPS provider module is not affected, enabling FIPS mode on OpenSSL 1.1.1 does not disable the vulnerable CMS code path (CMS is outside the FIPS boundary but still callable).
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo evidence. Not observed by GreyNoise, no CISA alerts, no vendor incident reports. No active campaigns documented as of 2026-09-17.
CISA KEV StatusNot listed in the Known Exploited Vulnerabilities catalog.
Proof-of-Concept14 GitHub repositories tagged with CVE-2025-9230 PoCs. Most demonstrate the crash/DoS path only. No public RCE exploit confirmed.
EPSSNot yet scored in FIRST EPSS feed at time of assessment. Given the niche attack surface, expect a low percentile once scored.
CVSS Vectorscve.org: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H → 7.5. Red Hat: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L → 5.6. OpenSSL project: Moderate. Tenable VPR: 5.0 (Medium, 94th percentile).
Affected VersionsOpenSSL 1.1.1 < 1.1.1zd, 1.0.2 < 1.0.2zm, 3.0 < 3.0.18, 3.2 < 3.2.6, 3.3 < 3.3.5, 3.4 < 3.4.3, 3.5 < 3.5.4
Fixed Versions1.1.1zd, 1.0.2zm, 3.0.18, 3.2.6, 3.3.5, 3.4.3, 3.5.4 — note 1.1.1 and 1.0.2 are premium support only (EOL for public).
Scanning / ExposureOpenSSL is ubiquitous (~70% of internet-facing TLS endpoints), but the vulnerable CMS PWRI code path is exercised by a negligible fraction. Shodan/Censys can identify OpenSSL versions but cannot determine CMS PWRI usage.
Disclosure Date2025-09-30 (OpenSSL security advisory)
ReporterNot publicly credited in the OpenSSL advisory. Multiple vendor bulletins (IBM, Siemens, SUSE, Red Hat, Debian) issued downstream advisories.

Sources.

  1. Tenable Plugin 266294
  2. OpenSSL 1.1.1 Vulnerabilities Page
  3. CVE-2025-9230 — Red Hat Customer Portal
  4. CVE-2025-9230 — cvefeed.io
  5. CVE-2025-9230 — SUSE Security
  6. IBM Security Bulletin — CVE-2025-9230
  7. NVD — CVE-2025-9230
05 · The Call

Final Verdict
= UNCHANGED to MEDIUM (4.5/10)

Why this verdict

  • Niche code path: The vulnerability is in CMS PWRI decryption, a feature almost no production application exercises. TLS, the dominant OpenSSL use case, is entirely unaffected. This alone invalidates the AC:L in the CVSS vector for real-world scoring.
  • No active exploitation or KEV listing: Zero in-the-wild exploitation evidence, no CISA KEV entry, no GreyNoise scanning activity. The 14 GitHub PoCs demonstrate crashes, not weaponized RCE.
  • Vendor consensus on Moderate: OpenSSL project rates it Moderate. Red Hat scored it 5.6 with AC:H. Tenable's own VPR is 5.0. Three independent severity assessments agree this is not High in practice.
  • Role multiplier: OpenSSL is a canonical high-value component present on network edge appliances, identity providers, hypervisors, and CI/CD systems. However, the vulnerable code path (CMS PWRI) is not invoked by any of these high-value roles in their standard configurations — none of them process password-based CMS messages. The blast radius is limited to the rare application that explicitly uses CMS_decrypt() with PWRI recipients, which represents well under 1% of the OpenSSL installed base. The high-value role floor does not apply because the chain does not succeed in those roles.
  • RCE is theoretical, DoS is the realistic ceiling: Public PoCs achieve crashes only. Heap-based RCE against hardened binaries with ASLR requires target-specific exploitation not demonstrated publicly.

Why not higher?

Promoting to HIGH would require either active exploitation, a realistic RCE chain, or a code path that impacts a significant share of deployments. None of these conditions are met. The CMS PWRI feature is so niche that even OpenSSL's own team rated this Moderate, and no attacker has demonstrated interest in weaponizing it. The 7.5 CVSS reflects a theoretical network-accessible DoS that almost no real application exposes.

Why not lower?

Dropping to LOW or IGNORE would undercount the theoretical RCE potential of the OOB write and the fact that OpenSSL 1.1.1 is past public EOL — any host still running it has a broader hygiene problem. The 14 public PoCs lower the bar for a motivated attacker to at least achieve process crashes against the rare vulnerable consumer. Additionally, downstream embedded or IoT devices may use CMS in ways not visible to enterprise scanning.

06 · Verification

Crowdsourced verification payload.

Run this script on each target host as any user with read access to the OpenSSL binary. Example: bash check_cve_2025_9230.sh /usr/bin/openssl. No root required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2025_9230.sh — Detect CVE-2025-9230 (OpenSSL CMS PWRI OOB)
# Usage: bash check_cve_2025_9230.sh [/path/to/openssl]
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

OPENSSL_BIN="${1:-openssl}"

if ! command -v "$OPENSSL_BIN" &>/dev/null; then
  echo "UNKNOWN — '$OPENSSL_BIN' not found in PATH"
  exit 2
fi

VERSION_STRING=$($OPENSSL_BIN version 2>&1) || { echo "UNKNOWN — could not execute openssl version"; exit 2; }
echo "Detected: $VERSION_STRING"

# Extract version number
VER=$(echo "$VERSION_STRING" | grep -oP 'OpenSSL \K[0-9]+\.[0-9]+\.[0-9]+[a-z]*')

if [[ -z "$VER" ]]; then
  echo "UNKNOWN — could not parse version from: $VERSION_STRING"
  exit 2
fi

# Parse major.minor.patch and letter suffix
MAJOR=$(echo "$VER" | cut -d. -f1)
MINOR=$(echo "$VER" | cut -d. -f2)
PATCH_RAW=$(echo "$VER" | cut -d. -f3)
PATCH_NUM=$(echo "$PATCH_RAW" | grep -oP '^[0-9]+')
SUFFIX=$(echo "$PATCH_RAW" | grep -oP '[a-z]+$' || true)

# Function to compare letter suffixes (zd = fixed for 1.1.1)
letter_ge() {
  # Returns 0 if $1 >= $2 lexicographically
  [[ "$(printf '%s\n%s' "$2" "$1" | sort | head -1)" == "$2" ]]
}

if [[ "$MAJOR" -eq 1 && "$MINOR" -eq 1 && "$PATCH_NUM" -eq 1 ]]; then
  # OpenSSL 1.1.1 branch — fixed in 1.1.1zd
  if [[ -z "$SUFFIX" ]]; then
    echo "VULNERABLE — OpenSSL 1.1.1 (no patch letter) is affected"
    exit 1
  elif letter_ge "$SUFFIX" "zd"; then
    echo "PATCHED — OpenSSL 1.1.1$SUFFIX >= 1.1.1zd"
    exit 0
  else
    echo "VULNERABLE — OpenSSL 1.1.1$SUFFIX < 1.1.1zd"
    exit 1
  fi
elif [[ "$MAJOR" -eq 1 && "$MINOR" -eq 0 && "$PATCH_NUM" -eq 2 ]]; then
  echo "VULNERABLE — OpenSSL 1.0.2 branch detected; fixed in 1.0.2zm (premium support). Upgrade to 3.x recommended."
  exit 1
elif [[ "$MAJOR" -eq 3 ]]; then
  # 3.0.x fixed in 3.0.18, 3.2.x in 3.2.6, 3.3.x in 3.3.5, 3.4.x in 3.4.3, 3.5.x in 3.5.4
  case "$MINOR" in
    0) FIXED=18 ;;
    2) FIXED=6 ;;
    3) FIXED=5 ;;
    4) FIXED=3 ;;
    5) FIXED=4 ;;
    *) echo "UNKNOWN — OpenSSL 3.$MINOR not in known affected range"; exit 2 ;;
  esac
  if [[ "$PATCH_NUM" -ge "$FIXED" ]]; then
    echo "PATCHED — OpenSSL $VER >= 3.$MINOR.$FIXED"
    exit 0
  else
    echo "VULNERABLE — OpenSSL $VER < 3.$MINOR.$FIXED"
    exit 1
  fi
else
  echo "UNKNOWN — OpenSSL $VER not in a known affected branch"
  exit 2
fi