Like a lock that only jams if someone installed an optional, rarely used extra tumbler
CVE-2023-0464 is an algorithmic complexity DoS in OpenSSL's X.509 policy-constraint verification path. It affects OpenSSL 1.0.2 through before 1.0.2zh, 1.1.1 through before 1.1.1u, 3.0.0 through before 3.0.9, and 3.1.0 through before 3.1.1. An attacker needs to supply a malicious certificate chain to an application that performs certificate validation with policy processing enabled, which is *not the default*.
The 7.5/HIGH CVSS score captures the theoretical network DoS outcome, but it badly overstates enterprise reality. The decisive friction is that policy processing is disabled by default and usually only appears in specialized PKI-heavy apps, custom certificate-validation code, or compliance-driven deployments; that cuts the reachable population down hard, and the impact is still availability-only.
3 steps from start to impact.
Find a target that actually uses policy checking
-policy path or the X509_VERIFY_PARAM_set1_policies() API (docs). In practice this is usually custom PKI tooling, certificate gateways, or niche trust-policy workflows rather than ordinary HTTPS serving.- Target application uses vulnerable OpenSSL
- Application accepts untrusted certificate chains
- Policy checking is explicitly enabled
- Policy processing is disabled by default in OpenSSL
- Many common TLS server deployments never invoke this path
- Reachability depends on app behavior, not just the library being installed
Feed a malicious chain into certificate verification
openssl verify against a malicious chain.- Attacker can present or upload a certificate chain to the vulnerable workflow
- Target uses OpenSSL verification on attacker-controlled input
- Many deployments only verify certificates from tightly controlled internal CAs
- Mutual TLS and custom trust workflows are a minority case in most enterprises
Burn CPU in the verifier
- Verification runs synchronously on a request or session path
- Resource limits or watchdogs do not kill the work quickly
- Timeouts, worker isolation, and process supervision often cap blast radius
- Impact is availability-only; there is no direct code execution or data exposure
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found; not listed in CISA KEV as of today. This is a major downgrade factor. |
|---|---|
| Proof-of-concept availability | Yes. Public PoC references exist, including Trinadh465/Openssl_1.1.1g_CVE-2023-0464 and technical walkthroughs demonstrating verifier CPU exhaustion. |
| EPSS | 0.00734 supplied in your intel; that is very low exploit likelihood relative to internet-priority CVEs. |
| KEV status | Not in CISA KEV; no federal due date, no known ransomware association published by CISA. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H scores the worst-case path as simple unauthenticated network DoS, but it does not encode the biggest real-world constraint: non-default policy checking must be enabled first. |
| Affected versions | Upstream affected trains are 1.0.2 < 1.0.2zh, 1.1.1 < 1.1.1u, 3.0.0 < 3.0.9, and 3.1.0 < 3.1.1. |
| Fixed versions | Upstream fixes landed in 1.0.2zh, 1.1.1u, 3.0.9, and 3.1.1. Distros backported fixes: Debian bullseye 1.1.1n-0+deb11u5, Ubuntu jammy 3.0.2-0ubuntu1.9, Ubuntu focal 1.1.1f-1ubuntu2.18, plus multiple Red Hat and SUSE errata. |
| Exposure/scanning reality | There is no reliable Shodan/Censys-style fingerprint for 'vulnerable to CVE-2023-0464' because this is a library flaw gated by application logic and non-default API use, not a banner-identifiable appliance bug. Expect internet exposure data to be mostly noise. |
| Disclosure | Disclosed 2023-03-22. |
| Reporter | Reported to OpenSSL on 2023-01-12 by David Benjamin (Google); fix developed by Dr Paul Dale. |
noisgate verdict.
The single biggest driver here is attacker reachability into a non-default code path: vulnerable OpenSSL alone is not enough, because the target app must also enable certificate policy checking. That prerequisite collapses the exposed population from 'every box with OpenSSL' to a much smaller set of specialized PKI workflows, keeping this out of urgent enterprise patch queues.
Why this verdict
- Down from 7.5/HIGH because policy checking is off by default in OpenSSL; the vulnerable path is opt-in.
- Requires attacker-controlled certificate input into verification; installed library presence alone does not create an exploit path.
- Exposure population is narrow and hard to reach externally; this is mostly relevant to PKI-specialized services, custom validators, and niche trust-policy deployments.
- Impact is availability only; there is no credential theft, privilege gain, or code execution.
- No KEV listing, no public exploitation evidence, and very low EPSS all argue against priority patch treatment.
Why not higher?
If this were reachable in default TLS server behavior, the vendor's 7.5 would be fair. But the exploit chain has a major prerequisite that most enterprises do not satisfy: an application must explicitly enable policy processing and then accept attacker-controlled cert chains into that path. That is too much friction for HIGH.
Why not lower?
It is not IGNORE because public PoC material exists and the trigger is remotely deliverable where the feature is in use. In PKI-heavy environments, a single exposed certificate-verification service can still suffer meaningful operational pain, so it belongs in backlog hygiene rather than being dismissed.
What to do — in priority order.
- Inventory policy-checking consumers — Within backlog hygiene timing for a LOW, identify applications and scripts that call OpenSSL certificate verification with policy flags or use
X509_VERIFY_PARAM_set1_policies(). This sharply narrows your true exposure and keeps the library finding from turning into meaningless fleet churn. - Disable policy verification where not required — If a service does not have a compliance or PKI reason to enforce certificate policies, remove that option during normal change windows. For this CVE, eliminating the non-default feature removes the attack path faster than blind package chasing.
- Cap verifier resource usage — Apply CPU, timeout, worker, or watchdog limits on certificate-processing services during normal hardening cycles. That contains process hangs and prevents one bad chain from monopolizing shared workers.
- Prioritize exposed PKI services for patching — Treat externally reachable mTLS gateways, custom enrollment portals, email-security certificate validators, and internal CA tooling as the only meaningful priority set. Patch those first during routine maintenance, then let the rest of the fleet ride normal library refresh cadence.
- A generic WAF does not help much; the payload is a malicious certificate chain inside a crypto validation workflow, not an HTTP exploit pattern.
- MFA is irrelevant; this is not an authentication bypass or account attack.
- Simple port-based external exposure counts are misleading; an HTTPS listener using OpenSSL is not automatically exploitable unless the app enables policy checking.
Crowdsourced verification payload.
Run this on the target Linux host as a local audit check. Invoke it as bash cve-2023-0464-check.sh with no special privileges required for basic package/version inspection; root helps only if your package manager metadata is restricted.
#!/usr/bin/env bash
# CVE-2023-0464 OpenSSL local exposure check
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
result="UNKNOWN"
reason="Could not determine package/version state"
have_cmd() { command -v "$1" >/dev/null 2>&1; }
ver_ge() {
# returns 0 if $1 >= $2 using sort -V
[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}
check_upstream_openssl() {
local v
v=$(openssl version 2>/dev/null | awk '{print $2}') || return 1
case "$v" in
3.1.*)
if ver_ge "$v" "3.1.1"; then result="PATCHED"; reason="Upstream OpenSSL $v >= 3.1.1"; return 0; else result="VULNERABLE"; reason="Upstream OpenSSL $v < 3.1.1"; return 0; fi ;;
3.0.*)
if ver_ge "$v" "3.0.9"; then result="PATCHED"; reason="Upstream OpenSSL $v >= 3.0.9"; return 0; else result="VULNERABLE"; reason="Upstream OpenSSL $v < 3.0.9"; return 0; fi ;;
1.1.1*)
local suffix
suffix=${v#1.1.1}
if [[ -z "$suffix" ]]; then result="VULNERABLE"; reason="Upstream OpenSSL 1.1.1 baseline is older than 1.1.1u"; return 0; fi
local letter=${suffix:0:1}
if [[ "$letter" =~ [u-z] ]]; then result="PATCHED"; reason="Upstream OpenSSL $v >= 1.1.1u"; else result="VULNERABLE"; reason="Upstream OpenSSL $v < 1.1.1u"; fi
return 0 ;;
1.0.2*)
local suffix
suffix=${v#1.0.2}
if [[ "$suffix" == zh* ]]; then result="PATCHED"; reason="Upstream OpenSSL $v >= 1.0.2zh"; else result="VULNERABLE"; reason="Upstream OpenSSL $v < 1.0.2zh"; fi
return 0 ;;
esac
return 1
}
check_dpkg() {
local pkgver osrel
pkgver=$(dpkg-query -W -f='${Version}' openssl 2>/dev/null) || return 1
osrel=$(grep '^VERSION_CODENAME=' /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"')
case "$osrel" in
jammy)
if dpkg --compare-versions "$pkgver" ge "3.0.2-0ubuntu1.9"; then result="PATCHED"; reason="Ubuntu jammy openssl $pkgver includes fix"; else result="VULNERABLE"; reason="Ubuntu jammy openssl $pkgver older than fixed 3.0.2-0ubuntu1.9"; fi ;;
focal)
if dpkg --compare-versions "$pkgver" ge "1.1.1f-1ubuntu2.18"; then result="PATCHED"; reason="Ubuntu focal openssl $pkgver includes fix"; else result="VULNERABLE"; reason="Ubuntu focal openssl $pkgver older than fixed 1.1.1f-1ubuntu2.18"; fi ;;
bionic)
if dpkg --compare-versions "$pkgver" ge "1.1.1-1ubuntu2.1~18.04.22"; then result="PATCHED"; reason="Ubuntu bionic openssl $pkgver includes fix"; else result="VULNERABLE"; reason="Ubuntu bionic openssl $pkgver older than fixed 1.1.1-1ubuntu2.1~18.04.22"; fi ;;
bullseye)
if dpkg --compare-versions "$pkgver" ge "1.1.1n-0+deb11u5"; then result="PATCHED"; reason="Debian bullseye openssl $pkgver includes fix"; else result="VULNERABLE"; reason="Debian bullseye openssl $pkgver older than fixed 1.1.1n-0+deb11u5"; fi ;;
*)
return 1 ;;
esac
return 0
}
check_rpm() {
local pkgver
pkgver=$(rpm -q --qf '%{VERSION}-%{RELEASE}\n' openssl 2>/dev/null) || return 1
# RHEL/SUSE often backport fixes without obvious upstream-style version jumps.
# If rpm-based and package metadata is present, prefer errata-driven validation by your scanner/SBOM.
result="UNKNOWN"
reason="RPM package found ($pkgver). Verify against vendor errata/backports; version string alone may be misleading."
return 0
}
if have_cmd dpkg-query && check_dpkg; then
:
elif have_cmd rpm && check_rpm; then
:
elif have_cmd openssl && check_upstream_openssl; then
:
fi
printf '%s - %s\n' "$result" "$reason"
case "$result" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esac
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.