metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

PAYLOAD value from datastore is not populated via RPC

Open nrathaus opened this issue 1 year ago • 4 comments

Background

Some modules / exploits define the preferred payload in their 'default_options', example: [https://github.com/rapid7/metasploit-framework/commit/2b90d33aefe0b01d52bce71bfd85f266e430f08a]

This information is not being sent our via the RPC interface, neither via the datastore (which isn't sent out) nor via the default_options variable that is created (via the module internal mechanism)

How to recreate:

Gather the options of the module: use exploit/linux/http/opennms_horizon_authenticated_rce via RPC

Note that compatible_payloads is empty (array is len 0), while if you use the msfconsole the PAYLOAD value of DefaultOptions is used, allowing you to know which payload to use

The problem is not specific to this module, all modules that use a DefaultOptions Payload will have a similar outcome

Potential solution in lib/msf/core/rpc/v10/rpc_module.rb add, under def rpc_info(mtype, mname), a check that verifies if PAYLOAD inside the datastore is present, if it is, pass it out

There is possible other values in the datastore that we may want to send back via the RPC to make it more accurate and useful.

Unfortunately, using rpc['datastore'] = m.datastore doesn't work (probably due to its size?)

Metasploit version

Framework: 6.4.1-dev- Console : 6.4.1-dev-

nrathaus avatar Mar 24 '24 08:03 nrathaus

It seems that if you add to the above function rpc_info a simple call for: res['PAYLOAD'] = m.datastore['PAYLOAD']

To cause the PAYLOAD to show up in the info of the module

nrathaus avatar Mar 24 '24 09:03 nrathaus

Maybe an option is to add to lib/msf/core/exploit.rb:

    if info.key? 'DefaultOptions'
      print "DefaultOptions found in info\n"
      self.default_options = info['DefaultOptions']
    end

Inside the def initialize - and then we can reference this

nrathaus avatar Mar 24 '24 09:03 nrathaus

I've also observed this issue for many modules; it would be really useful to have solved. For example, https://github.com/rapid7/metasploit-framework/blob/master//modules/exploits/multi/misc/apache_activemq_rce_cve_2023_46604.rb.

The wfsdelay is 2 and the payload is null if the options are queried for this module through the RPC API.

FenixH avatar Mar 29 '24 10:03 FenixH

Its not specific to the exploit I mentioned, just there it is evident if you compare RPC results and msfconsole results - due to lack of the payload values not being passed

nrathaus avatar Mar 29 '24 11:03 nrathaus

I've confirmed there's some nuanced differences in the RPC layer in how options are handled versus a module's default options that are used to populate the datastore.

Just to confirm all the datapoints - which RPC calls are you making here in particular? Just rpc_info or others as well?

adfoster-r7 avatar Apr 05 '24 11:04 adfoster-r7

I am using pymetasploit3 (just for context) and the use for ExploitModule class

What it does, is call module.info, pulls all the _info information and places them in dicts

It then tries to get default_target for use with payload picking.

Subsequently, via the payloads function you can make a call to module.target_compatible_payloads which should return the relevant payloads for this module.

Some modules like exploit/linux/http/opennms_horizon_authenticated_rce return an empty array (empty payloads), see this small python snippet:

exploit_path = "linux/http/opennms_horizon_authenticated_rce"
client = MsfRpcClient(
                metasploit_msfrpcd_password, port=55553, ssl=True
            )
res = client.modules.use("exploit", exploit_path)

Hope this clarifies the problem I am seeing

nrathaus avatar Apr 05 '24 14:04 nrathaus

Proposed fix: https://github.com/rapid7/metasploit-framework/pull/19086

I used via pymetasploit3 code that use all available exploits to confirm this has no effect beyond exposing the information (i.e. no crash)

nrathaus avatar Apr 14 '24 16:04 nrathaus

from pymetasploit3.msfrpc import MsfRpcClient
client = MsfRpcClient(
                metasploit_msfrpcd_password, port=55544 ssl=True
            )
exploits = client.modules.search("type:exploit")
for exploit in exploits:
  res = client.modules.use("exploit", exploit)

nrathaus avatar Apr 14 '24 17:04 nrathaus

Merged

nrathaus avatar Apr 21 '24 11:04 nrathaus