new dll hijacking scenario found by accident

Speaking of dll hijacking, many people may think it is very useless.

Some times ago, I accidentally discovered vulnerabilities in dll loading mechanism in cisco webex teams/IBM Db2/VMware ThinApp that can lead to LPE, and as far as I know, no one has ever mentioned this kind of dll hijacking scenario before.

Vendor advisories:

VMware ThinApp update addresses a DLL hijacking vulnerability
Cisco Webex Teams Client for Windows DLL Hijacking Vulnerability
Security Bulletin: IBM® Db2® could allow a local authenticated attacker to execute arbitrary code on the system, caused by DLL search order hijacking vulnerability in Microsoft Windows client. (CVE-2020-4739)

Details I posted to full disclosure mailing list:

VMware ThinApp DLL hijacking vulnerability
IBM(R) Db2(R) Windows client DLL Hijacking Vulnerability(0day)
Cisco Webex Teams Client for Windows DLL Hijacking Vulnerability

I will not repeat the details of these vulnerabilities, I will analyze the dll path processing mechanism in ntdll.dll.

In document microsoft said:

The first directory searched is the directory containing the image file used to create the calling process (for more information, see the CreateProcess function). Doing this allows private dynamic-link library (DLL) files associated with a process to be found without adding the process’s installed directory to the PATH environment variable. If a relative path is specified, the entire relative path is appended to every token in the DLL search path list. To load a module from a relative path without searching any other path, use GetFullPathName to get a nonrelative path and call LoadLibrary with the nonrelative path. For more information on the DLL search order, see Dynamic-Link Library Search Order.

So…What will happen if we provide a relative path to LoadLibrary?

Let us take following code in VMware ThinApp as example:

LoadLibraryExW(L"\\DummyTLS\\dummyTLS.dll", 0, 0);

The process is:KernelBase!LoadLibraryExW->ntdll!LdrpLoadDll->ntdll!LdrpPreprocessDllName:

So RtlDetermineDosPathNameType_Ustr will return 4(RtlPathTypeRooted) and LdrpGetFulPath will return C:\DummyTLS\dummyTLS.dll. You can refer to code in ReactOS:

So now we know Windows will treat relative path in LoadLibrary/AddDllDirectory…as the path rooted relative to the current disk designator, which is usually C:\. Since non-admin user can create directory under C:\ and write file to it, this cause LPE.

I also reported my findings to MSRC, but MSRC said this is the default behavior. I am not surprised, if the default behavior is to let developers write vulnerable code, that’s fine.

I am sharing my discovery because I haven’t seen anyone mention these and similar vulnerabilities exist in other products absolutely. At the same time, I want to remind developers should make sure that all your dlls are loaded correctly.

Some thoughts:

1.I don’t understand why Microsoft handle path this way.

2.This kind of bug would not have appeared if developers had been more careful.

3.Using relative path is dangerous and I will share some RCE/LPE vulnerabilities I found because of relative path.

4.Non-admin user can create directory under C:\ and write file to it, this is not right and it caused many LPE vulnerabilities.