APT 漏洞 CVE-2026-109518 自查与修复:阿里云、腾讯云换源后怎么确认
CVE-2026-109518 能让 HTTP 路径上的攻击者或恶意镜像以 root 执行代码。五分钟查清 apt 版本、软件源协议和镜像同步情况,再用 Ubuntu 给出的命令安全升级。
CVE-2026-109518:先看结论
CVE-2026-109518 是 APT 的一个高危漏洞。中间人(位于服务器和软件源之间、能修改流量的人)只要能篡改 HTTP 流量,就可以让 APT 装上一个没有通过验证的包,然后以 root 身份执行代码。恶意镜像站也能做到同样的事。漏洞的前提是 Acquire::Retries 不为 0,而 Ubuntu 和 Debian 都写明,这个值从 Ubuntu 22.04 和 Debian 12 起默认是 3。所以这些版本在默认配置下受影响,修复方法是把 apt 升级到下面表格里的版本。
漏洞由 Max Justicz 发现。Ubuntu 在 2026 年 11 月 4 日发布了安全公告 USN-8996-1,优先级为 High,CVSS(通用漏洞评分系统)v4.0 分数是 7.7。Debian 的公告是 DSA-6607-1 和 DLA-4880-1。
五分钟的检查顺序如下:
- 运行脚本,对比已安装版本、候选版本和修复版本。
- 查看
Acquire::Retries的值。 - 查看软件源走 http 还是 https。
- 确认镜像已经提供修复版,然后升级。
这个 APT 漏洞怎么触发
Ubuntu 的 CVE 页面 写明:问题的原因是硬链接被重复使用,攻击由一次包安装触发,并且需要客户端跟随重定向、重试下载包文件。Debian 的公告从另一个角度描述:HTTP 重定向让两个下载得到相同的 URI 时,APT 可能把它们合并。恢复 HTTP 下载时的文件处理也有问题,中间人可以在验证完成之后替换包。包的安装脚本以 root 身份运行,所以替换成功就等于拿到 root。
下面几条边界来自 Ubuntu 的博客:
- 漏洞在 APT 的 HTTP 后端,所以所有 APT 前端都受影响,不只是
apt这一个命令。 - 通过 snap 安装软件不受影响。FTP 等其他传输方式也不受影响。
- 博客的原话是 "The use of TLS via HTTPS protects against this vulnerability",也就是说 HTTPS 能挡住路径上的攻击。
- 博客同时说明,恶意镜像可以用类似方式利用这个漏洞。
最后一条对换过源的机器最重要,后面的镜像部分会单独讲。
各发行版的 apt 修复版本
这张表在 2026 年 11 月 5 日对照 USN-8996-1、Ubuntu CVE 页面和 Debian 安全跟踪页面 核对过。
此图表背后的数据
[
{
"distro": "Ubuntu 26.10",
"codename": "stonking",
"fixed_apt": "3.3.3ubuntu0.1",
"channel": "\u666e\u901a\u66f4\u65b0",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 26.04 LTS",
"codename": "resolute",
"fixed_apt": "3.2.1ubuntu0.1",
"channel": "\u666e\u901a\u66f4\u65b0",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 24.04 LTS",
"codename": "noble",
"fixed_apt": "2.8.4ubuntu0.1",
"channel": "\u666e\u901a\u66f4\u65b0",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 22.04 LTS",
"codename": "jammy",
"fixed_apt": "2.4.15ubuntu0.1",
"channel": "\u666e\u901a\u66f4\u65b0",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 20.04 LTS",
"codename": "focal",
"fixed_apt": "2.0.12+esm1",
"channel": "Ubuntu Pro",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 18.04 LTS",
"codename": "bionic",
"fixed_apt": "1.6.19+esm1",
"channel": "Ubuntu Pro",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 16.04 LTS",
"codename": "xenial",
"fixed_apt": "1.2.36+esm1",
"channel": "Ubuntu Pro + Legacy \u9644\u52a0\u7ec4\u4ef6",
"advisory": "USN-8996-1"
},
{
"distro": "Ubuntu 14.04 LTS",
"codename": "trusty",
"fixed_apt": "1.0.1ubuntu2.24+esm4",
"channel": "Ubuntu Pro + Legacy \u9644\u52a0\u7ec4\u4ef6",
"advisory": "USN-8996-1"
},
{
"distro": "Debian 13",
"codename": "trixie",
"fixed_apt": "3.0.4",
"channel": "security \u4ed3\u5e93",
"advisory": "DSA-6607-1"
},
{
"distro": "Debian 12",
"codename": "bookworm",
"fixed_apt": "2.6.2",
"channel": "security \u4ed3\u5e93",
"advisory": "DLA-4880-1"
},
{
"distro": "Debian testing \u548c unstable",
"codename": "forky, sid",
"fixed_apt": "3.3.6",
"channel": "\u666e\u901a\u66f4\u65b0",
"advisory": "Debian \u5b89\u5168\u8ddf\u8e2a\u9875\u9762"
}
]比如 Ubuntu 24.04 要升级到 2.8.4ubuntu0.1,Debian 12 要升级到 2.6.2,Debian 13 要升级到 3.0.4。
Ubuntu 14.04 到 20.04 只能通过 Ubuntu Pro 拿到修复。其中 14.04 和 16.04 还需要 Legacy 附加组件。这些旧版本在默认配置下不受影响。Ubuntu 的博客说,它们只有在 Acquire::Retries 被设成非零值时才受影响,所以第二步的检查对它们同样有用。
Ubuntu Pro 页面 写的是个人使用最多 5 台物理机免费,Ubuntu 社区正式成员最多 50 台。VPS 不是物理机,所以你的 VPS 算不算在内,请到这个页面确认。
Debian 的跟踪页面没有 Debian 11 这一行。Debian 11 比 Debian 12 更早,按跟踪页面的说法,默认配置下不受影响。如果你手动设置过非零的 Acquire::Retries,请到 Freexian 的 ELTS(Extended LTS)跟踪页面 deb.freexian.com/extended-lts/tracker/ 查这个 CVE 编号。长期来看,还是按 Debian 11 停止支持后的升级路径 迁移。
第一步:我的 apt 版本修复了吗
版本号不能用眼睛比较。2.8.3 和 2.8.4ubuntu0.1 这种字符串有 Debian 自己的排序规则,所以比较交给 dpkg --compare-versions。条件成立时它返回 0,否则返回 1,脚本就靠这个返回值分支。一台新机器的镜像可能已经带了修复版,也可能没有,所以脚本把两种情况都处理了。
cat > /tmp/apt-cve-check.sh <<'EOF'
#!/bin/bash
. /etc/os-release
case "$ID:$VERSION_ID" in
ubuntu:22.04) fixed=2.4.15ubuntu0.1 ;;
ubuntu:24.04) fixed=2.8.4ubuntu0.1 ;;
ubuntu:26.04) fixed=3.2.1ubuntu0.1 ;;
ubuntu:26.10) fixed=3.3.3ubuntu0.1 ;;
debian:12) fixed=2.6.2 ;;
debian:13) fixed=3.0.4 ;;
*) echo "NOT IN SCRIPT: $PRETTY_NAME"; exit 2 ;;
esac
installed=$(dpkg-query -W -f='${Version}' apt)
candidate=$(LC_ALL=C apt-cache policy apt | awk '/Candidate:/ {print $2}')
echo "installed: $installed"
echo "candidate: $candidate"
echo "fixed: $fixed"
if dpkg --compare-versions "$installed" ge "$fixed"; then
echo "RESULT: patched"
elif dpkg --compare-versions "$candidate" ge "$fixed"; then
echo "RESULT: not patched, fix is available from your sources"
else
echo "RESULT: not patched, your sources do not offer the fix yet"
fi
EOF
sudo apt update
bash /tmp/apt-cve-check.shLC_ALL=C 让 apt-cache policy 固定输出英文,这样 awk 才能匹配 Candidate:,不受系统语言影响。脚本的最后一行告诉你下一步做什么:
RESULT: patched:apt 已经是修复版。这台机器的 APT 修复完成,可以直接看后面的 Docker 部分。RESULT: not patched, fix is available from your sources:你的源已经提供修复版,继续第二步和第三步,然后升级。RESULT: not patched, your sources do not offer the fix yet:你的镜像还没有修复版,或者你的源里缺少相应的仓库。先看镜像同步那一节。NOT IN SCRIPT:你的系统不在脚本里。Ubuntu 14.04 到 20.04 请对照上面的表格,衍生发行版请看它自己的公告。
第二步:查看 Acquire::Retries
apt-config dump | grep -E '^Acquire::Retries '如果输出 Acquire::Retries "0";,说明这台机器明确关闭了重试。如果输出其他数字,说明重试是打开的。
如果什么都不输出,不要理解成 0。apt 的源码在这个配置项没有设置时使用 3,写法是 FindI("Acquire::Retries", 3)。apt-config dump 只反映配置,代码里的缺省值不一定会出现在这里,所以没有输出时请按重试已打开处理。apt.conf(5) 也没有写默认值,默认值 3 的依据是 Ubuntu 和 Debian 的 CVE 页面。
这一步只帮你判断风险。无论结果是什么,都要升级 apt。
第三步:软件源走 http 还是 https
软件源有两种格式。一行式写在 /etc/apt/sources.list 或 .list 文件里。deb822 格式写在 .sources 文件里,用 URIs: 字段。下面两条命令都能覆盖这两种格式。
apt-cache policy | grep -E 'https?://'
grep -RhE '^[[:space:]]*(deb|URIs:)' /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null第一条看 APT 实际加载的源,需要先运行过 sudo apt update。第二条直接读配置文件,以 # 开头的注释行不会出现。两条的结果不一致时,一个可能的原因是文件改过但还没有运行 apt update。如果同一个源写在两种格式里,请参考 APT 提示 deb822 源重复时的处理方法。
只要有一条源是 http://,这条源就是漏洞描述的那种传输方式。一条都不要漏掉,尤其是 security 那一行。
换源之后,http 是从哪里来的
换了国内镜像,不等于换了协议。换源命令改什么,要看命令本身。
只替换主机名的 sed 不会改协议。 比如下面这条,文件里原来是 http://archive.ubuntu.com,替换后就是 http://mirrors.aliyun.com,协议保持原样。
sudo sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list这条命令只改 /etc/apt/sources.list。在使用 /etc/apt/sources.list.d/ubuntu.sources 的系统上,它改不到真正生效的文件。
阿里云的 ECS 内网地址是 http。 阿里云的 Ubuntu 镜像页面 列出三个地址:公网 https://mirrors.aliyun.com/,ECS VPC 网络 http://mirrors.cloud.aliyuncs.com/,ECS 经典网络 http://mirrors.aliyuncs.com/。页面给 ECS 用户的 sed 命令同时改了主机和协议:
sed -i 's/https:\/\/mirrors.aliyun.com/http:\/\/mirrors.cloud.aliyuncs.com/g' /etc/apt/sources.list所以按这条命令切到内网之后,原来的 https 会变成 http。
腾讯云的示例也是 http。 腾讯的 Ubuntu 镜像帮助页 在 24.04 的示例里写 URIs: http://mirrors.tencentyun.com/ubuntu/,在 18.04 到 22.04 的示例里写 http://mirrors.tencent.com/ubuntu/。不过腾讯云的文档 说明内网域名 mirrors.tencentyun.com 支持 https,公网地址是 https://mirrors.tencent.com。把 http:// 改成 https:// 之后运行 sudo apt update,如果报错就改回去,然后直接升级 apt。
腾讯 24.04 的示例还有一个细节:noble-security 那一段是注释掉的,Suites 里只有 noble noble-updates noble-backports。这种配置下,你等的是 noble-updates。Launchpad 显示 24.04 的修复版 11 月 4 日进入 security,进入 updates 的时间更晚。
清华 TUNA 的 security 行也可能是 http。 TUNA 的 Ubuntu 帮助页 的镜像行用 https,但官方 security 源保留 http://security.ubuntu.com/ubuntu/。页面的理由是镜像同步有延迟,可能让生产系统拿不到最新的安全更新。腾讯的 Debian 帮助页也有类似提醒。这个做法有它的理由,但这一行仍然是 http,第三步的检查要看到它。
内网的 http 风险有多大?我们没有找到云厂商对这一点的说明,所以这里不下结论。修复也不依赖这个判断,因为升级 apt 就解决了问题。
HTTPS 能替代补丁吗
不能。Ubuntu 说 HTTPS 能防住这个漏洞的路径攻击,但同一篇博客也说恶意镜像可以用类似方式利用它。原因很好理解:TLS(传输层安全协议)保护的是你和镜像之间的这段路,而镜像本身就是 TLS 的另一端。Ubuntu 也说,装上修复版之后,被攻破的镜像就不再是这个漏洞的风险来源。
如果你想把官方源改成 https,Ubuntu 博客给的命令如下。它只处理 ubuntu.com 的官方主机,不会改第三方镜像。
sudo sed -Ei 's!http://((([a-z]+\.)?archive|security|ports)\.ubuntu\.com)!https://\1!' /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources
sudo apt update如果系统里没有 .list 或 .sources 文件,sed 会提示读不到对应的路径,这时看 apt update 的结果就行。Ubuntu 还提醒,有些社区或国家镜像不支持 HTTPS,所以 apt update 可能失败。这只是额外的预防措施,补丁还是要装。
镜像同步了吗:看 Candidate,不看名字
镜像是否可信和镜像是否同步是两回事。TUNA 和腾讯的页面都提到镜像同步有延迟。2026 年 11 月 5 日我们读到的情况如下:
- 阿里云、腾讯云和 TUNA 的 Ubuntu
pool目录都列出了四个修复版.deb,日期都是 11 月 4 日。 - 阿里云和 TUNA 的
debian-security目录都列出了apt_2.6.2和apt_3.0.4。
这只说明文件在 pool 里。APT 读的是索引,不是目录列表,所以文件存在不代表你的机器能拿到它。云厂商的内网地址也是另一个入口,我们从外部读不到。
判断依据只有一个:在你自己的机器上运行 sudo apt update,再看候选版本。第一步的脚本已经做了比较。想看版本来自哪个源,运行:
LC_ALL=C apt-cache policy aptCandidate: 这一行是 APT 准备安装的版本。下面的版本表列出每个版本来自哪个源。候选版本低于表格里的修复版时,按这个顺序排查:
- 确认源里有 security 或 updates 仓库,比如
noble-security、noble-updates,Debian 则是trixie-security或bookworm-security。 - 过一段时间再运行
sudo apt update,等镜像同步。 - 如果不想等,把 security 仓库临时指回官方地址(优先用 https),再运行
sudo apt update。
第四步:用 Ubuntu 给出的命令升级
升级全部软件包:
sudo apt update && sudo apt upgrade -o Acquire::Retries=0如果现在不想动其他软件,只升级 apt:
sudo apt update && sudo apt install -o Acquire::Retries=0 --only-upgrade '?source-package(^apt$)'这两条命令都来自 Ubuntu 的博客。关键是 -o Acquire::Retries=0。升级时运行的还是旧版 apt,而漏洞需要重试,所以把重试临时设成 0,去掉攻击需要的条件。Ubuntu 说这样做对路径上的攻击者和恶意镜像都有缓解作用。代价是下载失败时不会自动重试,失败了就再运行一次。
?source-package(^apt$) 选中由 apt 这个源码包构建的所有二进制包,所以相关的库会一起升级。
Debian 用户请注意:Acquire::Retries=0 这个做法来自 Ubuntu。Debian 的公告没有提到这个选项,只是建议升级 apt 包。不过 Debian 的跟踪页面写了同样的前提,-o 又是 apt 的通用配置选项,所以在 Debian 上可以用同样的写法。
升级完成后确认结果:
apt list --installed '?source-package(^apt$)'
bash /tmp/apt-cve-check.sh最后一行应该是 RESULT: patched。如果升级中途因为依赖问题停下,请看 修复 Ubuntu 和 Debian 上损坏的 APT 软件包。
自动更新会帮我修吗
Ubuntu 的博客说,启用了 unattended-upgrades 的系统会在 24 小时内自动应用这些补丁。换过源的机器不要只相信这句话,因为自动更新也要从你的源拿到修复版。运行第一步的脚本确认就可以。想检查自动更新的配置,Ubuntu 请看 在 Ubuntu 上配置 unattended-upgrades,Debian 请看 Debian 上 unattended-upgrades 不运行的排查方法。
Docker 镜像要不要重建
Ubuntu 的博客和 CVE 页面都没有讲 Docker 镜像,所以这里不给结论,给你一个可以自己运行的检查。把 ubuntu:24.04 换成你的镜像:
docker run --rm ubuntu:24.04 dpkg-query -W -f='${Version}\n' apt把输出和上面的表格对比。漏洞由包安装触发,所以需要重点看的是构建或运行时还会执行 apt-get install 的镜像。安全厂商 Ostorlab 的建议是,在每一台机器和每一个会安装软件包的容器镜像上都重复这次升级。如果版本低于修复版,等基础镜像更新后重新构建:
docker build --pull --no-cache -t myapp .有人在利用吗,我怎么知道是否中招
截至 2026 年 11 月 5 日,Ubuntu 和 Debian 的页面都没有提到在野利用。我们查看的 CISA KEV(已知被利用漏洞)目录版本 2026.11.04 中也没有这个编号。Ostorlab 写的是目前没有已知的在野利用,也没有公开的概念验证代码。这些只说明没有公开记录,不能证明没有人利用过。
我们不会给你一条 grep 日志的命令,因为厂商没有公布任何入侵指标。Ostorlab 说明了原因:替换成功后,dpkg 记录的文件和校验和与被替换的包是一致的,所以机器上看不出矛盾。这意味着本地校验通过并不能证明安全。Ostorlab 的建议是把包的校验和与官方归档对比,把已安装版本与归档的候选版本对比。如果一台通过 HTTP 装过包的机器出现说不清的差异,就当作可能已被入侵。
修好这一个漏洞后,建议把这类检查变成固定流程,可以继续看 检查服务器上的已知 CVE 和 Linux 服务器维护清单。
FAQ
我的软件源已经是 https,还需要修复 CVE-2026-109518 吗?
需要,仍然要安装修复版 apt。Ubuntu 说 HTTPS 能防住这个漏洞的路径攻击,但恶意镜像同样可以利用它,而镜像本身就是 TLS 连接的另一端。另外,换源后 security 那一行也可能仍然是 http://。请升级 apt,不要只改协议。
apt-config dump 里没有 Acquire::Retries,是不是就没事?
没有这一行不等于没事。apt 的源码在这个配置项没有设置时使用 3,所以没有输出不代表值是 0。Ubuntu 和 Debian 都写明,从 Ubuntu 22.04 和 Debian 12 起默认值是 3。只有明确看到 Acquire::Retries "0"; 才说明重试被关闭,而且这也不能替代升级。
运行 apt update 之后,候选版本还是旧版本,怎么办?
运行 LC_ALL=C apt-cache policy apt,看 Candidate: 和版本来源。可能的原因有两个:镜像还没有同步,或者源里没有 security 和 updates 仓库。先检查仓库配置,再等镜像同步。不想等的话,可以把 security 仓库临时指回官方地址,然后再运行 sudo apt update。
可以把 Acquire::Retries 永久设成 0,不升级 apt 吗?
不建议。Ubuntu 的 CVE 页面没有列出任何缓解措施,博客也只是说在安装这次更新时临时设为 0。Ostorlab 把它称为临时措施,并说明修复版 apt 才是永久修复。请用 -o Acquire::Retries=0 完成升级,这个选项只对这一条命令生效。
Ubuntu 20.04 或 Debian 11 受影响吗?
默认配置下不受影响,因为默认值 3 从 Ubuntu 22.04 和 Debian 12 才开始。如果你手动把 Acquire::Retries 设成了非零值,就会受影响。Ubuntu 20.04 的修复版只通过 Ubuntu Pro 提供。Debian 的跟踪页面没有 Debian 11 这一行,请到 Freexian 的 ELTS 跟踪页面查询。