In short

Make sure no service accepts SSLv2 and that no RSA private key is shared between services, because DROWN used an SSLv2 server as a Bleichenbacher padding oracle to decrypt TLS sessions on other servers with the same key. Turn off RSA key exchange entirely, since ROBOT (2017) and Marvin (2023) found new Bleichenbacher oracles; ECDHE and TLS 1.3 avoid it. DROWN decrypted sessions; it did not steal the private key.

  • The vulnerable boundary follows the key, not the hostname: one SSLv2 service exposes every server with that key.
  • DROWN is a cross-protocol form of Bleichenbacher’s 1998 attack on RSA PKCS#1 v1.5 encryption.
  • The same family returned as ROBOT in 2017 and Marvin in 2023; removing RSA key exchange removes the target.
  • A new certificate around the same key changes nothing; compare public-key fingerprints.
  • DROWN decrypted recorded or live sessions; it did not recover the server’s private key.

Incident at a glance

Date
Category
Protocol attack
Organizations
  • OpenSSL Project
  • Microsoft (IIS 7.0 and 7.5)
Impact
An SSLv2 server with export ciphers became a padding oracle for decrypting TLS sessions that used RSA key exchange on any server sharing its RSA key. At disclosure the researchers measured 33% of HTTPS servers as vulnerable.
How it was found
Academic researchers found the cross-protocol attack; Nimrod Aviram and Sebastian Schinzel reported it to OpenSSL on 29 December 2015.

Timeline

  1. Daniel Bleichenbacher publishes the adaptive chosen-ciphertext attack on RSA PKCS#1 v1.5 encryption.
  2. RFC 6176 prohibits SSL 2.0.
  3. OpenSSL 1.0.2a, 1.0.1m, 1.0.0r and 0.9.8zf fix the SSLv2 bug that later enabled the faster DROWN variant (CVE-2016-0703).
  4. The researchers report DROWN to OpenSSL.
  5. DROWN is disclosed; OpenSSL 1.0.2g and 1.0.1s disable SSLv2 by default and remove SSLv2 export ciphers.
  6. The paper is presented at the 25th USENIX Security Symposium.
  7. RFC 10015 forbids RSA key exchange in TLS 1.2, the key transport that Bleichenbacher-style oracles attack.

Verify it

  1. Run the shared-key script over every endpoint in your inventory and resolve each shared fingerprint.
  2. Run testssl.sh --drown --robot host:443 against each endpoint and confirm both report not vulnerable.
  3. Confirm no endpoint offers SSLv2, SSLv3 or a TLS_RSA key-exchange suite.
  4. After replacing a shared key, confirm the new fingerprint differs on every endpoint that used the old one.
Applies to

Historical SSLv2-to-TLS attack conditions. Disabling one endpoint is insufficient when the same key remains exposed elsewhere.

Part of
Collection: case studies

Fix it in your stack

Tested fixes: the vulnerable code, the fix, a plausible fix that still fails, and the regression tests that tell them apart.

Learning goals and prerequisitesAbout 19 minutes: 5 to read and 14 for the exercise

What you will learn

  • Explain a cross-protocol oracle through key reuse.
  • Distinguish decryption of connections from private-key recovery.
  • Scope remediation by public-key identity.

Before you start

Engineers who deploy certificates and keys across servers and appliances, and reviewers who scope TLS findings.

  • Understand cross-protocol key reuse and the effect of an exposed decryption oracle.

Refresh first: Padding oracle attacks

Go to the guided practice

The vulnerable boundary followed the key, not the hostname

DROWN, disclosed in 2016, used SSLv2 behavior as a cross-protocol oracle against RSA-encrypted secrets from other connections. A modern HTTPS endpoint could be exposed even if it did not accept SSLv2, when another service accepted SSLv2 using the same RSA private key. The two services might be on different ports, hosts, or application protocols.

