Skip to content

TDS / MQTT / Exchange

Back to the Technology Index

This page covers SQL Server’s TDS, MQTT for message delivery, and Exchange NSPI. It shows how each connection starts and how Impacket reads the responses. The corresponding CLIs are listed in the MSSQL / Exchange / MQTT Command Index.

Implementation: MSSQL in impacket/tds.py. Interactive operation is in impacket/examples/mssqlshell.py.

The normal transport is TCP. mssqlclient.py -named-pipe opens a named pipe over SMB and sends the same TDS messages. -auth-smb / -hashes-smb allow separate SMB and SQL credentials. With Windows authentication, the SMB identity is used for SQL login. TDS 8.0 strict encryption is not supported over named pipes.

MSSQL.getInstances() sends SQLR_CLNT_UCAST_EX to UDP 1434 (SQLR_PORT). This is the same Browser protocol used by mssqlinstance. Responses repeat name;value; pairs and contain the instance name, port, named pipe, and version. This helps determine the Kerberos SPN (MSSQLSvc/host:port or MSSQLSvc/host:INSTANCE).

TDS_PRELOGIN exchanges the version, encryption setting, instance, and thread ID. If encryption is required, the connection switches to TLS and sends LOGIN7 over it. There is also a TDS 8 path (tds8).

Authentication in TDS_LOGIN (LOGIN7):

PathCLIWire Format
SQL authenticationDefaultUser and obfuscated password in LOGIN7
Windows NTLM-windows-authType1/Type2/Type3 in the SSPI field
Kerberos-kSPNEGO + AP-REQ in SSPI; kerberosLogin()

Writing DOMAIN\user as the username alone does not enable Windows authentication. -windows-auth changes the login mechanism.

The SQL password is obfuscated in LOGIN7 by nibble swaps and XOR (encryptPassword()); without TLS, this does not protect it.

Channel binding applies over TLS. The client uses generate_cbt_from_tls_unique() to create tls-unique. checkMSSQLStatus checks the login response for CBT enforcement. The TDS 8 (tds8) path establishes TLS before PRELOGIN.

A query uses a SQL Batch packet. The server returns a token stream.

TokenMeaning
COLMETADATAColumn names and types
ROW / NBCROWRows
DONE / DONEPROC / DONEINPROCEnd of a batch; status includes whether there was an error
ERROR / INFOMessages; DONE can follow ERROR
ENVCHANGEChanges such as database switching; retained in the session
LOGINACK / FEATUREEXTACK / RETURNSTATUSLogin and features

TDS_INFO_ERROR and TDS_DONE have layouts for versions 7.1 and earlier and 7.2 and later (login7_uses_72_plus_token_layout). Packet boundaries are separate from token boundaries. Do not mistake multiple result sets or NULL for ordinary rows.

MSSQLShell helpers such as xp_cmdshell call server-side procedures in the same session. The database context and transaction remain in effect.

Related CLI: mssqlclient

Implementation: impacket/mqtt.py. mqtt_check sends CONNECT and checks whether anonymous connections work and what CONNACK returns. It is independent of the Windows authentication stack. The wire format starts with a fixed header and a variable-length integer for remaining length.

exchanger uses nspi.py and oxabref.py to enumerate and dump the address book. The transport is often RPC over HTTP (ncacn_http).

NSPI is an RPC interface for MAPI address books. Its main tasks are GUID / DNT lookups and restricted table enumeration. It is not an EWS/MAPI client for the mailbox itself.

  • Change TDS versions and token layouts together
  • Keep Windows and SQL authentication fields in LOGIN7 separate
  • Make CBT / TLS switching consistent with the PRELOGIN encryption flag
  • Check CONNECT flags for the MQTT protocol version (3.1 / 3.1.1)