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:

  1. Session Hijacking: Attackers can run CastSrv.exe under the context of another logged-in user by initializing the program with that user’s session.
  2. Unchecked Folder Creation: The IcastServerControl::GetEnableControl function creates the \AppData\Local\__Shared\PlayToReceiver directory without verifying if it’s a symbolic link.
  3. 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 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.

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 and user02.
  • Log in as user02, then log in as user01 to have both sessions running simultaneously.
  • Run the proof of concept (PoC) on user01.
  • Check for the arbitrary folder in user02 at C:\\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.