审计TLS证书透明度日志 是做什么的?
使用场景
- 监控自有域名,检测未知证书颁发机构(CA)未经授权或意外的证书签发
- 通过公开CT日志中的证书发现子域名和隐藏服务
- 检测使用相似域名证书的网络钓鱼基础设施(域名仿冒、同形攻击)
- 审计CA的合规性,验证所有已签发证书是否如浏览器策略所要求,出现在CT日志中
- 将持续证书监控集成到安全运营流水线,并对新签发行为设置告警
禁止使用于攻击或干扰CA、违反速率限制或服务条款爬取CT日志、或作为子域名枚举的唯一方法而不通过DNS验证佐证。
前提条件
- Python 3.10+,已安装
requests、cryptography和pyOpenSSL库 - 能够访问 crt.sh(HTTPS)和公开CT日志服务器
- 待监控域名列表(自有域名、品牌变体、域名仿冒候选)
- 用于新证书发现告警的SMTP凭据或Webhook URL
- 基本了解X.509证书结构和TLS证书链验证
工作流程
步骤1:域名清单与基线
为受监控的域名构建初始证书清单:
- 定义监控范围:列出所有自有根域名、注册品牌名称和已知子公司。包含通配符模式(
%.example.com)以实现全面的子域名覆盖。 - 查询crt.sh获取历史证书:使用crt.sh JSON API检索每个域名的所有已知证书。API端点
https://crt.sh/?q=%.example.com&output=json返回匹配通配符模式的证书,包含字段:issuer_ca_id、issuer_name、common_name、name_value、not_before、not_after和serial_number。 - 构建基线数据库:将初始证书集存储在本地SQLite数据库中,包含证书ID、域名、颁发者、有效期、SANs(主题备用名称)和首次发现时间戳。此基线可防止对已知证书重复告警。
- 识别授权CA:从基线中提取已为你域名合法签发证书的CA集合。将来任何来自非此集合CA的证书签发将触发高优先级告警。
- 映射子域名:从所有证书的
name_value字段中提取所有唯一子域名,构建初始子域名清单。
步骤2:持续CT日志监控
建立持续监控以发现新证书签发:
- 定期轮询crt.sh:以固定间隔(每15-60分钟)查询crt.sh API获取新证书。使用
exclude=expired参数聚焦当前有效的证书。将结果与基线数据库比较以识别新条目。 - 解析证书详情:对于每个新证书,提取完整的SAN列表、颁发者链、有效期、密钥类型和大小、CT日志SCT(签名证书时间戳)详情以及证书指纹(SHA-256)。
- 检测预证书:CT日志包含预证书(最终签发前提交的“加毒”证书)。将其作为早期警告进行跟踪,因为它们表明某个证书即将签发但尚未生效。
- 监控CT日志签名树头(STH):对于高级监控,直接查询CT日志服务器以获取最新STH,并验证连续树头之间的一致性证明。不一致表明日志行为异常(分叉攻击)。
- 速率限制感知:通过间隔查询和缓存响应来尊重crt.sh的速率限制。在收到HTTP 429响应时实施指数退避。对于高流量监控,可考虑直接查询crt.sh的PostgreSQL接口,地址为
crt.sh:5432。 - Atom/RSS订阅替代方案:订阅crt.sh的Atom订阅源以实现更轻量的监控:
https://crt.sh/atom?q=%25.example.com提供新日志条目的实时通知。
步骤3:通过CT数据进行子域名发现
从证书透明度数据中提取并验证子域名:
- 通配符扩展:带有通配符SAN(
*.dev.example.com)的证书揭示了DNS区域文件中可能不存在的子域。将父域记录为进一步枚举的目标。 - 历史证书挖掘:不使用
exclude=expired参数查询crt.sh,从过期证书中发现子域名,这些子域名可能仍在DNS中解析。它们代表了可能易受子域名接管攻击的历史基础设施。 - DNS验证:对每个发现的子域名执行DNS解析(A、AAAA、CNAME记录),以确定子域名当前是否活跃。与已知IP范围交叉引用,以识别Shadow IT或未经授权的服务。
- 域名仿冒检测:生成受监控域名的排列组合(位攻击、同形攻击、插入、省略、换位、键盘相邻替换),并查询CT日志中是否有针对这些变体签发的证书。针对仿冒域名的证书强烈表明存在网络钓鱼基础设施。
- 去重与丰富:规范化发现的子域名(小写、去除尾点)、去重,并通过WHOIS数据、IP地理定位和HTTP响应头来丰富信息,以确定调查优先级。
步骤4:证书签发告警
为安全相关的证书事件配置告警规则:
- 未经授权CA告警:当证书由未在授权CA列表中的CA签发时触发。这是最高优先级的告警,可能表明域名劫持、用于域名验证的BGP劫持或CA遭到入侵。
- 新子域名告警:当证书包含以前未见过的子域名SAN时触发。这可以捕捉Shadow IT部署和未经授权的服务。
- 通配符证书告警:对任何新的通配符证书签发触发告警,因为通配符证书一旦泄露影响范围更大,且其签发应被严格控制。
- 短生命周期证书异常:当证书的有效期异常短(不足24小时),偏离组织的正常证书生命周期时,触发告警。这可能表明Let's Encrypt的滥用或自动化网络钓鱼基础设施。
- 过期警告:当关键服务的证书即将过期(30、14、7天)时,基于CT日志数据中的
not_after字段触发告警。 - 告警投递:通过电子邮件(SMTP)、Slack webhook、PagerDuty发送告警,或写入与SIEM兼容的JSON日志格式,以便集成到现有的安全监控中。
步骤5:CT日志完整性验证与报告
验证日志完整性并生成合规证据:
- 签名树头(STH)监控:通过
get-sthAPI端点从每个受监控的CT日志获取最新STH。STH包含树大小和签名时间戳。使用日志的公钥验证签名。 - 一致性证明验证:在连续两次获取STH之间,通过
get-sth-consistency请求一致性证明,以验证日志始终保持仅追加状态,没有条目被修改或删除。 - 证书清单报告:生成受监控域名所有已签发证书的完整清单,按颁发者分组,并包含有效状态和密钥强度指标。
- CA多样性分析:报告有多少不同的CA为该组织签发证书,识别整合机会和单点故障。
- 合规证据:对于受PCI-DSS、SOC 2或类似框架约束的组织,CT监控日志提供了证书生命周期管理和未经授权签发检测能力的证据。
关键概念
| 术语 | 定义 |
|---|---|
| 证书透明度(CT) | 一个开放的框架(RFC 6962),要求CA将所有已签发证书记录在公开可审计的仅追加日志中,使域名所有者能够检测到未经授权的签发 |
| 签名证书时间戳(SCT) | CT日志保证某个证书将在最大合并延迟内(通常24小时)被纳入日志的承诺;浏览器在信任某个证书之前,要求其持有来自多个日志的SCT |
| Merkle树 | CT日志使用的加密数据结构,叶节点是证书哈希,父节点是其子节点的哈希,支持高效的一致性证明和归属证明 |
| 预证书 | 在最终签发前提交给CT日志的证书,包含一个 poison 扩展(OID 1.3.6.1.4.1.11129.2.4.3),阻止其用于TLS但保留其在日志中的位置 |
| crt.sh | 由Sectigo运营的免费网络服务,将来自所有主要CT日志的证书聚合到一个可搜索的PostgreSQL数据库中,提供Web和API访问 |
| 子域名接管 | 一种漏洞,当子域名的DNS记录指向已停用的服务(云提供商、CDN)而攻击者可重新注册该服务时发生,可通过过期的CT证书发现 |
| 最大合并延迟(MMD) | CT日志在返回SCT后,将提交的证书合并到其Merkle树中的最大时间(通常24小时) |
| CAA记录 | DNS认证机构授权记录,指定哪些CA被允许为某个域名签发证书;CT监控可检测对CAA策略的违反 |
工具与系统
- crt.sh:主要CT日志聚合器,通过
https://crt.sh/?q=<query>&output=json提供JSON API访问,支持通配符查询、身份过滤和证书详情检索 - ct-woodpecker:来自Let's Encrypt的开源CT日志监控工具,与Prometheus和Grafana集成,用于日志健康和一致性的操作监控
- certspotter:SSLMate的CT日志监控器,监控新颁发的证书并发送通知;可作为托管服务或自托管工具使用
- Google Argon / Xenon / Icarus:谷歌运营的CT日志,是使用最广泛的日志之一,可通过其各自日志URL上的RFC 6962 API进行查询
- OpenSSL:命令行工具,用于解析证书详情、验证证书链以及从通过CT监控检索的证书中提取SAN列表
常见场景
场景:为金融服务公司检测未经授权的证书签发
背景:一家银行监控其主域名(bank.example.com),通过CT日志发现有一个他们从未使用过的CA签发了一张证书,覆盖了 secure-login.bank.example.com —— 一个在DNS中不存在的子域名。
方法:
- CT监控代理在crt.sh结果中检测到来自“FreeSSL CA”的
secure-login.bank.example.com的新证书,该CA不在授权CA列表中(DigiCert、Sectigo) - 告警触发(未经授权CA + 新子域名),在CT日志条目出现后的15分钟内上报给安全团队
- 调查该证书:提取公钥,检查域名是否通过HTTP-01或DNS-01挑战验证,查询颁发组织的WHOIS信息
- 对
secure-login.bank.example.com进行DNS查询,发现其解析到银行未使用的托管提供商的IP地址——确认这是攻击者基础设施 - 启动事件响应:向FreeSSL CA请求吊销证书,提交域名滥用报告,将IP加入黑名单,并通知反钓鱼团队
- 实施CAA DNS记录(
bank.example.com. CAA 0 issue "digicert.com"),以防止未经授权的CA将来签发证书
陷阱:
- 未监控通配符模式(
%.bank.example.com),遗漏了针对子域名的证书 - 忽略了在正式证书签发前就出现在CT日志中的预证书,丧失早期预警优势
- 事件后未能验证CAA记录是否在所有域名上正确配置
- 由于授权更改后未更新基线数据库,对合法的证书续签过度告警
场景:通过CT日志子域名发现进行攻击面映射
背景:渗透测试人员将CT日志作为外部侦察的第一阶段,在主动扫描之前映射目标组织的互联网暴露服务。
方法:
- 查询crt.sh获取
%.target.com及所有已知子公司域名,收集了跨越8年的2,400个唯一证书 - 从所有证书(包括过期的)的SAN字段中提取347个唯一子域名
- 对所有347个子域名进行DNS解析,发现其中189个当前活跃,具有A/AAAA记录
- 识别出12个指向已停用云服务的子域名(CNAME指向S3存储桶、Azure端点),可能是子域名接管的候选
- 发现
staging-api.target.com和dev-portal.target.com,这些不在目标文档化的范围内,但可访问且运行着较旧版本的软件 - 向目标组织展示发现结果,显示其已知资产清单与CT衍生的攻击面之间的差距
陷阱:
- 假设所有CT发现的子域名都在范围内,而未与资产所有者确认
- 未检查通配符DNS响应,这可能导致子域名看起来存在时,实际解析到catch-all
- 仅依赖CT数据,而未交叉引用被动DNS数据库以获得全面覆盖
输出格式
## CT日志监控报告
**域名**:example.com
**监控周期**:2026-03-01 至 2026-03-19
**跟踪证书总数**:142
**检测到新证书**:7
**生成告警数**:2
### 告警:未经授权CA签发
- **严重性**:严重
- **证书CN**:secure-login.example.com
- **SANs**:secure-login.example.com、
- **颁发者CA**:FreeSSL CA(未经授权)
- **签发日期**:2026-03-15 14:22:33 UTC
- **过期日期**:2026-06-13 14:22:33 UTC
- **SHA-256指纹**:A1:B2:C3:...
- **发现时间**:2026-03-15 14:37:45 UTC(日志包含后约15分钟)
- **行动项目**:立即开始事件响应流程;联系FreeSSL CA请求吊销;更新防火墙规则;向域名注册商报告
### 告警:新子域名发现
- **严重性**:中等
- **子域名**:staging-api.target.com
- **来源证书ID**:证书ID #10492
- **首次DNS解析**:192.0.2.45(AWS EC2,us-east-1)
- **HTTP响应**:HTTP 200 OK,服务器:nginx/1.18.0
- **服务识别**:REST API端点,具有Swagger UI文档
- **行动项目**:联系资产所有者以确定该服务是否应为影子IT;如果授权,则添加至资产清单;如果未经授权,则启动下线流程