79% 对 51%:独立数字银行的应用安全落后。 阅读报告

深度解析

深度解析

Dropbear:SSH 限制绕过可到达 root 套接字

仅限一个 TCP 目标的 Dropbear 密钥仍可打开 Unix 套接字(包括 docker.sock),因为按目标检查跳过了流转发。

TL;DR

  • Dropbear 对 TCP 转发执行 permitopen 和 permitlisten,但对 Unix 套接字转发不执行。仅限一个 TCP 目标的密钥可以打开该账户能到达的任何套接字。
  • 截至 2026.94 的所有 Dropbear 版本和 Git HEAD 99baf182 都受影响。本地和远程流转发选项默认启用。
  • 当账户能到达 Docker 守护进程或数据库套接字时,研究者 knell 将其评为 9.9。没有分配 CVE,没有报告利用,截至 2026 年 11 月 14 日也不在 CISA 的 KEV 目录中。
  • 没有修复版本。为受限密钥添加 no-port-forwarding,或在关闭流转发选项的情况下重新编译 Dropbear。每种措施的成本见“如何修复?”。

我受影响吗?

以下条件全部成立时,您会受影响:

  • 服务器运行 Dropbear,任何版本或截至 99baf182(2026-11-11)的 Git HEAD。
  • 构建保持 Unix 套接字转发启用。DROPBEAR_SVR_LOCALSTREAMFWD 和 DROPBEAR_SVR_REMOTESTREAMFWD 默认为 1。
  • 至少一个 authorized_keys 条目带有 permitopen= 或 permitlisten=。该限制正是密钥持有者不被授予通用访问的原因。
  • 该密钥背后的账户能到达敏感 Unix 套接字,例如 /var/run/docker.sock 或数据库套接字。研究者的 9.9 案例是 Docker 套接字。
  • 攻击者持有该受限密钥,或能使用持有它的账户。

没有 permitopen 或 permitlisten 限制的密钥不是本缺陷的对象:其持有者已经拥有通用转发访问。绕过影响的是管理员特意收窄的密钥。

分支 受影响版本 修复版本
发布版本 截至 2026.94(2026-07-23) 无
Git 截至 99baf182(2026-11-11) 无

检查服务器版本和受限密钥:

# Server and client version
dropbear -V

# Keys that carry a per-destination restriction
grep -R -E 'permitopen=|permitlisten=' /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys 2>/dev/null

# Accounts that can reach the Docker socket
getent group docker

密钥列表是重要检查。带有 permitopen 的密钥,其账户同时属于 docker 组,就是研究者描述的 9.9 案例。

如何修复?

截至 2026 年 11 月 14 日,没有修复的 Dropbear 版本。按优先级应用以下三项缓解措施之一,并在项目发布基于路径的修复后移除。

  1. 为每个带有 permitopen 或 permitlisten 的密钥添加 no-port-forwarding。流转发处理程序通过 svr_pubkey_allows_tcpfwd() 检查该标志,因此密钥无法再打开 Unix 套接字。成本是该密钥也失去所有 TCP 转发,包括管理员允许的目标。
  2. 在 localoptions.h 中设置 DROPBEAR_SVR_LOCALSTREAMFWD 0 和 DROPBEAR_SVR_REMOTESTREAMFWD 0,重新编译 Dropbear。成本是该服务器上的任何账户都不能使用 Unix 套接字转发。
  3. 使用 -j -k 启动服务器。这些标志设置 nolocaltcp 和 noremotefwd,流转发处理程序会检查它们。成本是所有账户都失去本地和远程转发,而不只是受限密钥。

将账户移出 docker 组并收紧套接字权限可降低影响。它不能关闭绕过:密钥仍可到达账户能打开的任何其他套接字,包括数据库和服务套接字。

研究者建议在 svr-streamfwd.c 中实施与 TCP 路径相同的列表遍历,提供基于路径的 permitopen 等价检查。请关注 Dropbear 发布页面;项目尚未发布修复版本。

根本原因是什么?

Unix 套接字转发处理程序只检查粗粒度的 no-port-forwarding 标志。它们从不调用遍历密钥按目标列表的函数。

Dropbear 将限制保存在 authorized_keys 中。src/svr-authpubkeyoptions.c 第 65 行的 svr_pubkey_allows_tcpfwd() 仅在密钥带有 no-port-forwarding 时返回 0:

int svr_pubkey_allows_tcpfwd() {
    if (ses.authstate.pubkey_options 
        && ses.authstate.pubkey_options->no_port_forwarding_flag) {
        return 0;
    }
    return 1;
}

按目标检查位于同一文件的 svr_pubkey_allows_local_tcpfwd() 和 svr_pubkey_allows_remote_tcpfwd()。src/svr-tcpfwd.c 在第 202 和 99 行调用它们。两个流转发处理程序没有调用。

