CVE-2026-22866 Overview
A cryptographic vulnerability has been identified in the Ethereum Name Service (ENS) smart contracts that enables RSA signature forgery attacks. The RSASHA256Algorithm and RSASHA1Algorithm contracts in ENS versions 1.6.2 and prior fail to properly validate PKCS#1 v1.5 padding structure when verifying RSA signatures. This implementation flaw allows attackers to exploit Bleichenbacher's 2006 signature forgery attack against DNS zones using RSA keys with low public exponents (e=3).
The vulnerability is particularly concerning for ENS-supported Top-Level Domains (TLDs) that use e=3 for their Key Signing Keys, specifically .cc and .name domains. Successful exploitation allows malicious actors to fraudulently claim any domain under these TLDs on ENS without actual DNS ownership.
Critical Impact
Attackers can forge RSA signatures to fraudulently claim DNS domains on ENS without legitimate ownership, potentially enabling phishing, domain hijacking, and cryptocurrency theft targeting .cc and .name TLDs.
Affected Products
- Ethereum Name Service (ENS) Contracts version 1.6.2 and prior
- RSASHA256Algorithm smart contract
- RSASHA1Algorithm smart contract
Discovery Timeline
- 2026-02-25 - CVE CVE-2026-22866 published to NVD
- 2026-02-25 - Last updated in NVD database
Technical Details for CVE-2026-22866
Vulnerability Analysis
This vulnerability represents a classic Padding Oracle Attack (specifically Bleichenbacher's 2006 variant) affecting cryptographic signature verification in blockchain smart contracts. The root issue lies in insufficient validation of PKCS#1 v1.5 padding during RSA signature verification operations within the ENS DNSSEC oracle implementation.
The vulnerable contracts only verify that the last 32 bytes (for SHA-256) or 20 bytes (for SHA-1) of the decrypted signature match the expected hash value. This incomplete validation ignores the critical PKCS#1 v1.5 padding structure that should precede the hash, creating an opportunity for signature forgery when RSA keys use small public exponents.
ENS relies on DNSSEC to verify domain ownership before allowing domains to be claimed on the Ethereum blockchain. By forging valid-appearing signatures for domains using e=3 Key Signing Keys, attackers can bypass this verification entirely.
Root Cause
The root cause is improper cryptographic verification (CWE-347: Improper Verification of Cryptographic Signature). The RSASHA256Algorithm and RSASHA1Algorithm contracts perform an incomplete verification by only checking hash value equality without validating the full PKCS#1 v1.5 DigestInfo structure. According to PKCS#1 v1.5, the decrypted signature must contain a specific padding format: 0x00 0x01 [padding] 0x00 [DigestInfo] [Hash]. The vulnerable implementation skips validation of everything except the trailing hash bytes.
Attack Vector
The attack exploits the mathematical properties of RSA with small public exponents. When e=3, an attacker can craft a malicious signature S such that S^3 mod n produces a value where the trailing bytes match the expected hash, while the leading bytes (which should contain valid PKCS#1 padding) contain garbage data that the vulnerable contracts ignore.
The attack proceeds as follows:
- Attacker identifies a target domain under .cc or .name TLDs
- Attacker constructs a forged DNSSEC signature using Bleichenbacher's technique
- Attacker submits the forged signature to ENS to claim the domain
- ENS contracts verify only the hash portion, accepting the forged signature
- Attacker gains control of the ENS domain without DNS ownership
The security patch introduces proper PKCS#1 v1.5 padding validation:
+pragma solidity ^0.8.4;
+
+import "./RSAVerify.sol";
+import "../../utils/BytesUtils.sol";
+
+/// @dev Library for PKCS#1 v1.5 signature verification
+library RSAPKCS1Verify {
+ using BytesUtils for *;
+
+ /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-1
+ bytes constant SHA1_DIGEST_INFO = hex"3021300906052b0e03021a05000414";
+
+ /// @dev PKCS#1 v1.5 DigestInfo prefix for SHA-256
+ bytes constant SHA256_DIGEST_INFO = hex"3031300d060960864801650304020105000420";
+
+ /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-1
+ function verifySHA1(
+ bytes memory modulus,
+ bytes memory exponent,
+ bytes memory sig,
+ bytes20 hash
+ ) internal view returns (bool) {
+ (bool ok, bytes memory result) = recoverAndVerify(modulus, exponent, sig, SHA1_DIGEST_INFO);
+ return ok && hash == result.readBytes20(result.length - 20);
+ }
+
+ /// @dev Verifies an RSA signature with PKCS#1 v1.5 padding for SHA-256
+ function verifySHA256(
+ bytes memory modulus,
+ bytes memory exponent,
Source: GitHub Commit Reference
The fix introduces the RSAPKCS1Verify library which properly validates the DigestInfo structure before extracting and comparing hash values.
pragma solidity ^0.8.4;
import "./Algorithm.sol";
-import "./RSAVerify.sol";
+import "./RSAPKCS1Verify.sol";
import "../../utils/BytesUtils.sol";
import "@ensdomains/solsha1/contracts/SHA1.sol";
Source: GitHub Commit Reference
Detection Methods for CVE-2026-22866
Indicators of Compromise
- Unexpected ENS domain registrations for .cc or .name TLDs without corresponding DNS ownership changes
- DNSSEC signature submissions with anomalous padding patterns in RSA signatures
- Domain claims that bypass normal DNSSEC verification workflows
- Blockchain transactions calling DNSSECImpl with signatures containing non-standard PKCS#1 padding
Detection Strategies
- Monitor ENS contract events for domain claims on .cc and .name TLDs and cross-reference with actual DNS ownership records
- Implement off-chain signature validation that performs full PKCS#1 v1.5 padding verification before accepting ENS domain claims
- Analyze historical ENS transactions for domains under affected TLDs to identify potentially fraudulent claims
- Deploy blockchain monitoring tools to detect calls to vulnerable RSASHA256Algorithm and RSASHA1Algorithm contracts
Monitoring Recommendations
- Set up alerts for ENS domain registration events involving .cc and .name TLDs on both mainnet and testnets
- Monitor for unusual patterns in DNSSEC signature submissions, particularly those with non-standard byte sequences
- Track contract interactions with the vulnerable algorithm contracts until migration to patched versions is complete
- Implement webhook notifications for any high-value domain transfers under affected TLDs
How to Mitigate CVE-2026-22866
Immediate Actions Required
- Deploy the patched RSAPKCS1Verify library contract to your blockchain environment immediately
- Update DNSSECImpl.setAlgorithm to point to the newly deployed patched contract
- Audit any existing ENS domain claims under .cc and .name TLDs for potential fraudulent registrations
- Notify users and stakeholders about the vulnerability and remediation steps
Patch Information
A security patch has been merged at commit c76c5ad0dc9de1c966443bd946fafc6351f87587. The patch introduces a new RSAPKCS1Verify library that properly validates the full PKCS#1 v1.5 padding structure, including the DigestInfo prefix, before accepting RSA signatures. Organizations running ENS infrastructure should deploy this patched contract and reconfigure their DNSSECImpl to use the updated algorithm implementations.
For detailed patch information, refer to the GitHub Security Advisory and the Bug Fix Pull Request.
Workarounds
- Deploy the patched contracts independently and call DNSSECImpl.setAlgorithm to point to the patched algorithm implementations
- Temporarily disable DNSSEC verification for .cc and .name TLDs until patches are deployed (may impact functionality)
- Implement additional off-chain verification for domain claims under affected TLDs before accepting them
- Consider requiring additional proof of domain ownership for high-value domains under affected TLDs
# Configuration example - Updating DNSSECImpl to use patched algorithm
# After deploying the patched RSAPKCS1Verify contract, update the algorithm pointer
# 1. Deploy the patched contract and note the address
# PATCHED_CONTRACT_ADDRESS=0x...
# 2. Call setAlgorithm on DNSSECImpl (via your deployment framework)
# cast send $DNSSEC_IMPL_ADDRESS "setAlgorithm(uint8,address)" 8 $PATCHED_RSASHA256_ADDRESS --private-key $DEPLOYER_KEY
# cast send $DNSSEC_IMPL_ADDRESS "setAlgorithm(uint8,address)" 5 $PATCHED_RSASHA1_ADDRESS --private-key $DEPLOYER_KEY
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


