This is less a front-door break-in than a locksmith learning your key pattern by listening to a million tiny clicks
CVE-2022-4304 is an OpenSSL RSA decryption timing oracle: tiny timing differences during RSA decrypt processing can leak enough signal for a Bleichenbacher-style plaintext recovery attack. Upstream affected ranges are OpenSSL 3.0.0 through 3.0.7, 1.1.1 before 1.1.1t, and 1.0.2 before 1.0.2zg; distro builds may be fixed via backports even when the package version string looks older.
The vendor's MEDIUM label is technically fair in a vacuum but still a little generous for enterprise patch triage. The decisive reality check is exploit friction: the attacker needs a reachable RSA decryption path, usually a legacy TLS_RSA_* handshake or some application-level RSA decrypt API, then must collect a very large number of timing samples under noisy network conditions; that sharply narrows both exposed population and practical attacker success.
4 steps from start to impact.
Find a real RSA decryption surface
TLS_RSA_* key exchange, discoverable with tools like nmap --script ssl-enum-ciphers or validation tooling such as tlsfuzzer.- Internet- or network-reachable service using vulnerable OpenSSL code
- A code path that performs RSA decryption on untrusted input
- For TLS use cases, support for legacy RSA key exchange or equivalent RSA decrypt behavior
- TLS 1.3 removes RSA key exchange entirely
- Most modern TLS 1.2 deployments prefer ECDHE, so the decryption oracle often never appears
- Many applications link OpenSSL but never expose raw RSA decryption to remote users
Capture a target ciphertext
- Ability to observe a legitimate session or otherwise obtain a target ciphertext
- The captured ciphertext must map to the same vulnerable decryption behavior later probed
- Perfect forward secrecy kills the classic TLS payoff when ECDHE is used
- Many enterprises no longer permit RSA key exchange on external services
- Network visibility requirements already imply a stronger attacker position than a generic unauthenticated internet bug
Hammer the oracle with timing probes
tlsfuzzer and marvin-toolkit, the attacker sends a very large number of crafted trial ciphertexts and records response times. The whole attack lives or dies on extracting a stable statistical signal from tiny timing differences across the network.- Server accepts repeated handshake/decrypt attempts
- Attacker can collect high-volume, high-quality timing measurements
- The signal is not drowned out by infrastructure jitter
- Load balancers, connection reuse, rate limits, autoscaling, and noisy neighbors smear timing signal
- Attack cost is high because sample counts are huge
- A WAF or reverse proxy may not block the math, but it often adds enough jitter to make exploitation far harder
Recover plaintext offline
- Sufficient samples collected from the same target behavior
- Leak magnitude large enough to survive network noise
- A meaningful target plaintext exists
- Many real networks are simply too noisy
- The attack yields confidentiality impact only; there is no direct integrity or code-execution path
- Even a successful result is often limited to specific sessions or specific app-layer decrypt operations
The supporting signals.
| In-the-wild status | No evidence of active exploitation from CISA KEV, and no vendor advisory I found claims live campaigns. As verified on 2026-06-05, this CVE is not in the CISA KEV catalog. |
|---|---|
| PoC / tooling availability | Research-grade public tooling exists: tlsfuzzer and marvin-toolkit. That matters, but this is not a one-shot RCE PoC; it is a measurement-and-statistics workflow. |
| EPSS | 0.00224 (0.224%). *Inference:* current public trackers place it roughly in the mid-pack percentile (~45th-49th), which matches the very low operational exploitation signal. |
| KEV status | Not KEV-listed as of 2026-06-05, which is consistent with the absence of broad opportunistic exploitation. |
| CVSS vector | CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N — remote and confidentiality-relevant, but the AC:H is doing real work here because the attack chain is fragile and sample-hungry. |
| Affected versions | Upstream OpenSSL lists 3.0.0-3.0.7, 1.1.1 before 1.1.1t, and 1.0.2 before 1.0.2zg as affected. |
| Fixed versions / distro backports | Upstream fixes are 3.0.8, 1.1.1t, and 1.0.2zg. Debian tracks backported fixes in buster as 1.1.1n-0+deb10u4 and bullseye as 1.1.1n-0+deb11u4, so package version strings alone can mislead. |
| Exposure reality | *Inference:* internet census tools are weak for this CVE because they can find TLS services, but they cannot reliably tell you whether a target actually negotiates TLS_RSA_* or exposes a remotely reachable app-layer RSA decrypt path. Treat this as an asset inventory and cipher-policy problem, not a Shodan count problem. |
| Disclosure / reporting | OpenSSL says an initial possible timing-side-channel report arrived on 2020-07-14, a refined report on 2022-07-15, and the advisory published on 2023-02-07/2023-02-08 depending on source timezone. The issue was reported by Hubert Kario (Red Hat). |
noisgate verdict.
The single biggest downgrade factor is reachable population: a vulnerable library is not enough; the attacker needs a remotely reachable RSA decryption path, and the most common TLS path mostly disappeared with TLS 1.3 and ECDHE-first TLS 1.2 configs. The remaining attack is real but expensive, timing-sensitive, and usually confined to legacy or specialty deployments rather than the average enterprise fleet.
Why this verdict
- Baseline starts at vendor MEDIUM, then drops on attacker position reality: the attacker is nominally remote and unauthenticated, but in practice they need a live RSA decryption oracle plus a target ciphertext; that is already narrower than a normal network bug.
- Reachable population is sharply reduced by modern crypto defaults: TLS 1.3 removed RSA key exchange, and well-run TLS 1.2 estates prefer ECDHE, so a huge fraction of OpenSSL deployments are not exploitable through the classic observed-session path.
- Operational exploit friction is extreme: public tooling exists, but success still depends on very large probe volumes, stable timing collection, and enough signal surviving network noise and middleboxes.
Why not higher?
There is no broad internet-scale smash-and-grab path here. No KEV entry, no known active campaigns, no integrity or availability impact, and a large chunk of modern deployments simply do not expose the necessary RSA decryption behavior at all.
Why not lower?
This is still a real confidentiality bug in one of the most widely deployed crypto libraries, not a paperwork CVE. If you still run legacy TLS_RSA_* or application-level RSA decryption on exposed systems, the impact can be meaningful and the fix is well established.
What to do — in priority order.
- Disable legacy
TLS_RSA_*cipher suites — If the service is exposed over TLS, removing RSA key exchange cuts off the most common remotely reachable attack path outright; prefer ECDHE/TLS 1.3 everywhere. For aLOWverdict there is no formal SLA, but do it in the next normal crypto-hardening change window. - Inventory app-layer RSA decryption uses — Find services, middleware, VPNs, mail gateways, HSM front-ends, and ICS components that still perform RSA decryption on untrusted input, because those are the real blast-radius drivers for this CVE. For
LOW, treat this as backlog hygiene and complete it during the next routine library exposure review. - Rate-limit handshake and decrypt abuse — High-volume repetitive probes are part of the attack economics, so rate limits, per-source throttles, and connection anomaly controls raise attacker cost and reduce measurement quality. Use the next standard perimeter tuning cycle; no mitigation SLA applies at this severity.
- Alert on repetitive failed handshakes — Build detections for bursts of failed TLS handshakes or repetitive malformed decrypt requests against the same endpoint, because that is where exploitation is most likely to surface operationally. Roll this into regular detection engineering maintenance rather than emergency change.
- Patch the terminating tier first — Where legacy backends remain, prioritize the front-end TLS terminator, reverse proxy, or appliance actually doing RSA decryption so you remove the exposed oracle without waiting for every downstream dependency. For
LOW, schedule in normal remediation waves.
- A WAF alone does not understand cryptographic timing oracles; it may add jitter, but it does not guarantee the RSA decryption path is gone.
- MFA is irrelevant here because this is not an account-takeover or login abuse problem.
- Rotating certificates does not fix the oracle; the weakness is in decryption behavior, not in a specific cert/key pair being old.
Crowdsourced verification payload.
Run this on the target host or container image that ships OpenSSL, not from an auditor workstation. Invoke it as bash check-cve-2022-4304.sh or bash check-cve-2022-4304.sh /usr/bin/openssl; root is not required, but package-changelog checks are more reliable if the local package database is readable.
#!/usr/bin/env bash
# check-cve-2022-4304.sh
# Detect likely exposure to CVE-2022-4304 (OpenSSL RSA timing oracle)
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_BIN="${1:-$(command -v openssl 2>/dev/null || true)}"
CVE="CVE-2022-4304"
if [ -z "$TARGET_BIN" ] || [ ! -x "$TARGET_BIN" ]; then
echo "UNKNOWN: openssl binary not found or not executable"
exit 2
fi
version_line="$($TARGET_BIN version -a 2>/dev/null | head -n 1)"
if [ -z "$version_line" ]; then
echo "UNKNOWN: unable to read OpenSSL version"
exit 2
fi
version="$($TARGET_BIN version 2>/dev/null | awk '{print $2}')"
platform_info="$($TARGET_BIN version -a 2>/dev/null | tr '\n' ' ' )"
# First: distro/package backport checks, because package versions may look older than upstream fixed releases.
check_dpkg() {
if ! command -v dpkg-query >/dev/null 2>&1; then
return 1
fi
local pkg
for pkg in openssl libssl3 libssl1.1 libssl1.0.0; do
if dpkg-query -W -f='${Status}\n' "$pkg" 2>/dev/null | grep -q "install ok installed"; then
if command -v apt-cache >/dev/null 2>&1; then
if apt-cache show "$pkg" 2>/dev/null | grep -qi "$CVE"; then
echo "PATCHED: dpkg package metadata for $pkg references $CVE (backport likely)"
exit 0
fi
fi
# Debian fixed versions from tracker
local ver
ver="$(dpkg-query -W -f='${Version}\n' "$pkg" 2>/dev/null | head -n1)"
case "$pkg:$ver" in
openssl:1.1.1n-0+deb10u4*|openssl:1.1.1n-0+deb11u4*|libssl1.1:1.1.1n-0+deb10u4*|libssl1.1:1.1.1n-0+deb11u4*)
echo "PATCHED: Debian backported fixed package detected ($pkg $ver)"
exit 0
;;
esac
fi
done
return 1
}
check_rpm() {
if ! command -v rpm >/dev/null 2>&1; then
return 1
fi
local pkg
for pkg in openssl openssl-libs; do
if rpm -q "$pkg" >/dev/null 2>&1; then
if rpm -q --changelog "$pkg" 2>/dev/null | grep -q "$CVE"; then
echo "PATCHED: rpm changelog for $pkg references $CVE (backport likely)"
exit 0
fi
fi
done
return 1
}
check_dpkg
check_rpm
# Upstream version comparison fallback. Handles common OpenSSL trains only.
normalize() {
# Converts versions like 3.0.7, 1.1.1s, 1.1.1t into sortable numeric-ish tuples.
local v="$1"
local base suffix letter_num=0
base="${v%%[a-z]}"
suffix="${v#$base}"
if [ "$suffix" != "$v" ] && [ -n "$suffix" ]; then
# a=1 ... z=26
letter_num=$(( $(printf '%d' "'${suffix}") - 96 ))
fi
IFS=. read -r a b c <<< "$base"
a=${a:-0}; b=${b:-0}; c=${c:-0}
printf "%03d%03d%03d%03d\n" "$a" "$b" "$c" "$letter_num"
}
ver_ge() {
[ "$(normalize "$1")" -ge "$(normalize "$2")" ]
}
ver_lt() {
[ "$(normalize "$1")" -lt "$(normalize "$2")" ]
}
# Common upstream trains
if [[ "$version" =~ ^3\.0\.[0-9]+$ ]]; then
if ver_ge "$version" "3.0.8"; then
echo "PATCHED: upstream OpenSSL $version is at or above 3.0.8"
exit 0
else
echo "VULNERABLE: upstream OpenSSL $version is below 3.0.8"
exit 1
fi
fi
if [[ "$version" =~ ^1\.1\.1[a-z]?$ ]]; then
if ver_ge "$version" "1.1.1t"; then
echo "PATCHED: upstream OpenSSL $version is at or above 1.1.1t"
exit 0
else
echo "VULNERABLE: upstream OpenSSL $version is below 1.1.1t"
exit 1
fi
fi
if [[ "$version" =~ ^1\.0\.2[a-z]?$ ]]; then
if ver_ge "$version" "1.0.2zg"; then
echo "PATCHED: upstream OpenSSL $version is at or above 1.0.2zg"
exit 0
else
echo "VULNERABLE: upstream OpenSSL $version is below 1.0.2zg"
exit 1
fi
fi
# Newer trains likely contain the fix; older/odd vendor forks are ambiguous.
if [[ "$version" =~ ^3\.[1-9]\.[0-9]+$|^4\.[0-9]+\.[0-9]+$ ]]; then
echo "PATCHED: OpenSSL $version is on a newer major/minor train than the affected upstream releases"
exit 0
fi
echo "UNKNOWN: version '$version' from '$version_line' could not be mapped cleanly; inspect package advisory/backport status"
exit 2
If you remember one thing.
TLS_RSA_* or otherwise performs remote RSA decryption; if you find those legacy surfaces, harden cipher policy or patch the terminating tier in the next normal change window, because for this LOW verdict there is no noisgate mitigation SLA. For the actual library update, there is likewise no strict noisgate remediation SLA beyond backlog hygiene, so roll fixed packages into your normal maintenance cadence and prioritize only the small subset of externally reachable legacy-RSA systems above the rest of the fleet.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.