在 src/svr-streamfwd.c 中,本地处理程序 newstreamlocal() 在第 294 行检查 svr_opts.nolocaltcp 和 svr_pubkey_allows_tcpfwd()。远程处理程序 svr_remotestreamlocalreq() 在第 219 行检查 svr_opts.noremotefwd 和同一函数。搜索代码树可发现,这两个按目标函数只被 src/svr-tcpfwd.c 引用。

默认构建在 src/default_options.h 第 76 和 77 行启用两个流转发选项。通道在 src/svr-session.c 中注册。

不完整的修复在历史中可见。提交 796a89ef(2024-04-03)“Apply tcp forwarding restrictions to unix sockets too” 为 newstreamlocal() 添加了粗粒度检查并更新了手册。它没有添加标题所宣称的按目标检查。作者在 src/svr-streamfwd.c 第 213 和 214 行指出,如果为 streamlocal 增加 permitlisten 等价项,检查可以放宽;但该等价项并不存在。

如何被利用?

  1. 攻击者使用管理员通过 permitopen="host:port" 限制到一个 TCP 目标的密钥进行认证。
  2. 攻击者打开一个指向 Unix 套接字路径的 direct-streamlocal@openssh.com 通道,而不是 TCP 目标。
  3. Dropbear 的流转发处理程序检查 no-port-forwarding 标志和服务器范围的转发开关。两者都通过,因为密钥没有 no-port-forwarding。
  4. 处理程序从不查询 permitopen 列表,因此连接到请求的套接字。
  5. 攻击者使用该套接字的协议。在 /var/run/docker.sock 上,Docker API 可以启动一个挂载主机文件系统的容器,这等同于主机 root。

研究者在由固定源码构建的本地环境中演示了绕过。带有 permitopen="127.0.0.1:1" 的密钥在请求 127.0.0.1:22 时被拒绝,但同一密钥到达了 /tmp/target.sock。随后同一密钥打开 /var/run/docker.sock,并从真实守护进程收到 HTTP/1.1 200 OK, Api-Version 1.56。

远程方向同理。带有 permitlisten 的密钥可以让服务器监听任意可写的 Unix 路径,并遮蔽服务套接字。

攻击如何展开?

受限密钥通过粗粒度转发检查,请求 Unix 套接字而不是 TCP 目标,并到达管理员从未允许的套接字。

