作者:houjingyi
去年我分享了我发现的CVE-2020-3535:Cisco Webex Teams windows客户端dll劫持漏洞。当时我文章中说:
考虑另外一种exe和加载的dll不在同一个路径的情况,如果C:\abc\def\poc.exe想要加载C:\abc\lib\test.dll,可不可以写成LoadLibraryW(L”..\lib\test.dll”)呢?这也是会导致漏洞的,同样windows会把”..\lib\test.dll”直接当成”C:\lib\test.dll”。我在另外某个知名厂商的产品中发现了这样的代码,我已经报告给了厂商,还在等厂商给我答复。我可能会在90天的期限或者厂商发布安全公告之后补充更多细节。
实际上我发现了两个产品中都有这样的代码,分别是IBM(R) Db2(R)和VMware ThinApp。具体细节我发到full disclosure里面了:
VMware ThinApp DLL hijacking vulnerability
IBM(R) Db2(R) Windows client DLL Hijacking Vulnerability(0day)
我们看看LoadLibrary的文档:
微软说你们可不能直接给LoadLibrary一个相对路径啊,你们应该先用GetFullPathName获取dll的绝对路径,再把绝对路径作为参数调用LoadLibrary。那么当我们给LoadLibrary提供一个相对路径的时候到底发生了什么呢?以VMware ThinApp中的LoadLibraryExW(L"\\DummyTLS\\dummyTLS.dll", 0, 0)
为例我们来简单分析一下Windows的ntdll.dll是怎么处理dll路径的。这里的流程是:KernelBase!LoadLibraryExW->ntdll!LdrpLoadDll->ntdll!LdrpPreprocessDllName,我们来看LdrpPreprocessDllName。
代码的意思是调用RtlDetermineDosPathNameType_Ustr判断路径的类型,这里返回了4也就是RtlPathTypeRooted,后面调用LdrpGetFullPath就得到C:\DummyTLS\dummyTLS.dll这样的一个路径了。所以这里处理的逻辑就是只要你是一个相对路径,Windows就认为你是一个相对于磁盘根目录(一般也就是C盘)的路径。可以参考ReactOS的代码。
非常糟糕的是Windows中非管理员用户是可以在C盘根目录下创建文件夹并向其中写入文件的,所以就导致了这种本地提权的场景。
小结
1.确实不能理解Windows系统里面为什么有这么奇怪的设计,可能很多Windows开发也不知道。
2.还是像我之前文章里面说的,如果dll加载失败的时候开发者认真调试检查就能避免这样的漏洞(也正因为如此这种dll劫持的场景一般不会发生)。
3.Windows中非管理员用户是可以在C盘根目录下创建文件夹并向其中写入文件的,这给了很多这样本地提权场景利用的机会。
4.使用绝对路径往往能更安全一点,后面有机会我也可能继续分享一些我发现的相对路径导致的各种各样的本地提权或者RCE的场景。