实现原理:安全评分算法
对应代码:
pkg/security.go· 入口AnalyzeSecurity(target)/AnalyzeSecurityFromCert(cert, host)
analyze 命令给出的 0-100 分是怎么算出来的?本页拆到字段、阈值与代码行。
总体流程
数据结构(完整字段)
SecurityAnalysis(security.go L12-21)顶层结构:
ExpirationCheck.Status 的状态机:
10 条 issue 精确触发条件
collectSecurityIssues(L266-358)共收集 10 条问题,每条 severity 与触发条件精确如下:
| Severity | Type | 触发条件(精确) |
|---|---|---|
| Critical | Certificate Expired | CertificateCheck.IsExpired |
| High | Certificate Expiring Soon | IsExpiringSoon(0 < DaysUntilExpiry <= 30) |
| High | Weak Signature Algorithm | WeakSignature(签名算法 ∈ {MD5, SHA1}) |
| Medium | Self-Signed Certificate | IsSelfSigned(Subject==Issuer) |
| High | Weak Key Size | WeakKeySize(KeySize>0 && <2048) |
| High | Certificate Chain Invalid | !ChainValid |
| High | Insecure TLS Version | !IsSecureVersion(版本 ∉ {TLS 1.2, TLS 1.3}) |
| High | Weak Cipher Suite | !IsSecureCipherSuite(含 RC4/DES/3DES/NULL/EXPORT) |
| Low | Missing OCSP Stapling | !HasOCSPStaple |
| Medium | Missing HSTS Header | HSTS!=nil && !HSTS.Enabled |
扣分算法
为什么离线扣分更保守?
离线模式拿不到协议层信息(TLS 版本、套件、漏洞、HSTS、OCSP staple),少了一大块扣分来源——所以同等证书离线分通常更高。详见下表与 离线 vs 在线分析。
同一证书可能给出不同等级
在线 / 离线不仅扣分权重不同,等级阈值也不同。一张 40-59 分的证书:在线判 Critical 🔴,离线判 High 🟠。对比两次扫描结果时务必确认是否同模式。
离线 vs 在线评分权重精确对比
| 维度 | 在线(security.go L361-393) | 离线(offline.go L67-95) |
|---|---|---|
| Critical 扣分 | −30 | −25 |
| High 扣分 | −20 | −15 |
| Medium 扣分 | −10 | −5 |
| Low 扣分 | −5 | −2 |
| Good 阈值 | ≥90 | ≥80 |
| Medium 阈值 | ≥70 | ≥60 |
| Low 等级 | ≥50 | —(无 Low 等级) |
| High 等级 | —(无 High 等级) | ≥40 |
| Critical 阈值 | <50 | <40 |
| 起始分 | 100 | 100 |
| 下限 | 0 | 0 |
关键差异:
- 离线每级少扣 5 分(更宽容)
- 但等级阈值更严:Good 从 90 降到 80;离线无 "Low" 等级,多一个 "High" 等级覆盖 40-59
- 同一张证书在 40-59 区间:在线判 Critical,离线判 High
关键常量
| 常量 | 值 | 位置 |
|---|---|---|
weakSignatures | {MD5, SHA1} | L151 |
secureVersions | {TLS 1.2, TLS 1.3} | L208 |
weakCiphers | {RC4, DES, 3DES, NULL, EXPORT} | L226 |
| 即将过期阈值 | 30 天 | L148 |
| 超长有效期阈值 | 398 天(且非自签) | L188 |
| 到期状态 Expired | <0 天 | — |
| 到期状态 Critical | <=7 天 | — |
| 到期状态 Warning | <=30 天 | — |
批量评分
BatchAnalyzeSecurityWithContext(L440-525)的并发模型:
- 并发上限:
maxConcurrency=10(硬编码,targets 少于 10 时下调) - 信号量:
chan struct{}容量 10 - 无超时:由调用方 ctx 控制
- 错误路径:
- ctx 取消 → 产出
SecurityLevel:"Error"/Severity:"Critical"/Type:"Cancelled"的 issue - 分析失败 →
Type:"Connection Failed" - Summary 聚合时
"Critical"与"Error"都计入CriticalCount
- ctx 取消 → 产出
- AverageScore:
totalScore / len(targets)整数除法
BatchSummary 字段:GoodCount / MediumCount / LowCount / CriticalCount / AverageScore。
与 18 项检查的关系
两者共用底层证书层检查函数,但展示形式不同:analyze 给总分,scan-cert-security 给逐项明细。
下一步
- 18 项检查细节 → 18 项证书检查
- 漏洞怎么探测 → TLS 漏洞探测
- 离线全貌 → 离线 vs 在线分析