Fix for PrintNightmare CVE-2021-34527 exploit to keep your Print Servers running while a patch is not available

UPDATE JULY 6th, 2021:
Please check the updated recommendations in our previous post here.

As we wrote in our previous post, the PrintNightmare vulnerability is critical and should be addressed immediately, as a patch is not yet available. A regular domain user can easily take over the entire Active Directory domain.

While we still recommend that the print spooler service should be disabled on any system that does not need it, we also want to provide a temporary workaround to make the exploit ineffective, while allowing you to keep your print servers running, until a patch is available.

The exploit works by dropping a DLL in a subdirectory under C:\Windows\System32\spool\drivers

By restricting the ACLs on this directory (and subdirectories) we can prevent malicious DLLs to be introduced by the print spooler service.

At the moment, we are not aware of any way to force the DLL to be dropped in a different location.

Restricting the ACLs

The following PowerShell script will do the trick.

$Path = "C:\Windows\System32\spool\drivers"

$Acl = (Get-Item $Path).GetAccessControl('Access')

$Ar = New-Object  System.Security.AccessControl.FileSystemAccessRule("System", "Modify", "ContainerInherit, ObjectInherit", "None", "Deny")

$Acl.AddAccessRule($Ar)

Set-Acl $Path $Acl

This will add a Deny rule for the drivers directory and all subdirectories, preventing the SYSTEM account to modify its contents.

PrintNightmare CVE-2021-1675 workaround ACL
Deny rule on the drivers directory and subdirectories

If administrators need to perform configuration changes that require the service to write in these directories, this rule can temporarily be removed, and re-added after the change.

To remove the ACL we just added (as commented by u/bclimber):

$Path = "C:\Windows\System32\spool\drivers"

$Acl = (Get-Item $Path).GetAccessControl('Access')

$Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("System", "Modify", "ContainerInherit, ObjectInherit", "None", "Deny")

$Acl.RemoveAccessRule($Ar)

Set-Acl $Path $Acl

This is not a perfect solution, but until a patch is available, it is a way to keep the print server running in cases where it is strictly necessary.

We have verified that the ACL prevents the successful execution of the following exploit implementations:

EDIT:

We changed:

$Acl = Get-Acl $Path

to:

$Acl = (Get-Item $Path).GetAccessControl('Access')

to avoid errors when running this as SYSTEM. Thanks _Dadministrator_ for bringing this up

EDIT2:

For a fancier version, Chaim Black wrote a nice wrapper function around it.

EDIT3:

If print jobs fail, you can test the following (thanks @ve55ev for the suggestion) – NOTE: we have not tested this.


By Fabio Viggiani

Fabio is the technical lead of Truesec Security Team. He leads advanced Incident Response missions, and has extensive experience in Red Team assignments as well as traditional penetration tests.

He also works closely with Truesec Security Operations Center, focusing on Threat Hunting and detection.

This gives him a strong insight in the current threat landscape and the latest attacks and detection techniques.