In RSA key transport, a client encrypts a secret using the server’s public key. RSA ciphertexts have an algebraic relation: multiplying a ciphertext by s^e modulo n corresponds to multiplying the underlying RSA message by s modulo n before padding interpretation. An oracle that reveals whether transformed messages have useful structure can gradually constrain the original secret.

DROWN is a cross-protocol form of Bleichenbacher’s 1998 padding oracle attack on RSA PKCS#1 v1.5 encryption, adapted to SSLv2’s protocol behavior. The padding-oracle guide at /domains/identity-crypto/encryption/padding-oracle-attacks/ explains the same principle for CBC: a validity signal that leaks plaintext. The published work describes a general attack and more efficient variants associated with implementation weaknesses (CVE-2016-0800 and CVE-2016-0703). Its result was decryption or active compromise of targeted connections under the attack assumptions, not recovery of the server’s long-term private key.

A service graph reveals more than a TLS score

Suppose api.example and mail.example present different certificates whose public keys have the same fingerprint K1. The API accepts TLS 1.2 RSA key transport; the mail service accepts SSLv2. A certificate inventory that compares only names or serial numbers misses their shared private-key boundary. An attacker can observe one service and query the other.

The general explanation requires suitable victim exchanges and repeated access to the oracle. A single SSLv2 handshake result establishes an obsolete exposed protocol, but does not itself demonstrate decryption of a chosen TLS session. The research also includes active variants, so a blanket claim that preferring forward-secret suites alone eliminates all DROWN exposure is too broad.

Private-key reuse is often introduced for operational convenience: copying one wildcard certificate to web servers, mail appliances, load balancers, and disaster-recovery systems. The trust consequences outlive the original deployment decision. A forgotten service can remain an oracle after the prominent endpoint is hardened.

Close the oracle everywhere the key is used

Disable SSLv2 and update affected implementations across every service sharing the key. If the reuse inventory is incomplete, issuing a fresh key to the modern service can separate it from unknown legacy uses. Reissuing a certificate with the same public key does not provide that separation.

Because the attack does not inherently extract the private key, a claim that every DROWN finding automatically proves key theft is incorrect. Key replacement may still be prudent where the key’s exposure or distribution cannot be bounded. Make that decision explicit rather than confusing cryptographic recovery with operational uncertainty.

Longer-term, give services independently managed keys and track key identity across deployments. This adds renewal and inventory work, but limits the reach of a protocol failure. A policy that forbids copying private keys across trust contexts is useful only if deployment tooling makes distinct issuance and rotation practical.

What should you do today?

  • Confirm no listener anywhere accepts SSLv2 or SSLv3, including mail, VPN, management and appliance interfaces.
  • Turn off TLS_RSA key-exchange suites: Bleichenbacher oracles reappeared as ROBOT in 2017 and as the Marvin timing attack in 2023, and RFC 10015 (July 2026) now forbids these suites in TLS 1.2. TLS 1.3 has no RSA key exchange at all, and the TLS guide at /domains/identity-crypto/key-management-pki/tls-pki-operations/ gives a current server profile.
  • Give each service its own key pair instead of copying one wildcard certificate and key everywhere.
  • In application code, stop using RSA PKCS#1 v1.5 encryption; use RSA-OAEP or, better, a KEM or ECDH-based scheme from a maintained library.

Find endpoints that share a private key

Certificates can differ while the key inside them is the same, so compare public-key fingerprints. This script prints the SHA-256 fingerprint of the public key each endpoint serves and lists keys served by more than one. It was tested with OpenSSL 3.6.4 against local servers where two different certificates shared one key, a third used its own key, and a fourth endpoint was unreachable. It sees only reachable endpoints, so also compare the fingerprints in your certificate inventory and secret store.

