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.
Vendor | Microsoft |
Security Impact | Elevation of Privilege |
CVE ID | CVE-2022-24547 |
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 |
Product:
ISO Download:
Version:
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:
CastSrv.exe
under the context of another logged-in user by initializing the program with that user’s session.IcastServerControl::GetEnableControl
function creates the \AppData\Local\__Shared\PlayToReceiver
directory without verifying if it’s a symbolic link.CastSrv.exe
under another user’s session and use the IcastServerControl::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.
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.
user01
and user02
.user02
, then log in as user01
to have both sessions running simultaneously.user01
.user02
at C:\\Users\\user02\\test
.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.
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.
\AppData\Local\__Shared\PlayToReceiver
.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!
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.