PrintDemon (CVE-2020-1048) is a vulnerability that uses the Windows Printer Spooler to escalate privileges, bypass Endpoint Detection & Response (EDR), and gain persistence. The Windows Printer Spooler has a long history of vulnerabilities, including a vulnerability (CVE-2010-2729) used by the well-known Malware called Stuxnet in 2010.
A printer must be associated with two attributes: A printer port and a printer driver. Setup the printer port to ‘PORTPROMPT, makes it possible to print to a file. There is no check when using the PowerShell command ‘Add-PrinterPort’ if the user has permission to access the location set as the printer port. So the user is free to set any location for the printer port as a low-privileged user. When you print to the printer, it uses the printer port to print to a file. If the user does not have write permission to the location, the print job gets queued. Once you restart the spooler service, the print job will execute with SYSTEM privileges, and the file will also get dropped with these privileges. Since SYSTEM is a high-privileges account, you can drop a file anywhere on the system as a low-privileged user, hence the name privilege-escalation.
There was one problem, however. When you print a string to the printer, it looks like there are some markup bytes at the beginning of the file as the printer thinks you are printing and not to a file. Since the first few bytes of a file is the signature (magic bytes) of a file, it can not be touched if you want to execute it in a usual way.
I wanted to check if I was able to write a valid executable file to disk without any markup bytes at the beginning of the file. The script linked below creates a printer with a malicious printer port and write a byte array to the newly created printer. This way, it is possible to dump a valid binary on disk as SYSTEM once you restart the spooler service.
Attacks like DLL hijacking is possible as a low-privileged user using the PrintDemon bug. Microsoft released a patch last week. After installing the patch, the system checks if the user has permissions, which you set as a port on a printer, before creating the port. Unfortunately, the patch prevents creating a new malicious port, but malicious ports created before the patch still work.
The C# code can be found here and the PowerShell code can be found here.