Testshared-keys.shShell
#!/usr/bin/env bash
# Fingerprint the public key each TLS endpoint serves and report keys served by more than one.
# Usage: ./shared-keys.sh endpoints.txt   (one host:port per line; mail on port 25 or 587 needs -starttls smtp)
results=$(while read -r endpoint; do
  [ -n "$endpoint" ] || continue
  key=$(openssl s_client -connect "$endpoint" -servername "${endpoint%:*}" </dev/null 2>/dev/null \
    | openssl x509 -noout -pubkey 2>/dev/null)
  if [ -z "$key" ]; then echo "none $endpoint"; continue; fi
  echo "$(openssl pkey -pubin -outform DER <<<"$key" | openssl dgst -sha256 -r | cut -c1-64) $endpoint"
done < "$1" | sort)
echo "$results"
awk '$1 != "none" { n[$1]++; e[$1] = e[$1] " " $2 }
     END { for (k in n) if (n[k] > 1) print "SHARED KEY" e[k] }' <<<"$results"

Verify both the endpoint and the reuse closure

Test the approved modern service path, reject SSLv2 negotiation on every known listener, and compare public-key fingerprints across the inventory. Include alternate ports, mail protocols, appliances, and restored instances. An external scan sees only reachable surfaces and cannot prove that the private key has never been copied elsewhere.

The fixture supplies fingerprint and protocol observations. It supports a risk-scope decision rather than a reproduced attack. A complete production report should separate protocol support, implementation version, shared-key evidence, and demonstrated connection compromise; those claims have different evidentiary requirements.

Guided practice

An inventory contains four endpoints. Identify where the same-key SSLv2 boundary exists.

Supplied scenario material
Plain text
A: api:443, TLS1.2 RSA transport, key fingerprint K1.
B: mail:465, SSLv2 accepted, key fingerprint K1.
C: files:443, TLS1.2 RSA transport, key fingerprint K2.
D: backup:8443, protocol unknown, key fingerprint K1.
New certificate A2: different serial, same fingerprint K1.
  1. 1. Build the key groups

    Group endpoints by fingerprint and identify confirmed versus unknown oracle paths.

    Expected result and reasoning

    K1 groups A, B, D; B is a confirmed SSLv2 path and D needs investigation. K2 groups C; the fixture supplies no shared-key SSLv2 path for C.

  2. 2. Assess certificate renewal

    Decide whether deploying A2 breaks A’s relationship with B.

    Expected result and reasoning

    It does not: the unchanged public-key fingerprint indicates the same RSA key. A new serial alone changes no key boundary.

  3. 3. Plan and verify closure

    Choose a repair when D cannot be inventoried immediately.

    Expected result and reasoning

    Disable SSLv2 and patch B; give A an independently generated key if separation from D cannot be established. A must still serve its intended clients, B must reject SSLv2, and A’s new fingerprint must differ from K1.

Your deliverable: A key-to-service graph with confirmed findings, unknowns, and replacement verification.

No RSA ciphertext or SSLv2 oracle is queried. The supplied inventory cannot prove private-key theft or rule out undiscovered key copies.

Save a draft on this device to resume later. Automatic saving begins after you choose Save. Drafts are never sent by this application; use synthetic data.

No draft saved on this device yet.

Sources & further reading

The standards, specifications and documentation behind the guidance above. Each is the evidence for a claim on this page; consult it for detail beyond the defaults and versions listed here.

  1. DROWN research team: disclosure and technical explanation
  2. OpenSSL: An OpenSSL user’s guide to DROWN (March 1, 2016)
  3. ROBOT: Return Of Bleichenbacher’s Oracle Threat (2017)
  4. The Marvin Attack: Bleichenbacher timing oracles in RSA implementations (2023)
  5. RFC 10015: Deprecating obsolete key exchange methods in TLS 1.2 and DTLS 1.2. July 2026.
  6. OpenSSL Security Advisory: DROWN (CVE-2016-0800) and CVE-2016-0703. 1 March 2016.

Reference information

ASVS 5.0.0 requirements
v5.0.0-11.3.1 · v5.0.0-12.1.1 · v5.0.0-12.1.2

Download this guide as Markdown