VPS优惠推送
分享好玩教程

Windows 上手动阻断 eMudhra 被泄露的中间证书(离线机器也适用)

不是所有 Windows 都能自动更新。

先把事情说清楚:这次出问题的是 eMudhra 的 8 个中间 CA 证书。

中间 CA 的作用,是「替根证书给网站签证书」。这 8 个中间 CA 的私钥泄露了。

泄露的方式特别离谱,值得看一眼。正常的 P-384 私钥长这样(一长串随机数字):

priv: 3f:9a:... (48 字节,几乎不可能猜出来)

而 eMudhra 出问题的那一份,是这样的:

priv: 00:00:00:...:00:04

对,就是 4。研究人员从 1 开始往回枚举,猜到 4 的时候,算出来的公钥和证书里公开的公钥完全一致 —— 私钥就这么破了。

拿到私钥之后,攻击者可以给任意域名签一张"看起来完全合法"的证书,包括冒充你的银行、你的公司 OA、你的路由器管理页。

打个比方:这相当于小偷拿到了能制作正规通行证的官方印章,想给谁发证就给谁发证。

正常情况下,浏览器会自己处理掉。各家动作都很快:

  • Google Chrome:10 月 17 日,通过 CRLSet 远程封锁,不用更新、不用重启浏览器就生效;
  • Mozilla Firefox:10 月 17 日,通过 OneCRL 远程封锁,从收到报告到分发完不到 3 小时;
  • Apple / Safari:10 月 19 日,系统证书信任体系已封锁;
  • Microsoft / Edge:10 月 20 日,同样已封锁。

所以只要你的浏览器是最近更新的、而且连着网,基本已经免疫了。

但「浏览器安全了」不等于「你的机器安全了」。curl、Python、Node.js、以及大量直接读系统证书库的应用程序,走的不是浏览器那套远程封锁机制 —— 它们只认系统里的根证书/中间证书列表。系统不更新,它们就还信着。

这也是本文为什么要手动把证书塞进「不信任列表」:拦的不是浏览器,是那些不走浏览器规则的程序。

但现实是:内网机、工控机、老系统,还有一堆「能上网但不让打补丁」的机器 —— 收不到这个更新。它们到现在还信着这些证书。

本文就是把它们手动丢进「不信任列表」。三步,五分钟,不需要联网授权,不需要等推送。

先确认一件事:你的机器是不是"中招"状态

打开这个检测站:

https://emudhra.we-have-a-problem.com/

红的就是还信着,绿的就是已经阻断。先看颜色,再决定要不要往下做。

红的话:任何用这 8 个中间 CA 签发的证书,你的浏览器都会当合法证书 —— 包括别人给自己签的「你的银行」「你的公司 OA」。

第一步:建脚本文件

随便找个目录,比如 D: 根目录。新建一个文本文件,全名改成:

Block-EmudhraCompromisedCA.ps1

注意是 .ps1,不是 .ps1.txt。Windows 默认隐藏扩展名,改之前先进「查看 → 文件扩展名」把它显示出来,不然你会得到一个打不开的文本文件。

把下面这段粘贴进去,保存:

#Requires -Version 5.1
#Requires -RunAsAdministrator
$ErrorActionPreference = 'Stop'
Import-Module PKI

$manifestSha256 = 'F67B3ABE9B4879F4E91874ED041BECCD71257F1DB41C588C724CCF12AA90C59E'
$url  = 'https://emudhra.we-have-a-problem.com/impacted-intermediates.json'
$file = [IO.Path]::GetTempFileName()

try {
    Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $file

    $hash = (Get-FileHash -LiteralPath $file -Algorithm SHA256).Hash
    if ($hash -ne $manifestSha256) {
        throw "清单 SHA-256 不匹配,未导入任何证书。当前:$hash"
    }

    $certs = Get-Content -LiteralPath $file -Raw -Encoding UTF8 | ConvertFrom-Json
    $n = 0
    foreach ($c in $certs) {
        $b64 = $c.pem -replace '-----(BEGIN|END) CERTIFICATE-----', '' -replace 's', ''
        [IO.File]::WriteAllBytes($file, [Convert]::FromBase64String($b64))
        Import-Certificate -FilePath $file -CertStoreLocation Cert:LocalMachineDisallowed | Out-Null
        $n++
    }
    Write-Host "已导入 $n 个中间 CA 到不信任列表" -ForegroundColor Green
}
finally {
    Remove-Item -LiteralPath $file -ErrorAction SilentlyContinue
}

这里有个细节值得说一下:脚本会先校验清单文件的 SHA-256,对不上就直接退出、一张证书都不导入。因为清单是从公网下载的,不校验等于「谁劫持了下载,谁就能决定你信谁」——那就本末倒置了。

第二步:运行

在保存脚本的文件夹里,资源管理器顶部的地址栏直接输入 powershell 回车 —— 这样打开的命令行会定位在当前目录,不用 cd。

然后执行:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .Block-EmudhraCompromisedCA.ps1

要点:

  • 必须是管理员。写 LocalMachine 的证书存储需要提权,普通窗口会报权限错误;
  • -ExecutionPolicy Bypass 是必须的 —— 默认执行策略会拦下未签名的脚本;
  • 跑完应该看到 已导入 N 个中间 CA 到不信任列表。

第三步:验证

回到那个检测站,刷新。

变绿就成了。


想用命令行确认也可以,看一眼不信任列表里有没有这些证书:

Get-ChildItem Cert:LocalMachineDisallowed | Where-Object { $_.Subject -like '*eMudhra*' } | Select-Object Subject, Thumbprint

这不算"修好了"

手动导入只是让这一台机器不再信任它们。真正该做的是等 Windows 正式更新把根列表推下来 —— 那时候系统会自动处理,你这两步也就不需要了。

所以适用场景很明确:

  • 能自动更新、能等推送的机器 → 别折腾,直接更新;
  • 离线机、隔离网、不能打补丁的老机器 → 用这个;
  • 批量的话,把脚本丢进组策略 / SCCM 的启动脚本里,比一台台敲快得多。

另外补一句:改完记得重启浏览器。Chrome / Edge 有自己的一份缓存,不重启可能还是旧状态。

来源

这套做法最早是我在 NodeSeek 看到网友「80hou」整理的《中间 CA 私钥泄露修复留档》里学到的,原文写得很干净。本文按自己的习惯重写了一遍,脚本也加了中文提示和错误信息。

  • 检测站与清单:https://emudhra.we-have-a-problem.com/
  • 站点源码:https://github.com/galadran/we-have-a-problem.com
  • 原帖(需登录):https://www.nodeseek.com/post-1000277-1
  • 私钥枚举细节与各家处理时间表:小众软件这篇(写得更通俗,推荐先看)
  • 事件背景(中间 CA 泄露是怎么回事):一周七个雷

清单哈希以检测站当前发布为准;如果你跑的时候报 SHA-256 不匹配,先去检测站核对最新值,别硬改脚本。

赞(0)
未经允许不得转载:F12笔记 » Windows 上手动阻断 eMudhra 被泄露的中间证书(离线机器也适用)

评论 抢沙发