UPDATE JULY 6, 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:WindowsSystem32spooldrivers
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:WindowsSystem32spooldrivers"
$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.
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:WindowsSystem32spooldrivers"
$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:
- https://github.com/cube0x0/CVE-2021-1675 (both C# and Python impacket implementations)
- https://github.com/afwu/PrintNightmare
EDIT:
We changed:
$Acl <strong>=</strong> Get-Acl $Path
to:
$Acl <strong>=</strong> (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.