by Bhabesh Raj, Associate Security Analytics Engineer

On Patch Tuesday for June 2021, Microsoft fixed a Print Spooler vulnerability CVE-2021-1675 in Windows. At the same time, a similar vulnerability dubbed PrintNightmare that had been discovered by another group mistakenly released the details and proof-of-concept (PoC) of PrintNightmare due to the confusion effectively turning PrintNightmare into a zero-day.

Originally categorized as a low severity privilege escalation vulnerability, on June 21 Microsoft ramped up the severity of CVE-2021-1675 to critical because the flaw enabled remote code execution. Coincidentally, PrintNightmare also allows remote code execution which further contributed to the confusion between CVE-2021-1675 and PrintNightmare. On July 2, Microsoft finally dropped a new CVE-2021-34527 for PrintNightmare and stated that CVE-2021-34527 is similar but distinct from CVE-2021-1675 though both are flaws in the same functions. Interestingly, systems are still vulnerable to CVE-2021-1675 even after applying the patches if they are Point and Print configured with the NoWarningNoElevationOnInstall option.

The PrintNightmare vulnerability arises due to the fact that any authenticated user can install a new printer driver and specify a driver file that is housed on a remote server. Thus, the Print Spooler service executes code in an arbitrary DLL (disguised as a printer driver) with SYSTEM privileges. Threat actors are likely having a field day due to the availability of several working PoCs, which is made worse by the confusion in the security community regarding which systems are affected by PrintNightmare.

Both flaws are very severe due to the fact that the Print Spooler service is enabled by default with the exception of Server core. Domain controllers remain the juicy target for the vulnerability as they can allow full domain compromise.

Since no patch is available, we advise disabling the Print Spooler service on unnecessary machines. Administrators can use Group Policy Preferences (GPP) to disable Print Spooler on machines across the domain or to disable inbound remote printing through Group Policy allowing only local printing. Remember that disabling the Print Spooler service effectively disables the ability to print both locally and remotely by the server. 

It is important to note that usually small organizations configure their domain controllers to also function as print servers, making it unfeasible for them to disable print spooler service as doing this will hamper their daily business operations. If Print Spooler needs to be running on some servers, administrators can offload the print server duty from the domain controller to a separate server. The risk of running print service on domain controllers is too high and cannot be justified.

LogPoint has released UseCases version 5.0.2, which includes dashboards and alerts for detecting exploitation of PrintNightmare vulnerability.

Preparing your log sources

The most solid evidence for detecting the exploitation of the flaw requires events from the Microsoft-Windows-PrintServer/Admin and Microsoft-Windows-PrintServer/Operational channels. You need to manually enable the latter. First, prepare plans with administrators to begin forwarding logs from the aforementioned sources to LogPoint. Also, If you have deployed Sysmon in the environment, we advise administrators to update the configuration to make sure Sysmon can catch PrintNightmare’s artifacts. Finally, you can also use IDS/IPS events to pick up network artifacts left by PrintNightmare.

Data Sources PrintNightmare

Possible data sources requirements for detecting PrintNightmare

Detecting exploitation artifacts in LogPoint

We can detect PrintNightmare artifacts from either endpoint or network events. As stated earlier, the most reliable way to detect the exploitation requires looking for Event IDs such as 808 and 316. In both events, we can observe the name of the malicious DLL being loaded by the print spooler service. In our testing, Event ID 808 is not always generated, and even when it is generated, the malicious DLL was successfully loaded.

norm_id=WinServer event_source="Microsoft-Windows-PrintService" event_id=808

A failed load of a printer plugin

You can look for events showing a failed load of a printer plugin.

norm_id=WinServer event_source="Microsoft-Windows-PrintService" event_id=316

events showing the addition or update of printer drivers

You can look for events showing the addition or update of printer drivers.

Using Sysmon’s file creation events, we can hunt for dropping of DLLs in the Print Spooler’s driver directory.

norm_id=WindowsSysmon event_id=11
path="C:\Windows\System32\spool\drivers\x64\3\*"

DLLs in Print Spooler's driver directory

You can look for the dropping of DLLs in Print Spooler’s driver directory.

The dropped DLLs are subsequently loaded by the Print Spooler process (spoolsv.exe) as seen from Sysmon’s image load events.

norm_id=WindowsSysmon label=Image label=Load
source_image="*\spoolsv.exe"
image="C:\Windows\System32\spool\drivers\x64\3\*"

loading of DLLs from Print Spooler's driver directory

You can look for the loading of DLLs from Print Spooler’s driver directory.

The loaded DLLs also make their appearance on print spooler’s registry paths as seen from Sysmon’s registry events.

norm_id=WindowsSysmon label=Registry label=Set
target_object IN ["*\Configuration File*", "*\Data File"] | chart count() by host, image, target_object, detail

newly loaded DLLs from Print Spooler's registry location

You can look for the list of newly loaded DLLs from Print Spooler’s registry location

Finally, the DLLs are deleted as seen from Sysmon’s file deletion events.

