23 年 7 月,Qualys Security Advisory 的安全研究员曝光了一个在 OpenSSH 中潜伏了 13 年的漏洞。
事实上,尽管 Project Zero 的研究员 Jann Horn 早已在 2016 年指出了这个问题,并且 OpenSSH 的开发者也及时进行了限制与修复,但这个漏洞的故事远没有结束。
这个漏洞为何能在 7 年后再度成为威胁?
这背后又隐藏着哪些巧妙的利用技巧?
以下为本期深蓝洞察年度安全报告的第九篇。
09
2010 年,OpenSSH 为了支持 PKCS#11密钥的添加和删除,引入了这样一个功能:由 server 指定一个动态库,在本地进行加载(dlopen)并获取所需符号,如果找不到则将其卸载(dlclose)。
在 2016 年,研究员 Jann Horn 揭示了这功能中的一个严重的安全漏洞:如果攻击者能在受害者的机器上放置一个带有恶意初始化函数的动态库,就能利用这一功能执行任意代码。这一漏洞被编号为 CVE-2016-10009。
作为应对,OpenSSH 开发者在加载动态库前增加了一个白名单检查,只允许来自 /usr/lib
和 /usr/local/lib
的库被加载。
然而,2023 年 7 月,Qualys Security Advisory 的研究员发现,即使加上了这样的限制,这个漏洞并未被完全消除。
他们发现在 Ubuntu 22.04 系统中,仅通过加载并卸载系统软件包中的库,攻击者也能执行任意代码。这一新的漏洞被编号为 CVE-2023-38408。
接下来,让我们详细看看该研究的发现及利用的思路。
该研究在调研了大量 Ubuntu 系统软件包中的动态库后发现,有一些动态库在加载和卸载后会产生以下四种副作用之一:
有的动态库的栈可执行,会将整个程序的栈变为可执行;
有的动态库被标记为 nodelete
,dlclose 后内存不会释放;
有的动态库加载时会注册一个 SIGSEGV 信号处理器,在卸载时不会被清除;
有的动态库一加载就会立即因内存问题(大概率是空指针解引用)引发 SIGSEGV。
攻击者可利用这些副作用巧妙地构造出如下利用链:
加载使栈可执行的动态库,在栈上存储 shellcode;
加载注册 SIGSEGV 信号处理器的库,卸载后留下悬空指针;
加载 nodelete 的库,替代上一步中被卸载的内容;
加载引发 SIGSEGV 的库,触发 SIGSEGV 并期望新加载的代码能够跳到栈上的 shellcode。
了解到这一问题后,OpenSSH 的开发者立即进行了修补,主要包括默认关闭此功能,需要手动命令行开启,以及在动态库加载前通过静态符号检查 C_GetFunctionList
的存在来决定是否进行 dlopen。
虽然 Qualys Security Advisory 的研究员只在 Ubuntu 上进行了研究,但是实际上 OpenSSH portable 在大部分 Unix 系统以及 Linux 发行版中普遍存在,本地加载共享库这个功能也广泛地存在于各个系统中。
DARKNAVY 发现,在 MacOS 中,也可以直接加载 /usr/lib
和 /usr/local/lib
下的动态库。但是这些动态库是否能够像 Ubuntu 的动态库如此巧妙地构成利用链,还有待进一步的深入研究。
令人惊讶的是,Windows powershell 移植的 SSH 也存在类似的加载功能。
不过,Windows 下不存在 dlopen,改为了使用 LoadLibrary 来进行加载。但是由于移植时的实现不同,每次加载完动态库后,进程会自动重启,微软的开发者 Danny Maertens 认为 Windows 下的 SSH 不受该漏洞的影响。
然而,事情可能并没有像他想的那样美好。
经过 DARKNAVY 研究发现,Windows 下不存在 /usr/lib
和 /usr/local/lib
的默认白名单检查。可以说,CVE-2016-10009 在 Windows 下一直没有被修复。
下图中左边是 Windows 对应的源码,而右边是 OpenSSH 的源码。
不难看出,Windows 的实现是直接删去了白名单的检查。
有趣的是,Windows 在 2021 年末才终于移植了 PKCS#11 密钥的实现。可能他们并不了解这个 5 年前的漏洞,把 patch 当成了一个可有可无的功能,而没有及时进行移植。
更为严重的是,LoadLibrary 可以直接远程加载 SMB 共享的动态库,而 Windows 下没有对这一点进行任何限制。
也就是说,攻击者不需要在受害者机器上放置恶意动态库即可进行攻击。下图是我们的 Demo:
只能加载可信动态库的限制看似天衣无缝,但在巧妙构造的利用链面前却会败下阵来。Windows 移植中每次重启进程的特性会给攻击者的利用造成困难,但是缺失的白名单限制似乎又会带来更大的问题。
如何才算真正修复了一个漏洞?
如何评估同一个漏洞对不同系统的影响?
这个漏洞又一次给我们抛出了两个久存的问题。
也许,只有从攻击者视角出发、结合环境特性来进行对抗性研判研究,才能真正回答好这两个问题。
参 考:
[1] https://www.qualys.com/2023/07/19/cve-2023-38408/rce-openssh-forwarded-ssh-agent.txt
[2] https://bugs.chromium.org/p/project-zero/issues/detail?id=1009
[3] https://github.com/PowerShell/Win32-OpenSSH/issues/2102#issuecomment-1673762659
[4] https://github.com/openbsd/src/commit/9476ce1dd37d3c3218d5640b74c34c65e5f4efe5
[5] https://github.com/openbsd/src/commit/f8f5a6b003981bb824329dc987d101977beda7ca
明日,请继续关注《深蓝洞察 | 2023 年度安全报告》第十篇。