Posted by James Forshaw, Project Zero
And we’re back again for anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r blog in my series on Windows Exploitation tricks. This time I’ll detail how I was able to exploit Issue 1550 which results in an arbitrary object directory being created by using a useful behavior of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CSRSS privileged process. Once again by detailing how I’d exploit a particular vulnerability I hope that readers get a better understanding of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complexity of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows operating system as well as giving Microsoft information on non-memory corruption exploitation techniques so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y can mitigate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in some way.
Quick Overview of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Vulnerability
Object Manager directories are unrelated to normal file directories. The directories are created and manipulated using a separate set of system calls such as NtCreateDirectoryObject racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than NtCreateFile. Even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re not file directories cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y’re vulnerable to many of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same classes of issues as you’d find on a file system including privileged creation and symbolic link planting attacks.
Issue 1550 is a vulnerability that allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 creation of a directory inside a user-controllable location while running as SYSTEM. The root of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug is in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 creation of Desktop Bridge applications. The AppInfo service, which is responsible for creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new application, calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 undocumented API CreateAppContainerToken to do some internal housekeeping. Unfortunately this API creates object directories under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s AppContainerNamedObjects object directory to support redirecting BaseNamedObjects and RPC endpoints by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OS.
As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API is called without impersonating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user (it’s normally called in CreateProcess where it typically isn’t as big an issue) cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object directories are created with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 identity of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service, which is SYSTEM. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user can write arbitrary objects to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir AppContainerNamedObjects directory cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could drop an object manager symbolic link and redirect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory creation to almost anywhere in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object manager namespace. As a bonus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory is created with an explicit security descriptor which allows cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user full access, this will become very important for exploitation.
One difficulty in exploiting this vulnerability is that if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object directory isn’t created under AppContainerNamedObjects because we’ve redirected its location cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 underlying NtCreateLowBoxToken system call which performs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token creation and captures a handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory as part of its operation will fail. The directory will be created but almost immediately deleted again. This behavior is actually due to an earlier issue I reported which changes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system call’s behavior. This is still exploitable by opening a handle to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 created directory before it’s deleted, and in practice it seems winning this race is reliable as long as your system has multiple processors (which is basically any modern system). With an open handle cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory is kept alive as long as needed for exploitation.
This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original PoC I sent to MSRC stopped, all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PoC did was create an arbitrary object directory. You can find this PoC attached to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial bug report in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue tracker. Now let’s get into how we might exploit this vulnerability to go from a normal user account to a privileged SYSTEM account.
Exploitation
The main problem for exploitation is finding a location in which we can create an object directory which can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be leveraged to elevate our privileges. This turns out to be harder than you might think. While almost all Windows applications use object directories under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hood, such as BaseNamedObjects, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 applications typically interact with existing directories which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability can’t be used to modify.
An object directory that would be interesting to abuse is KnownDlls (which I mentioned briefly in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog in this series). This object directory contains a list of named image section objects, of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 form NAME.DLL. When an application calls LoadLibrary on a DLL inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SYSTEM32 directory cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loader first checks if an existing image section is present inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls object directory, if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 section exists cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n that will be loaded instead of creating a new section object.
KnownDlls is restricted to only being writable by administrators (not strictly true as we’ll see) because if you could drop an arbitrary section object inside this directory you could force a system service to load cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 named DLL, for example using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Diagnostics Hub service I described in my last blog post, and it would map cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 section, not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file on disk. However cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability can’t be used to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls object directory ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than adding a new child directory which doesn’t help in exploitation. Maybe we can target KnownDlls indirectly by abusing ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r functionality which our vulnerability can be used with?
Whenever I do research into particular areas of a product I will always note down interesting or unexpected behavior. One example of interesting behavior I discovered when I was researching Windows symbolic links. The Win32 APIs support a function called DefineDosDevice, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 purpose of this API is to allow a user to define a new DOS drive letter. The API takes three parameters, a set of flags, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 drive prefix (e.g. X:) to create and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device to map that drive to. The API’s primary use is in things like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CMD SUBST command.
On modern versions of Windows this API creates an object manager symbolic link inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s own DOS device object directory, a location which can be written to by a normal low privileged user account. However if you look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of DefineDosDevice you’ll find that it’s not implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller’s process. Instead cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation calls an RPC method inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current session’s CSRSS service, specifically cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method BaseSrvDefineDosDevice inside BASESRV.DLL. The main reason for calling into a privileged service is it allows a user to create a permanent symbolic link which doesn’t get deleted when all handles to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link object are closed. Normally to create a permanent named kernel object you need cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SeCreatePermanentPrivilege privilege, however a normal user does not have that privilege. On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand CSRSS does, so by calling into that service we can create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 permanent symbolic link.
The ability to create a permanent symbolic link is certainly interesting, but if we were limited to only creating drive letters in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s DOS devices directory it wouldn’t be especially useful. I also noticed that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation never verified that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lpDeviceName parameter is a drive letter. For example you could specify a name of “GLOBALROOT\RPC Control\ABC” and it would actually create a symbolic link outside of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s DosDevices directory, specifically in this case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path “\RPC Control\ABC”. This is because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation prepends cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DosDevice prefix “\??” to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device name and passes it to NtCreateSymbolicLink. The kernel would follow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full path, finding GLOBALROOT which is a special symbolic link to return to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 root and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n follow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path to creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 arbitrary object. It was unclear if this was intentional behavior so I looked in more depth at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation in CSRSS, which is shown in abbreviated form below.
NTSTATUS BaseSrvDefineDosDevice(DWORD dwFlags,
LPCWSTR lpDeviceName,
LPCWSTR lpTargetPath) {
WCHAR device_name[];
snwprintf_s(device_name, L"\\??\\%s", lpDeviceName);
UNICODE_STRING device_name_ustr;
OBJECT_ATTRIBUTES objattr;
RtlInitUnicodeString(&device_name_ustr, device_name);
InitializeObjectAttributes(&objattr, &device_name_ustr,
LPCWSTR lpDeviceName,
LPCWSTR lpTargetPath) {
WCHAR device_name[];
snwprintf_s(device_name, L"\\??\\%s", lpDeviceName);
UNICODE_STRING device_name_ustr;
OBJECT_ATTRIBUTES objattr;
RtlInitUnicodeString(&device_name_ustr, device_name);
InitializeObjectAttributes(&objattr, &device_name_ustr,
OBJ_CASE_INSENSITIVE);
BOOLEAN enable_impersonation = TRUE;
CsrImpersonateClient();
HANDLE handle;
NTSTATUS status = NtOpenSymbolicLinkObject(&handle, DELETE, &objattr);①
CsrRevertToSelf();
if (NT_SUCCESS(status)) {
BOOLEAN is_global = FALSE;
// Check if we opened a global symbolic link.
IsGlobalSymbolicLink(handle, &is_global); ②
if (is_global) {
enable_impersonation = FALSE; ③
snwprintf_s(device_name, L"\\GLOBAL??\\%s", lpDeviceName);
RtlInitUnicodeString(&device_name_ustr, device_name);
}
// Delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing symbolic link.
NtMakeTemporaryObject(handle);
NtClose(handle);
}
if (enable_impersonation) { ④
CsrRevertToSelf();
}
// Create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link.
UNICODE_STRING target_name_ustr;
RtlInitUnicodeString(&target_name_ustr, lpTargetPath);
status = NtCreateSymbolicLinkObject(&handle, MAXIMUM_ALLOWED,
BOOLEAN enable_impersonation = TRUE;
CsrImpersonateClient();
HANDLE handle;
NTSTATUS status = NtOpenSymbolicLinkObject(&handle, DELETE, &objattr);①
CsrRevertToSelf();
if (NT_SUCCESS(status)) {
BOOLEAN is_global = FALSE;
// Check if we opened a global symbolic link.
IsGlobalSymbolicLink(handle, &is_global); ②
if (is_global) {
enable_impersonation = FALSE; ③
snwprintf_s(device_name, L"\\GLOBAL??\\%s", lpDeviceName);
RtlInitUnicodeString(&device_name_ustr, device_name);
}
// Delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing symbolic link.
NtMakeTemporaryObject(handle);
NtClose(handle);
}
if (enable_impersonation) { ④
CsrRevertToSelf();
}
// Create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link.
UNICODE_STRING target_name_ustr;
RtlInitUnicodeString(&target_name_ustr, lpTargetPath);
status = NtCreateSymbolicLinkObject(&handle, MAXIMUM_ALLOWED,
objattr, target_name_ustr); ⑤
if (enable_impersonation) { ⑥
CsrRevertToSelf();
}
if (NT_SUCCESS(status)) {
status = NtMakePermanentObject(handle); ⑦
NtClose(handle);
}
return status;
}
if (enable_impersonation) { ⑥
CsrRevertToSelf();
}
if (NT_SUCCESS(status)) {
status = NtMakePermanentObject(handle); ⑦
NtClose(handle);
}
return status;
}
We can see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first thing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code does is build cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device name path cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n try and open cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link object for DELETE access ①. This is because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API supports redefining an existing symbolic link, so it must first try to delete cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old link. If we follow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 default path where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link doesn’t exist we’ll see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code impersonates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 low privileged user in this case) ④ cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n creates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link object ⑤, reverts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation ⑥ and makes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object permanent ⑦ before returning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 status of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 operation. Nothing too surprising, we can understand why we can create arbitrary symbolic links because all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code does is prefix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 passed device name with “\??”. As cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code impersonates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller when doing any significant operation we can only create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link in a location that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user could already write to.
What’s more interesting is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 middle conditional, where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target symbolic link is opened for DELETE access, which is needed to call NtMakeTemporaryObject. The opened handle is passed to anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r function ②, IsGlobalSymbolicLink, and based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result of that function a flag disabling impersonation is set and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device name is recreated again with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global DOS device location \GLOBAL?? as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prefix ③. What is IsGlobalSymbolicLink doing? Again we can just RE cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function and check.
void IsGlobalSymbolicLink(HANDLE handle, BOOLEAN* is_global) {
BYTE buffer[0x1000];
NtQueryObject(handle, ObjectNameInformation, buffer, sizeof(buffer));
UNICODE_STRING prefix;
RtlInitUnicodeString(&prefix, L"\\GLOBAL??\\");
// Check if object name starts with \GLOBAL??
*is_global = RtlPrefixUnicodeString(&prefix, (PUNICODE_STRING)buffer);
}
BYTE buffer[0x1000];
NtQueryObject(handle, ObjectNameInformation, buffer, sizeof(buffer));
UNICODE_STRING prefix;
RtlInitUnicodeString(&prefix, L"\\GLOBAL??\\");
// Check if object name starts with \GLOBAL??
*is_global = RtlPrefixUnicodeString(&prefix, (PUNICODE_STRING)buffer);
}
The code checks if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 opened object’s name starts with \GLOBAL??\. If so it sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 is_global flag to TRUE. This results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flag enabling impersonation being cleared and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device name being rewritten. What this means is that if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller has DELETE access to a symbolic link inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global DOS device directory cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link will be recreated without any impersonation, which means it will be created as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SYSTEM user. This in itself doesn’t sound especially interesting as by default only an administrator could open one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global symbolic links for DELETE access. However, what if we could create a child directory underneath cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global DOS device directory which could be written to by a low privileged user? Any symbolic link in that directory could be opened for DELETE access as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 low privileged user could specify any access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y liked, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code would flag cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link as being global, when in fact that’s not really cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case, disable impersonation and recreate it as SYSTEM. And guess what, we have a vulnerability which would allow us to create an arbitrary object directory under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global DOS device directory.
Again this might not be very exploitable if it wasn’t for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rewriting of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path. We can abuse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fact that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path “\??\ABC” isn’t cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as “\GLOBAL??\ABC” to construct a mechanism to create an arbitrary symbolic link anywhere in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object manager namespace as SYSTEM. How does this help us? If you write a symbolic link to KnownDlls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it will be followed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel when opening a section requested by DLL loader. Therefore even though we can’t directly create a new section object inside KnownDlls, we can create a symbolic link which points outside that directory to a place that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 low-privileged user can create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 section object. We can now abuse cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hijack to load an arbitrary DLL into memory inside a privileged process and privilege elevation is achieved.
Pulling this all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r we can exploit our vulnerability using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following steps:
- Use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability to create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 directory “\GLOBAL??\KnownDlls”
- Create a symbolic link inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new directory with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DLL to hijack, such as TAPI32.DLL. The target of this link doesn’t matter.
- Inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s DOS device directory create a new symbolic link called “GLOBALROOT” pointing to “\GLOBAL??”. This will override cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real GLOBALROOT symbolic link object when a caller accesses it via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user’s DOS device directory.
- Call DefineDosDevice specifying a device name of “GLOBALROOT\KnownDlls\TAPI32.DLL” and a target path of a location that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user can create section objects inside. This will result in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following operations:
- CSRSS opens cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link “\??\GLOBALROOT\KnownDlls\TAPI32.DLL” which results in opening “\GLOBAL??\KnownDlls\TAPI32.DLL”. As this is controlled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open succeeds, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link is considered global which disables impersonation.
- CSRSS rewrites cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path to “\GLOBAL??\GLOBALROOT\KnownDlls\TAPI32.DLL” cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n calls NtCreateSymbolicLinkObject without impersonation. This results in following cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real GLOBALROOT link, which results in creating cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbolic link “\KnownDlls\TAPI32.DLL” with an arbitrary target path.
- Create cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 image section object at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target location for an arbitrary DLL, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n force it to be loaded into a privileged service such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Diagnostics Hub by getting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 service to call LoadLibrary with a path to TAPI32.DLL.
- Privilege escalation is achieved.
Abusing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DefineDosDevice API actually has a second use, it’s an Administrator to Protected Process Light (PPL) bypass. PPL processes still use KnownDlls, so if you can add a new entry you can inject code into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protected process. To prevent that attack vector Windows marks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls directory with a Process Trust Label which blocks all but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest level level PPL process from writing to it, as shown below.
How does our exploit work cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n? CSRSS actually runs as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highest level PPL so is allowed to write to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KnownDlls directory. Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 impersonation is dropped cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 identity of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process is used which will allow full access.
If you want to test this exploit I’ve attached cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new PoC to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue tracker here.
Wrapping Up
You might wonder at this point if I reported cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 behavior of DefineDosDevice to MSRC? I didn’t, mainly because it’s not in itself a vulnerability. Even in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case of Administrator to PPL, MSRC do not consider that a serviceable security boundary (example). Of course cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Windows developers might choose to try and change this behavior in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future, assuming it doesn’t cause a major regression in compatibility. This function has been around since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 early days of Windows and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current behavior since at least Windows XP so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s probably something which relies on it. By describing this exploit in detail, I want to give MS as much information as necessary to address cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitation technique in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 future.
I did report cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability to MSRC and it was fixed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 June 2018 patches. How did Microsoft fix cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability? The developers added a new API, CreateAppContainerTokenForUser which impersonates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 token during creation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new AppContainer token. By impersonating during token creation cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code ensures that all objects are created only with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privileges of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user. As it’s a new API existing code would have to be changed to use it, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365refore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a chance you could still find code which uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 old CreateAppContainerToken in a vulnerable pattern.
Exploiting vulnerabilities on any platform sometimes requires pretty in-depth knowledge about how different components interact. In this case while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 initial vulnerability was clearly a security issue, it’s not clear how you could proceed to full exploitation. It’s always worth keeping a log of interesting behavior which you encounter during reverse engineering as even if something is not a security bug itself, it might be useful to exploit anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r vulnerability.
No comments:
Post a Comment