TL;dr
Vulnerabilities can often be found in places we don’t expect, and CVE-2022-24547
in CastSrv.exe
is one of the examples. CVE-2022-24547 is a privilege escalation vulnerability in CastSrv.exe, allowing attackers to bypass security and gain elevated privileges. We’ll break down how the bug works, its exploitation, and how to protect against it.
Summary
Vendor | Microsoft |
Security Impact | Elevation of Privilege |
CVE ID | CVE-2022-24547 |
CVSS3.1 Scoring System:
Base Score: 7.8
Vector String: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector (AV) | Local |
Attack Complexity (AC) | Low |
Privileges Required (PR) | Low |
User Interaction (UI) | None |
Scope (S) | Unchanged |
Confidentiality (C) | High |
Integrity (I) | High |
Availability (A) | High |
Affected Software
Product:
- Microsoft Windows 10.0.18363.592 64-bits (2020-01-14)
ISO Download:
Version:
- Windows 10 10.0.18363.592 64-bits (2020-01-14)
Description of Vulnerability
The vulnerability exists in the IcastServerControl::GetEnableControl
function of the CastSrv.exe
program, allowing attackers to create arbitrary folders within another user’s account on the system.
Key factors contributing to this bug:
- Session Hijacking: Attackers can run
CastSrv.exe
under the context of another logged-in user by initializing the program with that user’s session. - Unchecked Folder Creation: The
IcastServerControl::GetEnableControl
function creates the\AppData\Local\__Shared\PlayToReceiver
directory without verifying if it’s a symbolic link. - Improper Permissions: The created directory has full DACL permissions, allowing any user to access and modify it (see DACL Access Control).
Thus, the vulnerability allows an attacker to run
CastSrv.exe
under another user’s session and use theIcastServerControl::GetEnableControl
function to create arbitrary folders in that user’s directory.
This interface is registered under:
clsid: f8842f8e-dafe-4b37-9d38-4e0714a61149
uuid: 7733f245-f909-4be2-918f-bddecbcd07cc
clsid name: CastServerInteractiveUser
interfaces name: ICastServerControl
Vulnerable method name: ICastServerControl::GetEnableControl
The registered interface (ICastServerControl
) can be activated within any interactive user session on the machine through the utilization of a “session moniker.” This capability presents a potential vector for cross-session privilege escalation, as both the interfaces and their associated methods may be exploited. For further details, please refer to the following link: COM Cross-Session Activation.
The underlying call of functions in IcastServerControl::GetEnableControl
that create \\PlayToReceiver
with full DACL permission, and drop image files are simplified in below Control Flow Graph. I will describe more details on this later in Exploitation.
Exploitation
Step 1: We need to initialize CastSrv.exe
with the target user’s session ID.
In the image above, the string session:2!new:f8842f8e-dafe-4b37-9d38-4e0714a61149
indicates that the number 2
represents the target user’s session ID, while f8842f8e-dafe-4b37-9d38-4e0714a61149
is the GUID for the CastSrv.exe
service. You will need to replace 2
with the session ID of the targeted user.
Step 2: We need to trigger the CCastServerControl::GetEnableControl
function in the ICastServerControl
interface.
In the above picture, you could see the vtable of ICastServerControl
interface
CCastServerControl::StartCastServer(void)
CCastServerControl::StopCastServer(void)
CCastServerControl::Advise(ICastAppLaunchCallback *)
CCastServerControl::Unadvise(ICastAppLaunchCallback *)
CCastServerControl::GetEnableControl(int *)
CCastServerControl::SetEnableControl(int)
CCastServerControl::PutSettings(IUnknown *)
One method from the ICastServerControl
interface, CCastServerControl::GetEnableControl
, when called, will create a folder under \AppData\Local\__SHARED\PlayToReceiver
.
When invoked, CCastServerControl::GetEnableControl
initiates a call to CServerHolder::GetDMRServer
and subsequently to IPlayToReceiverAppRegistrar+72
, which corresponds to CPlayToReceiverAppRegistrar::GetEnableControl
via its virtual table in DMRServer.dll
.
Within DMRServer.dll
, these calls trigger the initialization of the CSharedDMR
and CPlayToReceiverInternal
classes. The initialization of the CSharedDMR
class results in the creation of several image files, which will be discussed in further detail later. Meanwhile, the CPlayToReceiverInternal::RuntimeClassInitialize
method creates the PlayToReceiver
folder within the %AppData%
directory. Notably, this process does not include a check for symbolic links.
Since we know that the UUID of ICastServerControl
is 7733f245-f909-4be2-918f-bddecbcd07cc
, we can recreate it as follows.
// 7733f245-f909-4be2-918f-bddecbcd07cc is UUID of ICastServerControl
class __declspec(uuid("7733f245-f909-4be2-918f-bddecbcd07cc")) ICastServerControl : public IUnknown {
public:
virtual HRESULT __stdcall StartCastServer(void);
virtual HRESULT __stdcall StopCastServer(void);
virtual HRESULT __stdcall Advise(void* p0);
virtual HRESULT __stdcall Unadvise(void* p0);
virtual HRESULT __stdcall GetEnableControl(int64_t* p0);
virtual HRESULT __stdcall SetEnableControl(int64_t p0);
virtual HRESULT __stdcall PutSettings(IUnknown* p0);
};
Since we are already running CastSrv.exe
for the user02
session 2
from Step 1, we will now call BindToObject
to obtain a pointer to the ICastServerControl
interface and then trigger the ICastServerControl->GetEnableControl
method from there.
Note that this is the first time we are calling the ICastServerControl->GetEnableControl
method. However, since CastSrv.exe
is now running under another user context, we have already created the folder PlayToReceiver
in the \user02\AppData\Local\__SHARED\PlayToReceiver
directory.
Step 3: We create a symbolic link from \user02\AppData\Local\__SHARED\PlayToReceiver
to another path, C:\\Users\\user02\\arbitrary_folder
, by calling NtCreateSymbolicLinkObject
.
Step 4: We then need to call ICastServerControl->GetEnableControl
again, which will follow the symbolic link and create the arbitrary folder at the specified location.
Before proceeding, we need to delete some image files in \user02\AppData\Local\__SHARED\
that were created when calling ICastServerControl->GetEnableControl
. These image files are icon files that CastSrv.exe
extracts from C:\Windows\SystemResources\DDORes.dll.mun
. Since these files are located in the SystemResources
folder, modifying them requires Administrator permissions, which we do not have.
The creation of these image files is initiated during the initialization of the CSharedDMR
class. Specifically, when CSharedDMR::RuntimeClassInitialize
is invoked, it extracts icons from DDORes.dll.mun
and subsequently writes them to the aforementioned image files.
Exploit Reproduction (Optional)
- Create a Windows 10 environment with two users:
user01
anduser02
. - Log in as
user02
, then log in asuser01
to have both sessions running simultaneously. - Run the proof of concept (PoC) on
user01
. - Check for the arbitrary folder in
user02
atC:\\Users\\user02\\test
.
Exploit Conditions
An attacker must be on the same system as the targeted user, and the targeted user must have an active session while the attacker carries out the exploit.
Detection Guidance
The exploit is facilitated by leveraging the symbolic link associated with the folder \AppData\Local\__Shared\PlayToReceiver
. Consequently, users should implement measures to either prohibit the creation of this folder or validate whether it is a symbolic link.
Suggested Mitigations
- Implement restrictions to prevent the creation of the folder
\AppData\Local\__Shared\PlayToReceiver
.
Acknowledgements
I would also like to thank my co-worker Chen Le Qi for his valuable guidance throughout the research – I’ve really learnt a lot!
Conclusion
Throughout this research, I’ve learned a lot about how privilege escalation vulnerabilities can be exploited in subtle ways, even though I never successfully exploited CVE-2022-24547. The process of dissecting the vulnerability, understanding the flow, and experimenting with different methods has given me valuable insights into security research and exploit development. While the exploit didn’t come to fruition, the experience has definitely expanded my technical knowledge, and I hope this post provides helpful information for others working on similar challenges.