norm_id=WindowsSysmon event_id IN [23, 26] source_image="*\spoolsv.exe" image="C:\Windows\System32\spool\drivers\x64\3\*"

While the new Sysmon configuration is being pushed to the environment, we can also use native Windows events to look for possible exploitation. We can either look for the spawning of WerFault.exe by the Print Spooler service or the unexpected termination of the Print Spooler service. We can use native Windows events because the Print Spooler service will generate an error during the loading of the payload DLL. It should be noted that successful side-loading of the DLL will bypass this behavior.

((norm_id=WindowsSysmon label="Process" label=Create
parent_image="*\spoolsv.exe" image="*\WerFault.exe")
OR (norm_id=WinServer channel=System event_id=7031
message="The Print Spooler service terminated unexpectedly"))
| timechart count() by event_id, host

error generated by the Print Spooler service

Look for an error generated by the Print Spooler service to identify successful exploitation as well as to narrow down the time range in case events from Print Service or Sysmon are not available.

Alternatively, we can also use generic exploitation detection by looking for the spawning of suspicious processes by the Print Spooler service.

norm_id=WindowsSysmon label="Process" label=Create
parent_image="*\spoolsv.exe" image IN ["*\cmd.exe", "*\powershell.exe", "*\rundll32.exe"]

From the network side, we need to look for the transfer of the payload DLL via SMB, which is easy if you have IDS/IPS like Snort and Zeek (Bro) in the environment.

norm_id IN [Snort, SuricataIDS] (message="ET POLICY SMB2 NT Create AndX Request For a DLL File - Possible Lateral Movement"
OR signature="ET POLICY SMB2 NT Create AndX Request For a DLL File - Possible Lateral Movement")

norm_id=BroIDS event_category=files
(file="*.DLL" OR mime_type="application/x-dosexec")

For the transfer of DLLs via SMB

If you have an IDS or IPS, you can look for the transfer of DLLs via SMB.

In both of the above queries, we can further narrow them down by specifically looking for domain controllers as the destination but that may not always be the case.

We should remember that PrintNightmare can also be used for local privilege escalation (LPE) like for example using the PowerShell PoC to create a local admin user bypassing the need for remote RPC or SMB protocols. Administrators are advised to lookout for new user local creations after the generation of any of the PrintNightmare artifacts as shown below.

[ norm_id=WindowsSysmon label=Registry label=Set
target_object IN ["*\Configuration File*", "*\Data File"]] as s1 followed by [ label=Create label=User ] as s2 on s1.host=s2.host
| chart count() by s1.host, s1.image, s1.target_object, s1.detail, s2.target_user

New user creations following the addition of new entries in Print Spooler's registry location

You can look for new user creations following the addition of new entries in Print Spooler’s registry location

Sysmon Configuration is key to detect exploitation

One can readily notice how we have used Sysmon to detect various artifacts generated by PrintNightmare. Don’t overlook the importance of Sysmon in today’s threat landscape. You can use Sysmon to enrich the base Windows event logs by complementing existing sources like process creation as well as adding support for new data sources like pipe creations that are vital to detecting threats in the current landscape. However, configuring Sysmon remains a game of delicate balance between detecting a wide range of events and avoiding log flooding. It all boils down to properly configuring rules in the Sysmon configuration that is specifically tailored to the environment where you will deploy it.

SwiftOnSecurity’s Sysmon configuration remains one of the best starting points to begin configuring Sysmon tailored to one’s environment. Sysmon configuration must include rules for detecting important events like dropping of DLLs and EXEs but also an exclusion for legitimate applications that are very noisy like inbuilt system processes such as svchost, AVs, EDRs, vulnerability scanners and databases like MSSQL. Begin by deploying the base configuration on select systems and monitor the log volume. Then, start setting up exclusions for noisy events in the configuration. Repeat this process until the SIEM’s storage can handle the log volume when deployed to all the systems in the environment.

New Sysmon versions introduce new events so make sure to satisfy the minimum Sysmon version required to generate the events of interest. Finally, before blindly using a detection that relies on Sysmon, be sure to check whether the deployed configuration can generate the events required by the detection. Blindspots in Sysmon’s configuration are a common occurrence, which you must avoid through rigorous testing before full deployment in the environment.

Brace for PrintNightmare use by threat actors

Since we still do not know when Microsoft will release a patch for PrintNightmare, enterprise defenders must remain vigilant as we expect threat actors of all levels to begin exploiting the vulnerability to elevate privileges once gaining access into the environment. Even though Microsoft has stated that only Domain controllers are affected with their investigating going on to identify other affected roles, it is better to assume all versions of Windows are affected. We recommend correlating events from multiple sources for reliable detection, which should not be a problem for enterprises that have implemented a defense-in-depth approach.

We strongly advise administrators to perform a full enterprise-wide hunt for exploitation attempts from the start of June, apply necessary mitigations, satisfy data sources requirements and continuously look for future exploitation attempts by threat actors until Microsoft releases a patch.