咳咳,各位观众老爷们,晚上好!欢迎来到“网络安全那些事儿”小讲堂。今天咱们聊点稍微有点“过气网红”气质的东西,但绝对是网络安全领域里闪耀过的星星——HTTP Public Key Pinning (HPKP) 和 Certificate Transparency (证书透明)。
先别急着打哈欠,我知道HPKP已经被弃用了,但这并不妨碍我们从它的失败中学习经验。而Certificate Transparency,简称CT,虽然听起来高大上,但其实它就像一个“阳光下的秘密”,把证书颁发的过程晒出来,让坏人无处遁形。
咱们先从“爱作妖”的HPKP开始说起。
一、HPKP:理想很丰满,现实很骨感
HPKP,全称HTTP Public Key Pinning,翻译过来就是“HTTP公钥固定”。它的核心思想是:网站告诉浏览器,以后访问我的时候,只能信任特定的几个公钥。
1. HPKP的原理:
想象一下,你开了一家包子铺(你的网站),为了防止有人冒充你卖假包子,你给每位顾客发了一张“会员卡”(公钥)。这张卡上印着只有你家包子铺才有的特殊防伪标记。以后顾客来买包子,必须出示这张卡,确认身份无误才能卖给他。
这样一来,即使有人拿了假的会员卡(伪造的证书)想冒充你,浏览器(顾客)也会发现卡上的防伪标记不对,拒绝交易。
2. HPKP的配置:
HPKP通过HTTP头部来配置。服务器在响应头中添加Public-Key-Pins
字段,告诉浏览器应该信任哪些公钥。
Public-Key-Pins: pin-sha256="base64-encoded-sha256-hash-of-pinned-key"; max-age=expire-time; includeSubDomains; report-uri="report-url"
pin-sha256
: 指定要固定的公钥的SHA256哈希值。你需要把你的证书或者中间证书的公钥提取出来,计算SHA256哈希值,然后进行Base64编码。max-age
: 指定浏览器记住这个pin的时间,单位是秒。通常建议设置为比较长的时间,比如几个月甚至一年。includeSubDomains
: 可选参数,表示该pin也适用于所有子域名。report-uri
: 可选参数,指定一个URL,浏览器如果检测到pin验证失败,会向这个URL发送报告。
举个栗子:
假设你的网站 example.com
使用了Let’s Encrypt颁发的证书。
首先,你需要提取你的证书(或中间证书)的公钥,并计算SHA256哈希值:
openssl x509 -in example.com.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
假设运行结果是:"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
你还需要一个备用的pin(以防万一你的证书需要更换):
openssl x509 -in example.com.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
假设运行结果是:"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
那么你的HPKP头看起来会是这样:
Public-Key-Pins: pin-sha256="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; pin-sha256="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="; max-age=5184000; includeSubDomains; report-uri="https://example.com/report"
3. HPKP的问题:
理想很美好,现实很残酷。HPKP虽然能提高安全性,但它的“坑”也很多:
- 配置错误导致网站瘫痪: 如果配置错了,比如你pin了错误的公钥,或者忘记了备用pin,浏览器就会拒绝访问你的网站。这就像你给顾客发了错误的会员卡,导致他们无法买到包子,包子铺直接关门大吉。
- 证书轮换困难: 如果你的证书需要更换,你需要提前更新你的HPKP配置,否则浏览器会拒绝新的证书。这就像你要更换会员卡的防伪标记,必须提前通知所有顾客,否则他们会以为你是假包子铺。
- 难以管理: 对于大型网站来说,管理大量的pin非常困难。
- 容易被滥用: 恶意攻击者可能会利用HPKP来“锁定”某个网站的公钥,导致合法用户无法访问。
4. HPKP的“死亡”:
由于以上种种原因,HPKP最终被各大浏览器厂商弃用。Chrome在Chrome 67中移除了HPKP支持,Firefox也在Firefox 72中移除了HPKP支持。
5. HPKP的教训:
HPKP的失败告诉我们,安全措施不能过于复杂,否则会适得其反。同时也说明,安全措施需要考虑到易用性和可管理性。
二、Certificate Transparency (CT):阳光是最好的防腐剂
HPKP失败了,但我们不能因此放弃对HTTPS安全性的追求。Certificate Transparency (CT) 应运而生,它采用了一种更简单、更有效的方式来提高HTTPS的安全性。
1. CT的原理:
CT的核心思想是:将证书颁发的过程公开透明化。所有证书颁发机构 (CA) 颁发的证书都必须记录在公开的、可审计的日志服务器中。
这就像你开了一家银行,所有的存取款记录都必须公开记录在账本上,任何人都可以查阅。这样一来,如果有人伪造银行卡,或者非法转移资金,就会很容易被发现。
2. CT的组成部分:
- 证书颁发机构 (CA): 负责颁发证书。
- CT日志服务器: 负责存储证书记录。
- 监控者 (Monitors): 负责监控CT日志,发现异常情况。
- 审核者 (Auditors): 负责审核CT日志的完整性和一致性。
3. CT的工作流程:
- 网站所有者向CA申请证书。
- CA颁发证书后,将证书信息提交给CT日志服务器。
- CT日志服务器将证书信息添加到日志中,并返回一个Signed Certificate Timestamp (SCT)。SCT相当于一个“收据”,证明证书已经被记录在日志中。
- CA将SCT嵌入到证书中,或者通过其他方式(比如OCSP Stapling)提供给浏览器。
- 浏览器在验证证书时,会检查SCT是否有效。如果SCT有效,则认为证书是可信的。
- 监控者和审核者会定期检查CT日志,发现异常情况。
4. SCT的传递方式:
SCT可以通过以下三种方式传递给浏览器:
- X.509v3 Extension: SCT直接嵌入到证书的扩展字段中。
- TLS Extension: SCT通过TLS握手协议传递。
- OCSP Stapling: SCT通过OCSP Stapling传递。
5. CT的好处:
- 提高安全性: CT可以有效地防止CA颁发未经授权的证书,降低中间人攻击的风险。
- 增强透明度: CT将证书颁发的过程公开透明化,让所有人都可以监督CA的行为。
- 促进信任: CT可以增强用户对HTTPS的信任,促进HTTPS的普及。
6. CT的实施:
各大浏览器厂商都要求CA必须支持CT。Chrome从Chrome 69开始,要求所有新颁发的证书都必须符合CT的要求。
7. 如何查看证书的CT信息:
你可以通过Chrome浏览器的开发者工具查看证书的CT信息。
- 打开Chrome浏览器,访问一个HTTPS网站。
- 按下F12键,打开开发者工具。
- 选择 "Security" 选项卡。
- 点击 "View certificate" 按钮。
- 在证书详情中,你可以找到 "Certificate Transparency" 相关的 section,查看 SCT 信息。
8. CT的代码示例:
虽然你不能直接用JS代码来“实现”CT(因为CT主要由CA和浏览器实现),但你可以使用JS来验证证书的CT信息。
这里提供一个简单的例子,使用Node.js和node-forge
库来解析证书并提取SCT信息:
const forge = require('node-forge');
const fs = require('fs');
// 读取证书文件
const certPem = fs.readFileSync('example.com.crt', 'utf8');
// 解析证书
const cert = forge.pki.certificateFromPem(certPem);
// 获取证书扩展
const extensions = cert.extensions;
// 查找 CT 扩展 (OID: 1.3.6.1.4.1.11129.2.4.2)
const ctExtension = extensions.find(ext => ext.id === '1.3.6.1.4.1.11129.2.4.2');
if (ctExtension) {
// 解析 Signed Certificate Timestamp List
const sctListAsn1 = forge.asn1.fromDer(ctExtension.value);
// 遍历 SCT List
sctListAsn1.value.forEach(sctAsn1 => {
// 解析单个 SCT
const sct = {
version: sctAsn1.value[0].value,
logId: forge.util.bytesToHex(sctAsn1.value[1].value),
timestamp: sctAsn1.value[2].value.toNumber(),
extensions: forge.util.bytesToHex(sctAsn1.value[3].value),
signature: {
algorithm: {
algorithm: forge.pki.oids[sctAsn1.value[4].value[0].value],
},
signature: forge.util.bytesToHex(sctAsn1.value[4].value[1].value),
},
};
console.log('SCT:', sct);
});
} else {
console.log('No Certificate Transparency information found in the certificate.');
}
注意:
- 你需要安装
node-forge
库:npm install node-forge
- 你需要将
example.com.crt
替换成你的证书文件路径。 - 这个代码只是一个简单的示例,用于演示如何提取SCT信息。实际应用中,你需要对SCT进行更严格的验证。
9. CT的未来:
CT已经成为HTTPS安全性的重要组成部分。未来,CT将会更加普及,并发挥更大的作用。
三、HPKP vs CT:殊途同归
HPKP和CT的目标都是提高HTTPS的安全性,但它们采用的方式却截然不同。
特性 | HPKP | CT |
---|---|---|
原理 | 公钥固定 | 证书透明化 |
实施者 | 网站管理员 | 证书颁发机构 (CA)、浏览器 |
风险 | 配置错误导致网站瘫痪 | 对CA的依赖性较高 |
易用性 | 复杂 | 相对简单 |
可管理性 | 差 | 好 |
适用场景 | 理论上适用于所有HTTPS网站 | 适用于所有HTTPS网站 |
现状 | 已弃用 | 强制要求 |
核心思想 | 信任特定的公钥 | 信任透明的证书颁发过程 |
HPKP过于复杂和脆弱,最终走向了失败。CT则更加简单、有效,并得到了广泛的应用。
四、总结:
虽然HPKP已经成为了历史,但它给我们留下了深刻的教训。在设计安全措施时,我们不仅要考虑安全性,还要考虑易用性和可管理性。CT的成功则告诉我们,透明化是提高安全性的有效手段。
希望今天的讲座能让你对HPKP和CT有一个更深入的了解。记住,网络安全之路,任重道远,需要我们不断学习和探索。
下课!