flowchart LR A["攻击者持有指向一个 TCP 主机的
permitopen 密钥"] --> B["使用该密钥
连接 Dropbear"] B --> C["打开指向 docker.sock 的
direct-streamlocal 通道"] C --> D["处理程序只检查
no-port-forwarding"] D --> E["从不查询
permitopen 列表"] E --> F["Dropbear 连接到
root 拥有的套接字"] F --> G["Docker API 运行挂载主机
文件系统的容器"]

攻击者能做什么?

即使密钥仅限一个 TCP 目标,攻击者也能到达账户可打开的 Unix 套接字。当账户能到达 Docker 套接字时,这等同于主机 root。

影响取决于账户的操作系统身份能触及的套接字:

  • /var/run/docker.sock 让攻击者以 root 运行挂载主机文件系统的容器。研究者称这等同于主机 root。
  • /run/mysqld/mysqld.sock 和 /run/postgresql/.s.PGSQL.5432 等数据库套接字将数据库暴露给密钥持有者。
  • 代理和服务套接字暴露这些服务接受的内容。
  • 在 permitlisten 方向,攻击者可以让服务器监听任意可写路径并遮蔽服务套接字。

这些条件是影响的一部分:攻击者需要有效的受限密钥,账户必须能打开目标套接字,构建必须保持流转发启用。研究者将 Docker 案例评为 CVSS v3.1 9.9,向量 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H,当只能到达账户自己的套接字时约为 7。

这不是未认证缺陷。攻击者持有管理员签发的密钥,而管理员限制该密钥正是为了限制它能做的事情。

为什么修复有效?

目前没有上游修复。关闭绕过的更改会将 TCP 处理程序已有的按目标列表遍历应用到两个流转发处理程序。

缺少的检查在两个处理程序中都能看到。src/svr-streamfwd.c 第 294 行的本地处理程序目前是:

if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {

完整检查还会为请求的套接字路径调用基于路径的 svr_pubkey_allows_local_tcpfwd() 等价项。当密钥带有不包含该路径的目标列表时,它会拒绝通道。第 219 行的远程处理程序需要对 permitlisten 做同样更改。

研究者的建议是,在存在基于路径的选项之前,直接拒绝任何带有按目标限制的密钥的 streamlocal 通道。这是保守的修复,也容易推理:指定了目标的密钥不会获得 Unix 套接字。

no-port-forwarding 缓解措施有效,因为它设置了现有粗粒度检查读取的标志。构建和 -j -k 缓解措施有效,因为它们设置了处理程序读取的服务器范围开关。它们都不是对缺失列表遍历的代码修复。

如何检查是否已遭入侵?

没有报告利用,也没有公开入侵指标。检查针对条件和套接字使用,而不是已知载荷。

  • 列出每个带有 permitopen 或 permitlisten 的密钥及其所属账户。
  • 检查这些账户是否在 docker 组中,或能否打开数据库套接字。
  • 检查 Docker 守护进程审计日志中来自意外本地进程或用户的 API 调用,尤其是带主机绑定的容器创建。
  • 检查数据库日志中来自通常不连接的操作用户的本地套接字连接。
  • 查找团队中没有人创建的容器、镜像或绑定挂载。

Dropbear 的默认日志很少,分析也没有公布日志签名。失败的尝试可能不留痕迹,成功的尝试会在套接字所属的服务中留下影响。

时间线

  • 2024-04-03:提交 796a89ef 将粗粒度 TCP 转发限制应用到 Unix 套接字,但没有应用按目标检查。
  • 2025-12-09:提交 00cfa132 阻止强制命令密钥的 Unix 流转发,这是同一路径上的另一项限制。
  • 2026-07-23:Dropbear 发布 2026.94。
  • 2026-11-11:研究者测试 Git HEAD 99baf182,绕过存在。
  • 2026-11-13:研究者在 oss-security 邮件列表公布分析和实时证明。

从不完整修复到公开
图 1:粗粒度限制于 2024 年 4 月加入,按目标的那一半仍然缺失。绕过于 2026 年 11 月 13 日公开。来源:Dropbear Git 历史和 oss-security 公开,2026 年 11 月 14 日检查

常见问题

这个缺陷有 CVE 吗?

没有。研究者于 2026 年 11 月 13 日在 oss-security 邮件列表发布分析,截至 11 月 14 日没有 CVE 记录。Dropbear 项目没有发布公告。

permitopen 能保护 Unix 套接字吗?

不能。permitopen 和 permitlisten 只在 TCP 转发路径上执行。Unix 套接字处理程序检查 no-port-forwarding 标志和服务器范围转发开关,不检查目标列表。

这是远程未认证漏洞吗?

不是。攻击者需要管理员用 permitopen 或 permitlisten 限制的有效密钥。严重程度取决于该密钥背后的账户能到达什么。

哪些版本受影响?

截至 2026.94 的所有 Dropbear 版本,以及截至 99baf182(2026-11-11)的 Git HEAD。截至 2026 年 11 月 14 日没有修复版本。

no-port-forwarding 能阻止绕过吗?

能。no-port-forwarding 设置 svr_pubkey_allows_tcpfwd() 读取的标志,因此两个流转发处理程序都会拒绝通道。它还会阻止该密钥的所有 TCP 转发,包括被允许的目标。

如果账户不在 docker 组中呢?

攻击者仍可到达账户能打开的任何套接字,例如数据库或服务套接字。影响低于主机 root,但仍是密钥限制本应阻止的访问。

参考文献

  • knell,“Dropbear: the restriction names an address”,oss-security,2026 年 11 月 13 日,分析和实时证明:https://www.openwall.com/lists/oss-security/2026/11/13/4(2026 年 11 月 14 日检查)
  • 研究者的论文“Not an address”,完整分析和测试环境:https://archive.org/details/knell-not-an-address(2026 年 11 月 14 日检查)
  • Dropbear 99baf182 源码,src/svr-streamfwd.c,两个流转发处理程序:https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/svr-streamfwd.c(2026 年 11 月 14 日检查)
  • Dropbear 99baf182 源码,src/svr-authpubkeyoptions.c,粗粒度和按目标检查:https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/svr-authpubkeyoptions.c(2026 年 11 月 14 日检查)
  • Dropbear 99baf182 源码,src/default_options.h 第 76 和 77 行,流转发默认值:https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/default_options.h(2026 年 11 月 14 日检查)
  • 提交 796a89ef,“Apply tcp forwarding restrictions to unix sockets too”,2024 年 4 月 3 日:https://github.com/mkj/dropbear/commit/796a89efd21f(2026 年 11 月 14 日检查)
  • 提交 00cfa132,“Disallow unix stream forwarding for forced command”,2025 年 12 月 9 日:https://github.com/mkj/dropbear/commit/00cfa132fcbf(2026 年 11 月 14 日检查)
  • Dropbear 项目页面,嵌入式和路由器用途以及 2026.94 版本:https://matt.ucc.asn.au/dropbear/dropbear.html(2026 年 11 月 14 日检查)
  • CISA Known Exploited Vulnerabilities 目录,2026 年 11 月 14 日检查 Dropbear 条目(无):https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json(2026 年 11 月 14 日检查)