Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
1N3
GitHub Repository: 1N3/Sn1per
Path: blob/master/bin/http-default-accounts-fingerprints-nndefaccts.lua
2960 views
1
--[[
2
This file is part of NNdefaccts, an alternate fingerprint dataset for
3
Nmap script http-default-accounts.
4
5
NNdefaccts is Copyright (c) 2012-2019 by nnposter
6
(nnposter /at/ users.sourceforge.net, <https://github.com/nnposter>)
7
8
NNdefaccts is free software: you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by the Free
10
Software Foundation, either version 3 of the License, or (at your option)
11
any later version.
12
13
NNdefaccts is distributed in the hope that it will be useful, but WITHOUT
14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16
for more details.
17
18
You should have received a copy of the GNU General Public License along
19
with this program. If not, see <http://www.gnu.org/licenses/>.
20
21
Note that NNdefaccts is licensed separately from Nmap. By obtaining
22
a custom license for Nmap you are not automatically entitled to modify or
23
distribute the NNdefaccts dataset to the same extent as Nmap itself and,
24
conversely, licensing NNdefaccts does not cover Nmap. For details, see
25
<https://github.com/nnposter/nndefaccts/COPYING>.
26
27
You can obtain the latest version of the dataset from its public repository
28
at <https://github.com/nnposter/nndefaccts/>.
29
30
To report bugs and other problems, contribute patches, request a feature,
31
provide generic feedback, etc., please see instructions posted at
32
<https://github.com/nnposter/nndefaccts/README.md>.
33
]]
34
35
36
local base64 = require "base64"
37
local http = require "http"
38
local json = require "json"
39
local math = require "math"
40
local os = require "os"
41
local shortport = require "shortport"
42
local stdnse = require "stdnse"
43
local table = require "table"
44
local url = require "url"
45
local have_openssl, openssl = pcall(require, "openssl")
46
local have_rand, rand = pcall(require, "rand")
47
local have_stringaux, stringaux = pcall(require, "stringaux")
48
local have_tableaux, tableaux = pcall(require, "tableaux")
49
50
---
51
-- http-default-accounts-fingerprints-nndefaccts.lua
52
-- This file contains fingerprint data for http-default-accounts.nse
53
--
54
-- STRUCTURE:
55
-- * <code>name</code> - Descriptive name
56
-- * <code>cpe</code> - Official CPE Dictionary entry (optional)
57
-- * <code>category</code> - Category
58
-- * <code>login_combos</code> - Table of default credential pairs
59
---- * <code>username</code>
60
---- * <code>password</code>
61
-- * <code>paths</code> - Table of likely locations (paths) of the target
62
-- * <code>target_check</code> - Validation function of the target
63
-- (optional but highly recommended)
64
-- * <code>login_check</code> - Login function of the target
65
---
66
67
---
68
-- Backwards compatibility provisions for library rand
69
---
70
if not have_rand then
71
rand = {}
72
end
73
if not rand.random_string then
74
rand.random_string = stdnse.generate_random_string
75
end
76
77
---
78
-- Generates a random alphanumeric string.
79
--
80
-- @param len Length of the output string.
81
-- @return A random string consisting of letters and digits
82
---
83
local function random_alnum (len)
84
return rand.random_string(len, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
85
end
86
87
---
88
-- Generates a random hexadecimal string.
89
--
90
-- @param len Length of the output string.
91
-- @return A random string consisting of hexadecimal digits
92
---
93
local function random_hex (len)
94
return rand.random_string(len, "0123456789abcdef")
95
end
96
97
---
98
-- Backwards compatibility provisions for library stringaux
99
---
100
if not have_stringaux then
101
stringaux = {}
102
end
103
if not stringaux.ipattern then
104
stringaux.ipattern = stdnse.generate_case_insensitive_pattern
105
end
106
107
---
108
-- Backwards compatibility provisions for library tableaux
109
---
110
if not have_tableaux then
111
tableaux = {}
112
end
113
if not tableaux.tcopy then
114
tableaux.tcopy =
115
function (tbl)
116
local clone = {}
117
for k,v in pairs(tbl) do
118
clone[k] = type(v) == "table" and tableaux.tcopy(v) or v
119
end
120
return clone
121
end
122
end
123
if not tableaux.contains then
124
tableaux.contains = stdnse.contains
125
end
126
127
---
128
-- Requests given path using http.get() but disabling cache and redirects.
129
-- @param host The host to connect to
130
-- @param port The port to connect to
131
-- @param path The path to retrieve
132
-- @param options [optional] A table of HTTP request options
133
-- @return A response table (see library http.lua for description)
134
---
135
local function http_get_simple (host, port, path, options)
136
local opts = tableaux.tcopy(options or {})
137
opts.bypass_cache = true
138
opts.no_cache = true
139
opts.redirect_ok = false
140
return http.get(host, port, path, opts)
141
end
142
143
---
144
-- Requests given path using http.post() but disabling cache and redirects.
145
-- (The current implementation of http.post() does not use either; this is
146
-- a defensive wrapper to guard against future problems.)
147
-- @param host The host to connect to
148
-- @param port The port to connect to
149
-- @param path The path to retrieve
150
-- @param options [optional] A table of HTTP request options
151
-- @param postdata A string or a table of data to be posted
152
-- @return A response table (see library http.lua for description)
153
---
154
local function http_post_simple (host, port, path, options, postdata)
155
local opts = tableaux.tcopy(options or {})
156
opts.no_cache = true
157
opts.redirect_ok = false
158
return http.post(host, port, path, opts, nil, postdata)
159
end
160
161
---
162
-- Requests given path using http_post_simple() with the body formatted as
163
-- Content-Type multipart/form-data.
164
-- @param host The host to connect to
165
-- @param port The port to connect to
166
-- @param path The path to retrieve
167
-- @param options [optional] A table of HTTP request options
168
-- @param postdata A table of data to be posted
169
-- @return A response table (see library http.lua for description)
170
---
171
local function http_post_multipart (host, port, path, options, postdata)
172
local boundary = ("-"):rep(20)
173
.. math.random(1000000, 9999999)
174
.. math.random(1000000, 9999999)
175
local opts = tableaux.tcopy(options or {})
176
opts.header = opts.header or {}
177
opts.header["Content-Type"] = "multipart/form-data; boundary=" .. boundary
178
if type(postdata) ~= "table" then
179
return {status = nil,
180
["status-line"] = "POST data must be a table",
181
header = {},
182
rawheader = {}}
183
end
184
boundary = "--" .. boundary
185
local body = {}
186
for k, v in pairs(postdata) do
187
table.insert(body, boundary)
188
table.insert(body, ('Content-Disposition: form-data; name="%s"'):format(k))
189
table.insert(body, "")
190
table.insert(body, v)
191
end
192
table.insert(body, boundary .. "--")
193
table.insert(body, "")
194
return http_post_simple (host, port, path, opts, table.concat(body, "\r\n"))
195
end
196
197
---
198
-- Requests given path using native HTTP authentication.
199
-- @param host Host table
200
-- @param port Port table
201
-- @param path Path to request
202
-- @param user HTTP authentication username
203
-- @param pass HTTP authentication password
204
-- @param digest true: digest auth, false: basic auth, "any": try to detect
205
-- @return True if login in was successful
206
---
207
local function try_http_auth (host, port, path, user, pass, digest)
208
if digest == "any" then
209
local resp = http_get_simple(host, port, path)
210
local auth = (resp.header["www-authenticate"] or ""):lower():match("^%w+")
211
if not auth then return end
212
digest = auth == "digest"
213
end
214
local creds = {username = user, password = pass, digest = digest}
215
local resp = http_get_simple(host, port, path, {auth=creds})
216
return resp.status and not (resp.status >= 400 and resp.status <= 405)
217
end
218
219
---
220
-- Returns authentication realm advertised in an HTTP response
221
-- @param response HTTP response object, such as a result from http.get()
222
-- @return realm found in response header WWW-Authenticate
223
-- (or nil if not present)
224
---
225
local function http_auth_realm (response)
226
local auth = response.header["www-authenticate"] or ""
227
-- NB: "OEM Netcam" devices lack the closing double quote
228
return auth:match('%srealm%s*=%s*"([^"]*)')
229
end
230
231
---
232
-- Tests whether an HTTP response sets a named cookie with a given value
233
-- @param response a standard HTTP response object
234
-- @param name a case-insensitive cookie name that must be set
235
-- @param pattern to validate the cookie value
236
-- @return cookie value if such a cookie is found
237
---
238
local function get_cookie (response, name, pattern)
239
name = name:lower()
240
for _, ck in ipairs(response.cookies or {}) do
241
if ck.name:lower() == name and (not pattern or ck.value:find(pattern)) then
242
return ck.value
243
end
244
end
245
return false
246
end
247
248
---
249
-- Parses an HTML tag and returns parsed attributes
250
-- @param html a string representing HTML tag. It is expected that the first
251
-- and last characters are angle brackets.
252
-- @return table of attributes with their names converted to lowercase
253
---
254
local function parse_tag (html)
255
local attrs = {}
256
local _, pos = html:find("^<%f[%w][%w-]+[^%w-]")
257
while true do
258
local attr, equal
259
_, pos, attr, equal = html:find("%f[%w]([%w-]+)%s*(=?)%s*", pos)
260
if not pos then break end
261
local oldpos = pos + 1
262
if equal == "=" then
263
local c = html:sub(oldpos, oldpos)
264
if c == "\"" or c == "'" then
265
oldpos = oldpos + 1
266
pos = html:find(c, oldpos, true)
267
else
268
pos = html:find("[%s>]", oldpos)
269
end
270
if not pos then break end
271
else
272
pos = oldpos
273
end
274
attrs[attr:lower()] = html:sub(oldpos, pos - 1)
275
end
276
return attrs
277
end
278
279
---
280
-- Searches given HTML string for an element tag that meets given attribute
281
-- critera and returns its position and all its attributes
282
-- @param html a string representing HTML test
283
-- @param elem an element to search for (for example "img" or "div")
284
-- @param criteria a table of attribute names and corresponding patterns,
285
-- for example {id="^secret$"}. The patterns are treated as case-insensitive.
286
-- (optional)
287
-- @param init a string position from which to start searching (optional)
288
-- @return position of the opening angle bracket of the found tag or nil
289
-- @return position of the closing angle bracket of the found tag or nil
290
-- @return table of tag attributes with their names converted to lowercase
291
---
292
local function find_tag (html, elem, criteria, init)
293
local icrit = {}
294
for cnam, cptn in pairs(criteria or {}) do
295
icrit[cnam:lower()] = stringaux.ipattern(cptn)
296
end
297
local tptn = stringaux.ipattern("<" .. elem:gsub("%-", "%%-") .. "%f[%s/>].->")
298
local start
299
local stop = init
300
while true do
301
start, stop = html:find(tptn, stop)
302
if not start then break end
303
local attrs = parse_tag(html:sub(start, stop))
304
local found = true
305
for cnam, cptn in pairs(icrit) do
306
local cval = attrs[cnam]
307
if not (cval and cval:find(cptn)) then
308
found = false
309
break
310
end
311
end
312
if found then return start, stop, attrs end
313
end
314
return
315
end
316
317
---
318
-- Searches given HTML string for an element tag that meets given attribute
319
-- critera and returns all its attributes
320
-- @param html a string representing HTML test
321
-- @param elem an element to search for (for example "img" or "div")
322
-- @param criteria a table of attribute names and corresponding patterns,
323
-- for example {id="^secret$"}. The patterns are treated as case-insensitive.
324
-- (optional)
325
-- @param init a string position from which to start searching (optional)
326
-- @return table of tag attributes with their names converted to lowercase
327
---
328
local function get_tag (html, elem, criteria, init)
329
local start, stop, attrs = find_tag(html, elem, criteria, init)
330
return attrs
331
end
332
333
---
334
-- Builds an iterator function that searches given HTML string for element tags
335
-- that meets given attribute critera
336
-- @param html a string representing HTML test
337
-- @param elem an element to search for (for example "img" or "div")
338
-- @param criteria a table of attribute names and corresponding patterns,
339
-- for example {id="^secret$"}. The patterns are treated as case-insensitive.
340
-- (optional)
341
-- @param init a string position from which to start searching (optional)
342
-- @return iterator
343
---
344
local function get_tags (html, elem, criteria)
345
local init = 0
346
return function ()
347
local _, attrs
348
_, init, attrs = find_tag(html, elem, criteria, (init or #html) + 1)
349
return attrs
350
end
351
end
352
353
---
354
-- Searches given HTML string for an element tag that meets given attribute
355
-- critera and returns inner HTML of the corresponding element
356
-- (Nested elements of the same type are not supported.)
357
-- @param html a string representing HTML test
358
-- @param elem an element to search for (for example "div" or "title")
359
-- @param criteria a table of attribute names and corresponding patterns,
360
-- for example {id="^secret$"}. The patterns are treated as case-insensitive.
361
-- (optional)
362
-- @param init a string position from which to start searching (optional)
363
-- @return inner HTML
364
---
365
local function get_tag_html (html, elem, criteria, init)
366
local _, start, attrs = find_tag(html, elem, criteria, init)
367
if not start then return end
368
start = start + 1
369
local stop = html:find(stringaux.ipattern("</" .. elem:gsub("%-", "%%-") .. "[%s>]"), start)
370
return stop and html:sub(start, stop - 1) or nil
371
end
372
373
---
374
-- Searches given HTML string for a meta refresh tag and returns the target URL
375
-- @param html a string representing HTML test
376
-- @param criteria a pattern to validate the extracted target URL
377
-- for example {id="^secret$"}. The patterns are treated as case-insensitive.
378
-- (optional)
379
-- @param init a string position from which to start searching (optional)
380
-- @return table of tag attributes with their names converted to lowercase
381
---
382
local function get_refresh_url (html, criteria)
383
local refresh = get_tag(html, "meta", {["http-equiv"]="^refresh$", content="^0;%s*url="})
384
if not refresh then return end
385
local url = refresh.content:match("=(.*)")
386
return url:find(stringaux.ipattern(criteria)) and url or nil
387
end
388
389
---
390
-- Generates default scheme, host, and port components for a parsed URL.
391
--
392
-- This filter function generates the scheme, host, and port components from
393
-- the standard <code>host</code> and <code>port</code> script objects. These
394
-- components can then be passed onto function <code>url.build</code>.
395
--
396
-- As an example, the following code generates a URL for path "/test/"
397
-- on the current host and port:
398
-- <code>
399
-- local testurl = url.build(url_build_defaults(host, port, {path = "/test/"}))
400
-- </code>
401
-- or, alternatively, when not used as a filter:
402
-- <code>
403
-- local parsed = url_build_defaults(host, port)
404
-- parsed.path = "/test/"
405
-- local testurl = url.build(parsed)
406
-- </code>
407
--
408
-- @param host The host the URL is intended for.
409
-- @param port The port the URL is intended for.
410
-- @param parsed Parsed URL, as typically returned by <code>url.parse</code>,
411
-- or nil. The table can be be missing the scheme, host, and port components.
412
-- @return A clone of the parsed URL, with any missing scheme, host, and port
413
-- components added.
414
-- @see url.parse
415
-- @see url.build
416
---
417
local function url_build_defaults (host, port, parsed)
418
local parts = tableaux.tcopy(parsed or {})
419
parts.host = parts.host or stdnse.get_hostname(host, port)
420
parts.scheme = parts.scheme or shortport.ssl(host, port) and "https" or "http"
421
if not parts.port and port.number ~= url.get_default_port(parts.scheme) then
422
parts.port = port.number
423
end
424
return parts
425
end
426
427
---
428
-- Encodes a string to make it safe for embedding into XML/HTML.
429
--
430
-- @param s The string to be encoded.
431
-- @return A string with unsafe characters encoded
432
---
433
local function xmlencode (s)
434
return s:gsub("%W", function (c) return ("&#x%x;"):format(c:byte()) end)
435
end
436
437
---
438
-- Decodes an XML-encoded string.
439
--
440
-- @param s The string to be decoded.
441
-- @return A string with XML encoding stripped off
442
---
443
local function xmldecode (s)
444
local refmap = {amp = "&", quot = "\"", apos = "'", lt ="<", gt = ">"}
445
return s:gsub("&.-;",
446
function (e)
447
local r = e:sub(2,-2)
448
if r:find("^#x%x%x$") then
449
return stdnse.fromhex(r:sub(3))
450
end
451
return refmap[r]
452
end)
453
end
454
455
---
456
-- Performs URL encoding of all characters in a string.
457
--
458
-- @param s The string to be encoded.
459
-- @return A URL-encoded string
460
---
461
local function urlencode_all (s)
462
return s:gsub(".", function (c) return ("%%%02x"):format(c:byte()) end)
463
end
464
465
---
466
-- Decodes a base64-encoded string safely, catching any decoding errors.
467
--
468
-- @param s The string to be decoded.
469
-- @return A decoded string or nil if the input is invalid
470
---
471
local function b64decode (s)
472
local status, out = pcall(base64.dec, s)
473
return status and out or nil
474
end
475
476
477
fingerprints = {}
478
479
---
480
--WEB
481
---
482
table.insert(fingerprints, {
483
name = "Ansible AWX",
484
cpe = "cpe:/a:ansible:tower",
485
category = "web",
486
paths = {
487
{path = "/api/"}
488
},
489
target_check = function (host, port, path, response)
490
if not (response.status == 200
491
and get_cookie(response, "csrftoken", "^%w+$")
492
and response.body
493
and response.body:find("AWX REST API", 1, true)) then
494
return false
495
end
496
local jstatus, jout = json.parse(response.body)
497
return jstatus and jout.description == "AWX REST API"
498
end,
499
login_combos = {
500
{username = "admin", password = "password"}
501
},
502
login_check = function (host, port, path, user, pass)
503
local resp1 = http_get_simple(host, port, path)
504
if resp1.status ~= 200 then return false end
505
local token = get_cookie(resp1, "csrftoken")
506
if not token then return false end
507
local form = {username=user,
508
password=pass,
509
next=path}
510
local header = {["X-CSRFToken"]=token}
511
local resp2 = http_post_simple(host, port, url.absolute(path, "login/"),
512
{cookies=resp1.cookies, header=header}, form)
513
return resp2.status == 302
514
and resp2.header["location"] == path
515
and get_cookie(resp2, "userLoggedIn") == "true"
516
end
517
})
518
519
table.insert(fingerprints, {
520
name = "Cacti",
521
cpe = "cpe:/a:cacti:cacti",
522
category = "web",
523
paths = {
524
{path = "/"},
525
{path = "/cacti/"}
526
},
527
target_check = function (host, port, path, response)
528
return response.status == 200
529
and (get_cookie(response, "Cacti") or get_cookie(response, "CactiEZ"))
530
end,
531
login_combos = {
532
{username = "admin", password = "admin"}
533
},
534
login_check = function (host, port, path, user, pass)
535
local form = {action="login",
536
login_username=user,
537
login_password=pass}
538
local resp = http_post_simple(host, port, url.absolute(path, "index.php"),
539
nil, form)
540
return resp.status == 302
541
and (resp.header["location"] or ""):find("/", 1, true)
542
end
543
})
544
545
table.insert(fingerprints, {
546
name = "Zabbix",
547
cpe = "cpe:/a:zabbix:zabbix",
548
category = "web",
549
paths = {
550
{path = "/zabbix/"}
551
},
552
target_check = function (host, port, path, response)
553
return response.status == 200 and get_cookie(response, "zbx_sessionid")
554
end,
555
login_combos = {
556
{username = "admin", password = "zabbix"}
557
},
558
login_check = function (host, port, path, user, pass)
559
local form = {request="",
560
name=user,
561
password=pass,
562
enter="Sign in"}
563
local resp = http_post_simple(host, port, url.absolute(path, "index.php"),
564
nil, form)
565
return resp.status == 302 and resp.header["location"] == "dashboard.php"
566
end
567
})
568
569
table.insert(fingerprints, {
570
name = "Xplico",
571
category = "web",
572
paths = {
573
{path = "/"}
574
},
575
target_check = function (host, port, path, response)
576
return response.status == 302 and get_cookie(response, "Xplico")
577
end,
578
login_combos = {
579
{username = "admin", password = "xplico"},
580
{username = "xplico", password = "xplico"}
581
},
582
login_check = function (host, port, path, user, pass)
583
local lurl = url.absolute(path, "users/login")
584
local resp1 = http_get_simple(host, port, lurl)
585
if not (resp1.status == 200 and resp1.body) then return false end
586
local html = get_tag_html(resp1.body, "form", {action="/users/login$"})
587
if not html then return false end
588
local form = {}
589
for input in get_tags(html, "input", {type="^hidden$", name="", value=""}) do
590
form[input.name] = input.value
591
end
592
form["data[User][username]"] = user
593
form["data[User][password]"] = pass
594
local resp2 = http_post_simple(host, port, lurl,
595
{cookies=resp1.cookies}, form)
596
local loc = resp2.header["location"] or ""
597
return resp2.status == 302
598
and (loc:find("/admins$") or loc:find("/pols/index$"))
599
end
600
})
601
602
table.insert(fingerprints, {
603
name = "ExtraHop Web UI",
604
category = "web",
605
paths = {
606
{path = "/extrahop/"}
607
},
608
target_check = function (host, port, path, response)
609
return response.status == 200
610
and response.body
611
and response.body:find("csrfmiddlewaretoken", 1, true)
612
and response.body:lower():find("<title>extrahop login", 1, true)
613
end,
614
login_combos = {
615
{username = "admin", password = "admin"}
616
},
617
login_check = function (host, port, path, user, pass)
618
local resp1 = http_get_simple(host, port, path)
619
if not (resp1.status == 200 and resp1.body) then return false end
620
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrfmiddlewaretoken$", value=""})
621
if not token then return false end
622
local form = {[token.name]=token.value,
623
next=path,
624
username=user,
625
password=pass}
626
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}
627
local resp2 = http_post_simple(host, port, path,
628
{cookies=resp1.cookies, header=header}, form)
629
return resp2.status == 302
630
and (resp2.header["location"] or ""):sub(-#path) == path
631
end
632
})
633
634
table.insert(fingerprints, {
635
name = "Nagios",
636
cpe = "cpe:/a:nagios:nagios",
637
category = "web",
638
paths = {
639
{path = "/"},
640
{path = "/nagios/"}
641
},
642
target_check = function (host, port, path, response)
643
return http_auth_realm(response) == "Nagios Access"
644
end,
645
login_combos = {
646
{username = "nagiosadmin", password = "nagios"},
647
{username = "nagiosadmin", password = "nagiosadmin"},
648
{username = "nagiosadmin", password = "PASSW0RD"},
649
{username = "nagiosadmin", password = "CactiEZ"}
650
},
651
login_check = function (host, port, path, user, pass)
652
return try_http_auth(host, port, path, user, pass, false)
653
end
654
})
655
656
table.insert(fingerprints, {
657
name = "ManageEngine OpManager 10/11",
658
cpe = "cpe:/a:zohocorp:manageengine_opmanager",
659
category = "web",
660
paths = {
661
{path = "/"}
662
},
663
target_check = function (host, port, path, response)
664
if not (response.status == 200
665
and response.body
666
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])[^'\"]-/LoginPage%.do%1")) then
667
return false
668
end
669
local resp = http_get_simple(host, port, url.absolute(path, "LoginPage.do"))
670
return resp.status == 200
671
and resp.body
672
and resp.body:find("ManageEngine", 1, true)
673
and resp.body:lower():find("<title>%s*manageengine opmanager%s*</title>")
674
and get_tag(resp.body, "form", {action="/jsp/login%.do$"})
675
end,
676
login_combos = {
677
{username = "IntegrationUser", password = "plugin"},
678
{username = "admin", password = "admin"}
679
},
680
login_check = function (host, port, path, user, pass)
681
local resp1 = http_get_simple(host, port, url.absolute(path, "LoginPage.do"))
682
if resp1.status ~= 200 then return false end
683
local form2 = {clienttype="html",
684
isCookieADAuth="",
685
domainName="NULL",
686
authType="localUserLogin",
687
webstart="",
688
ScreenWidth=1024,
689
ScreenHeight=768,
690
loginFromCookieData="",
691
userName=user,
692
password=pass,
693
uname=""}
694
local resp2 = http_post_simple(host, port,
695
url.absolute(path, "jsp/Login.do"),
696
{cookies=resp1.cookies}, form2)
697
return (resp2.status == 200 or resp2.status == 302)
698
and get_cookie(resp2, "OPUTILSTICKET", "^%x+$")
699
end
700
})
701
702
table.insert(fingerprints, {
703
name = "ManageEngine OpManager 12",
704
cpe = "cpe:/a:zohocorp:manageengine_opmanager",
705
category = "web",
706
paths = {
707
{path = "/"}
708
},
709
target_check = function (host, port, path, response)
710
return response.status == 200
711
and response.body
712
and response.body:find("ManageEngine", 1, true)
713
and response.body:lower():find("<title>%s*manageengine opmanager%s*</title>")
714
and get_tag(response.body, "form", {action="^j_security_check%f[;\0]"})
715
end,
716
login_combos = {
717
{username = "admin", password = "admin"}
718
},
719
login_check = function (host, port, path, user, pass)
720
local resp1 = http_get_simple(host, port, path)
721
if resp1.status ~= 200 then return false end
722
local form2 = {AUTHRULE_NAME="Authenticator",
723
clienttype="html",
724
ScreenWidth=1024,
725
ScreenHeight=768,
726
loginFromCookieData="false",
727
ntlmv2="false",
728
j_username=user,
729
j_password=pass,
730
domainNameAD="Authenticator",
731
uname=""}
732
local resp2 = http_post_simple(host, port,
733
url.absolute(path, "j_security_check"),
734
{cookies=resp1.cookies}, form2)
735
return resp2.status == 303
736
and (resp2.header["location"] or ""):sub(-#path) == path
737
end
738
})
739
740
table.insert(fingerprints, {
741
name = "ntopng",
742
cpe = "cpe:/a:ntop:ntopng",
743
category = "web",
744
paths = {
745
{path = "/"}
746
},
747
target_check = function (host, port, path, response)
748
local loc = response.header["location"] or ""
749
if not (response.status == 302
750
and loc:find("/lua/login.lua?referer=", 1, true)
751
and get_cookie(response, "session") == "") then
752
return false
753
end
754
local resp = http_get_simple(host, port, loc)
755
return resp.status == 200
756
and resp.body
757
and resp.body:find("ntopng", 1, true)
758
and resp.body:lower():find("<title>welcome to ntopng</title>", 1, true)
759
and get_tag(resp.body, "form", {action="/authorize%.html$"})
760
end,
761
login_combos = {
762
{username = "admin", password = "admin"}
763
},
764
login_check = function (host, port, path, user, pass)
765
local form = {user=user,
766
password=pass,
767
referer=host.name .. path}
768
local resp = http_post_simple(host, port,
769
url.absolute(path, "authorize.html"),
770
nil, form)
771
return resp.status == 302
772
and resp.header["location"] == path
773
and get_cookie(resp, "user") == user
774
end
775
})
776
777
table.insert(fingerprints, {
778
name = "OpenNMS",
779
cpe = "cpe:/a:opennms:opennms",
780
category = "web",
781
paths = {
782
{path = "/login.jsp"},
783
{path = "/opennms/login.jsp"}
784
},
785
target_check = function (host, port, path, response)
786
return response.status == 200
787
and response.body
788
and response.body:find("OpenNMS", 1, true)
789
and response.body:lower():find("<title>%s*opennms web console%s*</title>")
790
and get_tag(response.body, "input", {name="^j_username$"})
791
end,
792
login_combos = {
793
{username = "admin", password = "admin"},
794
{username = "rtc", password = "rtc"}
795
},
796
login_check = function (host, port, path, user, pass)
797
local form = {j_username=user,
798
j_password=pass,
799
j_usergroups="",
800
Login=""}
801
local resp = http_post_simple(host, port,
802
url.absolute(path, "j_spring_security_check"),
803
nil, form)
804
return resp.status == 302
805
and (resp.header["location"] or ""):find("/index%.jsp%f[?\0]")
806
end
807
})
808
809
table.insert(fingerprints, {
810
name = "SevOne NMS",
811
category = "web",
812
paths = {
813
{path = "/"}
814
},
815
target_check = function (host, port, path, response)
816
return response.status == 200
817
and get_cookie(response, "SEVONE")
818
and response.body
819
and response.body:lower():find("<title>sevone nms - network manager", 1, true)
820
end,
821
login_combos = {
822
{username = "Admin", password = "SevOne"},
823
{username = "SevOneStats", password = "n3v3rd13"}
824
},
825
login_check = function (host, port, path, user, pass)
826
local resp1 = http_get_simple(host, port, path)
827
if not (resp1.status == 200 and resp1.body) then return false end
828
local token = resp1.body:match("GlobalData%.Utilities%.Xsrf%.setToken%(%s*['\"](%x+)")
829
if not token then return false end
830
local form = {login=user,
831
passwd=pass,
832
browser="mozilla",
833
version=52,
834
tzString=os.date("!%a %b %d %Y %H:%M:%S GMT+0000"),
835
check_tz=0}
836
local refpath = url.absolute(path, "doms/login/index.php")
837
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=refpath})),
838
["X-CSRFToken"]=token}
839
local resp2 = http_post_simple(host, port,
840
url.absolute(refpath, "processLogin.php"),
841
{cookies=resp1.cookies, header=header}, form)
842
if not (resp2.status == 200 and resp2.body) then return false end
843
local jstatus, jout = json.parse(resp2.body)
844
return jstatus and (jout.status == 0 or jout.status == -3)
845
end
846
})
847
848
table.insert(fingerprints, {
849
name = "Device42 Appliance Manager",
850
category = "web",
851
paths = {
852
{path = "/"}
853
},
854
target_check = function (host, port, path, response)
855
return response.status == 302 and get_cookie(response, "d42amid")
856
end,
857
login_combos = {
858
{username = "d42admin", password = "default"}
859
},
860
login_check = function (host, port, path, user, pass)
861
local lurl = url.absolute(path, "accounts/login/")
862
local resp1 = http_get_simple(host, port, lurl .. "?next=" .. path)
863
if not (resp1.status == 200 and resp1.body) then return false end
864
local form = {csrfmiddlewaretoken=get_cookie(resp1, "d42amid_csrftoken"),
865
username=user,
866
password=pass,
867
next=path}
868
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}
869
local resp2 = http_post_simple(host, port, lurl,
870
{cookies=resp1.cookies, header=header}, form)
871
return resp2.status == 302
872
and (resp2.header["location"] or ""):sub(-#path) == path
873
end
874
})
875
876
table.insert(fingerprints, {
877
name = "Grafana",
878
category = "web",
879
paths = {
880
{path = "/"}
881
},
882
target_check = function (host, port, path, response)
883
return response.status == 302 and get_cookie(response, "grafana_sess")
884
end,
885
login_combos = {
886
{username = "admin", password = "admin"}
887
},
888
login_check = function (host, port, path, user, pass)
889
local header = {["Accept"]="application/json, text/plain, */*",
890
["Content-Type"]="application/json;charset=utf-8"}
891
local jin = {user=user, email="", password=pass}
892
json.make_object(jin)
893
local resp = http_post_simple(host, port, url.absolute(path, "login"),
894
{header=header}, json.generate(jin))
895
return resp.status == 200 and get_cookie(resp, "grafana_user") == user
896
end
897
})
898
899
table.insert(fingerprints, {
900
name = "Apache Ambari",
901
cpe = "cpe:/a:apache:ambari",
902
category = "web",
903
paths = {
904
{path = "/"}
905
},
906
target_check = function (host, port, path, response)
907
return response.status == 200
908
and response.body
909
and response.body:find(">Ambari<", 1, true)
910
and response.body:lower():find("<title>ambari</title>", 1, true)
911
and get_tag(response.body, "script", {src="^javascripts/app%.js$"})
912
end,
913
login_combos = {
914
{username = "admin", password = "admin"}
915
},
916
login_check = function (host, port, path, user, pass)
917
return try_http_auth(host, port, url.absolute(path, "api/v1/users/admin"),
918
user, pass, false)
919
end
920
})
921
922
table.insert(fingerprints, {
923
name = "Cloudera Manager",
924
cpe = "cpe:/a:cloudera:cloudera_manager",
925
category = "web",
926
paths = {
927
{path = "/"}
928
},
929
target_check = function (host, port, path, response)
930
return response.status == 200
931
and get_cookie(response, "CLOUDERA_MANAGER_SESSIONID")
932
end,
933
login_combos = {
934
{username = "admin", password = "admin"}
935
},
936
login_check = function (host, port, path, user, pass)
937
local form = {j_username=user,
938
j_password=pass,
939
returnUrl="",
940
submit=""}
941
local resp = http_post_simple(host, port,
942
url.absolute(path, "j_spring_security_check"),
943
nil, form)
944
return resp.status == 302
945
and (resp.header["location"] or ""):find("/cmf/postLogin%f[?\0]")
946
end
947
})
948
949
table.insert(fingerprints, {
950
name = "OpenDaylight",
951
cpe = "cpe:/a:opendaylight:opendaylight",
952
category = "web",
953
paths = {
954
{path = "/"}
955
},
956
target_check = function (host, port, path, response)
957
return response.status == 200
958
and get_cookie(response, "JSESSIONID", "^%x+$")
959
and response.body
960
and response.body:find("OpenDaylight", 1, true)
961
and response.body:lower():find("<title>opendaylight ", 1, true)
962
and get_tag(response.body, "form", {action="^j_security_check%f[;\0]"})
963
end,
964
login_combos = {
965
{username = "admin", password = "admin"}
966
},
967
login_check = function (host, port, path, user, pass)
968
local resp1 = http_get_simple(host, port, path)
969
if resp1.status ~= 200 then return false end
970
local resp2 = http_post_simple(host, port,
971
url.absolute(path, "j_security_check"),
972
{cookies=resp1.cookies},
973
{j_username=user, j_password=pass})
974
return resp2.status == 302
975
and (resp2.header["location"] or ""):find(path, -#path, true)
976
end
977
})
978
979
table.insert(fingerprints, {
980
name = "OrientDB Studio",
981
cpe = "cpe:/a:orientdb:orientdb",
982
category = "web",
983
paths = {
984
{path = "/"}
985
},
986
target_check = function (host, port, path, response)
987
return response.status == 200
988
and response.body
989
and response.body:find("OrientDB", 1, true)
990
and get_tag(response.body, "meta", {content="^OrientDB Studio$"})
991
and get_refresh_url(response.body, "/studio/index%.html$")
992
end,
993
login_combos = {
994
{username = "reader", password = "reader"},
995
{username = "writer", password = "writer"},
996
{username = "admin", password = "admin"}
997
},
998
login_check = function (host, port, path, user, pass)
999
local resp1 = http_get_simple(host, port, url.absolute(path, "listDatabases"))
1000
if not (resp1.status == 200 and resp1.body) then return false end
1001
local jstatus, jout = json.parse(resp1.body)
1002
if not (jstatus and type(jout.databases) == "table") then return false end
1003
for _, db in ipairs(jout.databases) do
1004
if try_http_auth(host, port,
1005
url.absolute(path, "connect/" .. url.escape(db)),
1006
user, pass, false) then
1007
return true
1008
end
1009
end
1010
return false
1011
end
1012
})
1013
1014
table.insert(fingerprints, {
1015
name = "RockMongo",
1016
cpe = "cpe:/a:rockmongo:rockmongo",
1017
category = "web",
1018
paths = {
1019
{path = "/"}
1020
},
1021
target_check = function (host, port, path, response)
1022
local loc = response.header["location"] or ""
1023
if not (response.status == 302
1024
and loc:find("/index.php?action=login.index", 1, true)) then
1025
return false
1026
end
1027
local resp = http_get_simple(host, port, loc)
1028
return resp.status == 200
1029
and resp.body
1030
and resp.body:find("RockMongo", 1, true)
1031
and resp.body:lower():find("<title>rockmongo</title>")
1032
and get_tag(resp.body, "select", {name="^host$"})
1033
end,
1034
login_combos = {
1035
{username = "admin", password = "admin"}
1036
},
1037
login_check = function (host, port, path, user, pass)
1038
local form = {more=0,
1039
host=0,
1040
username=user,
1041
password=pass,
1042
db="",
1043
lang="en_us",
1044
expire=3}
1045
local resp = http_post_simple(host, port,
1046
url.absolute(path, "index.php?action=login.index&host=0"),
1047
nil, form)
1048
return resp.status == 302
1049
and (resp.header["location"] or ""):find("?action=admin.index", 1, true)
1050
and get_cookie(resp, "ROCK_LANG", "^[%a_]+$")
1051
end
1052
})
1053
1054
table.insert(fingerprints, {
1055
name = "Sambar Server",
1056
cpe = "cpe:/a:sambar:sambar_server",
1057
category = "web",
1058
paths = {
1059
{path = "/"}
1060
},
1061
target_check = function (host, port, path, response)
1062
return response.status == 200
1063
and (response.header["server"] or ""):find("^SAMBAR%f[%s\0]")
1064
end,
1065
login_combos = {
1066
{username = "admin", password = ""},
1067
{username = "anonymous", password = ""},
1068
{username = "billy-bob", password = ""}
1069
},
1070
login_check = function (host, port, path, user, pass)
1071
return try_http_auth(host, port, url.absolute(path, "session/login"),
1072
user, pass, true)
1073
end
1074
})
1075
1076
table.insert(fingerprints, {
1077
name = "WebLogic Server Console",
1078
cpe = "cpe:/a:bea:weblogic_server",
1079
category = "web",
1080
paths = {
1081
{path = "/console/"}
1082
},
1083
target_check = function (host, port, path, response)
1084
return response.status == 302
1085
and (response.header["location"] or ""):find("/console/login/LoginForm%.jsp%f[;\0]")
1086
end,
1087
login_combos = {
1088
{username = "weblogic", password = "weblogic"},
1089
{username = "weblogic", password = "weblogic1"},
1090
{username = "weblogic", password = "welcome1"},
1091
{username = "weblogic", password = "password"},
1092
{username = "system", password = "Passw0rd"},
1093
{username = "system", password = "password"},
1094
{username = "operator", password = "Passw0rd"},
1095
{username = "operator", password = "password"},
1096
{username = "monitor", password = "Passw0rd"},
1097
{username = "monitor", password = "password"},
1098
{username = "oraclesystemuser", password = "Passw0rd"},
1099
{username = "oraclesystemuser", password = "password"}
1100
},
1101
login_check = function (host, port, path, user, pass)
1102
local form = {j_username=user,
1103
j_password=pass,
1104
j_character_encoding="UTF-8"}
1105
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}
1106
local resp = http_post_simple(host, port,
1107
url.absolute(path, "j_security_check"),
1108
{header=header}, form)
1109
if not (resp.status >= 200 and resp.status <= 399) then return false end
1110
if resp.status == 302
1111
and (resp.header["location"] or ""):find("/console/login/LoginForm%.jsp$") then
1112
return false
1113
end
1114
return true
1115
end
1116
})
1117
1118
table.insert(fingerprints, {
1119
name = "WebSphere Community Edition Console",
1120
cpe = "cpe:/a:ibm:websphere_application_server",
1121
category = "web",
1122
paths = {
1123
{path = "/console/"}
1124
},
1125
target_check = function (host, port, path, response)
1126
return response.status == 302
1127
and (response.header["location"] or ""):find("/portal%f[/].-/Welcome%f[?\0]")
1128
end,
1129
login_combos = {
1130
{username = "system", password = "manager"}
1131
},
1132
login_check = function (host, port, path, user, pass)
1133
local resp1 = http_get_simple(host, port, path)
1134
local resource = resp1.header["location"]
1135
if not (resp1.status == 302 and resource) then return false end
1136
local respath = resource:match("%f[/]/%f[^/].*"):gsub("/%.%f[/]", "")
1137
local resp2 = http_get_simple(host, port, respath)
1138
if resp2.status ~= 200 then return false end
1139
local form3 = {j_username=user,
1140
j_password=pass,
1141
submit="Login"}
1142
local resp3 = http_post_simple(host, port,
1143
url.absolute(respath, "j_security_check"),
1144
{cookies=resp2.cookies}, form3)
1145
return resp3.status == 302
1146
and (resp3.header["location"] or ""):find(respath, 1, true)
1147
end
1148
})
1149
1150
table.insert(fingerprints, {
1151
name = "JBoss EAP Admin Console",
1152
cpe = "cpe:/a:redhat:jboss_enterprise_application_platform",
1153
category = "web",
1154
paths = {
1155
{path = "/"}
1156
},
1157
target_check = function (host, port, path, response)
1158
return response.status == 200
1159
and response.body
1160
and response.body:find("/admin-console/", 1, true)
1161
and get_tag(response.body, "a", {href="/admin%-console/$"})
1162
and response.body:lower():find("<title>welcome to jboss", 1, true)
1163
end,
1164
login_combos = {
1165
{username = "admin", password = "admin"}
1166
},
1167
login_check = function (host, port, path, user, pass)
1168
local curl = url.absolute(path, "admin-console/")
1169
local resp1 = http_get_simple(host, port,
1170
url.absolute(curl, "secure/summary.seam"))
1171
local lurl = resp1.header["location"]
1172
if not (resp1.status == 302 and lurl) then return false end
1173
local lpath = lurl:match("%f[/]/%f[^/].*")
1174
local resp2 = http_get_simple(host, port, lpath)
1175
if resp2.status ~= 200 then return false end
1176
local form3 = {login_form="login_form",
1177
["login_form:name"]=user,
1178
["login_form:password"]=pass,
1179
["login_form:submit"]="Login",
1180
["javax.faces.ViewState"]="j_id1"}
1181
local resp3 = http_post_simple(host, port, lpath:gsub("[;?].*$", ""),
1182
{cookies=resp1.cookies}, form3)
1183
return resp3.status == 302
1184
and (resp3.header["location"] or ""):find("/admin-console/secure/summary.seam?conversationId=", 1, true)
1185
end
1186
})
1187
1188
table.insert(fingerprints, {
1189
name = "JBoss JMX Console",
1190
cpe = "cpe:/a:redhat:jboss_enterprise_application_platform",
1191
category = "web",
1192
paths = {
1193
{path = "/"}
1194
},
1195
target_check = function (host, port, path, response)
1196
return response.status == 200
1197
and response.body
1198
and response.body:find("/jmx-console/", 1, true)
1199
and get_tag(response.body, "a", {href="/jmx%-console/$"})
1200
and response.body:lower():find("<title>welcome to jboss", 1, true)
1201
end,
1202
login_combos = {
1203
{username = "admin", password = "admin"}
1204
},
1205
login_check = function (host, port, path, user, pass)
1206
return try_http_auth(host, port, url.absolute(path, "jmx-console/"),
1207
user, pass, false)
1208
end
1209
})
1210
1211
table.insert(fingerprints, {
1212
name = "JBoss Web Console",
1213
cpe = "cpe:/a:redhat:jboss_enterprise_web_platform",
1214
category = "web",
1215
paths = {
1216
{path = "/"}
1217
},
1218
target_check = function (host, port, path, response)
1219
return response.status == 200
1220
and response.body
1221
and response.body:find("/web-console/", 1, true)
1222
and get_tag(response.body, "a", {href="/web%-console/$"})
1223
and response.body:lower():find("<title>welcome to jboss", 1, true)
1224
end,
1225
login_combos = {
1226
{username = "admin", password = "admin"}
1227
},
1228
login_check = function (host, port, path, user, pass)
1229
return try_http_auth(host, port, url.absolute(path, "web-console/"),
1230
user, pass, false)
1231
end
1232
})
1233
1234
table.insert(fingerprints, {
1235
name = "Apache Tomcat Manager",
1236
cpe = "cpe:/a:apache:tomcat",
1237
category = "web",
1238
paths = {
1239
{path = "/manager/html/"},
1240
{path = "/manager/status/"},
1241
{path = "/tomcat/manager/html/"},
1242
{path = "/tomcat/manager/status/"},
1243
{path = "/cognos_express/manager/html/"}
1244
},
1245
target_check = function (host, port, path, response)
1246
return http_auth_realm(response) == "Tomcat Manager Application"
1247
end,
1248
login_combos = {
1249
{username = "tomcat", password = "tomcat"},
1250
{username = "admin", password = "admin"},
1251
{username = "admin", password = ""},
1252
{username = "admin", password = "tomcat"},
1253
{username = "ADMIN", password = "ADMIN"},
1254
{username = "ovwebusr", password = "OvW*busr1"},
1255
{username = "j2deployer", password = "j2deployer"},
1256
{username = "cxsdk", password = "kdsxc"},
1257
{username = "xampp", password = "xampp"},
1258
{username = "QCC", password = "QLogic66"},
1259
{username = "fhir", password = "FHIRDefaultPassword"},
1260
{username = "username", password = "password"},
1261
{username = "username1", password = "password"},
1262
{username = "pippo", password = "paperino"},
1263
{username = "topolino", password = "minnie"},
1264
{username = "root", password = "vagrant"},
1265
{username = "tomcat", password = "s3cret"},
1266
{username = "root", password = "owaspbwa"},
1267
{username = "admin", password = "owaspbwa"}
1268
},
1269
login_check = function (host, port, path, user, pass)
1270
return try_http_auth(host, port, path, user, pass, false)
1271
end
1272
})
1273
1274
table.insert(fingerprints, {
1275
name = "Apache Tomcat Host Manager",
1276
cpe = "cpe:/a:apache:tomcat",
1277
category = "web",
1278
paths = {
1279
{path = "/host-manager/html/"},
1280
{path = "/host-manager/text/"},
1281
{path = "/tomcat/host-manager/html/"},
1282
{path = "/tomcat/host-manager/text/"}
1283
},
1284
target_check = function (host, port, path, response)
1285
return http_auth_realm(response) == "Tomcat Host Manager Application"
1286
end,
1287
login_combos = {
1288
{username = "tomcat", password = "tomcat"},
1289
{username = "admin", password = "admin"},
1290
{username = "admin", password = ""},
1291
{username = "ADMIN", password = "ADMIN"},
1292
{username = "xampp", password = "xampp"},
1293
{username = "QCC", password = "QLogic66"},
1294
{username = "fhir", password = "FHIRDefaultPassword"},
1295
{username = "username", password = "password"},
1296
{username = "pippo", password = "paperino"},
1297
{username = "root", password = "vagrant"},
1298
{username = "tomcat", password = "s3cret"},
1299
{username = "root", password = "owaspbwa"},
1300
{username = "admin", password = "owaspbwa"}
1301
},
1302
login_check = function (host, port, path, user, pass)
1303
return try_http_auth(host, port, path, user, pass, false)
1304
end
1305
})
1306
1307
table.insert(fingerprints, {
1308
name = "Apache ActiveMQ",
1309
cpe = "cpe:/a:apache:activemq",
1310
category = "web",
1311
paths = {
1312
{path = "/admin/"}
1313
},
1314
target_check = function (host, port, path, response)
1315
return http_auth_realm(response) == "ActiveMQRealm"
1316
end,
1317
login_combos = {
1318
{username = "user", password = "user"},
1319
{username = "admin", password = "admin"}
1320
},
1321
login_check = function (host, port, path, user, pass)
1322
return try_http_auth(host, port, path, user, pass, false)
1323
end
1324
})
1325
1326
table.insert(fingerprints, {
1327
name = "Pivotal RabbitMQ",
1328
cpe = "cpe:/a:pivotal_software:rabbitmq",
1329
category = "web",
1330
paths = {
1331
{path = "/"}
1332
},
1333
target_check = function (host, port, path, response)
1334
return response.status == 200
1335
and response.body
1336
and response.body:find("RabbitMQ", 1, true)
1337
and response.body:lower():find("<title>rabbitmq management</title>", 1, true)
1338
and get_tag(response.body, "div", {id="^outer$"})
1339
end,
1340
login_combos = {
1341
{username = "guest", password = "guest"}
1342
},
1343
login_check = function (host, port, path, user, pass)
1344
return try_http_auth(host, port, url.absolute(path, "api/whoami"),
1345
user, pass, false)
1346
end
1347
})
1348
1349
table.insert(fingerprints, {
1350
name = "OSGi Management Console",
1351
category = "web",
1352
paths = {
1353
{path = "/system/console"},
1354
{path = "/lc/system/console"}
1355
},
1356
target_check = function (host, port, path, response)
1357
return http_auth_realm(response) == "OSGi Management Console"
1358
end,
1359
login_combos = {
1360
{username = "admin", password = "admin"},
1361
{username = "karaf", password = "karaf"},
1362
{username = "smx", password = "smx"}
1363
},
1364
login_check = function (host, port, path, user, pass)
1365
return try_http_auth(host, port, path, user, pass, false)
1366
end
1367
})
1368
1369
table.insert(fingerprints, {
1370
name = "Apache Axis2",
1371
cpe = "cpe:/a:apache:axis2",
1372
category = "web",
1373
paths = {
1374
{path = "/axis2/axis2-admin/"}
1375
},
1376
target_check = function (host, port, path, response)
1377
return response.status == 200
1378
and response.body
1379
and response.body:find("Axis2", 1, true)
1380
and response.body:lower():find("<title>login to axis2 :: administration page</title>", 1, true)
1381
end,
1382
login_combos = {
1383
{username = "admin", password = "axis2"}
1384
},
1385
login_check = function (host, port, path, user, pass)
1386
local resp = http_post_simple(host, port, url.absolute(path, "login"), nil,
1387
{userName=user,password=pass,submit=" Login "})
1388
return resp.status == 200
1389
and get_tag(resp.body or "", "a", {href="^axis2%-admin/logout$"})
1390
end
1391
})
1392
1393
table.insert(fingerprints, {
1394
name = "Apache Ofbiz",
1395
cpe = "cpe:/a:apache:ofbiz",
1396
category = "web",
1397
paths = {
1398
{path = "/webtools/"}
1399
},
1400
target_check = function (host, port, path, response)
1401
local loc = response.header["location"] or ""
1402
if not (response.status == 302
1403
and loc:find(url.absolute(path, "control/main"), 1, true)) then
1404
return false
1405
end
1406
local resp = http_get_simple(host, port, loc)
1407
return resp.status == 200
1408
and resp.body
1409
and resp.body:find(url.absolute(loc, "checkLogin"), 1, true)
1410
and resp.body:lower():find("powered by%s+<a%f[%s][^>]-%shref%s*=%s*['\"]https?://ofbiz%.apache%.org%W")
1411
end,
1412
login_combos = {
1413
{username = "admin", password = "ofbiz"}
1414
},
1415
login_check = function (host, port, path, user, pass)
1416
local form = {USERNAME=user,
1417
PASSWORD=pass,
1418
JavaScriptEnabled="Y"}
1419
local resp = http_post_simple(host, port,
1420
url.absolute(path, "control/login"),
1421
nil, form)
1422
return resp.status == 200
1423
and get_cookie(resp, path:match("/([^/]+)/$") .. ".autoUserLoginId") == user
1424
end
1425
})
1426
1427
table.insert(fingerprints, {
1428
name = "Opencast Matterhorn",
1429
category = "web",
1430
paths = {
1431
{path = "/"}
1432
},
1433
target_check = function (host, port, path, response)
1434
local loc = response.header["location"] or ""
1435
if not (response.status == 302
1436
and loc:find("/login%.html%f[;\0]")
1437
and get_cookie(response, "JSESSIONID", "^%w+$")) then
1438
return false
1439
end
1440
local resp = http_get_simple(host, port, loc)
1441
return resp.status == 200
1442
and resp.body
1443
and resp.body:find("Matterhorn", 1, true)
1444
and resp.body:lower():find("<title>opencast matterhorn ", 1, true)
1445
and get_tag(resp.body, "form", {action="/j_spring_security_check$"})
1446
end,
1447
login_combos = {
1448
{username = "admin", password = "opencast"}
1449
},
1450
login_check = function (host, port, path, user, pass)
1451
local form = {j_username=user,
1452
j_password=pass,
1453
submit="Login"}
1454
local resp = http_post_simple(host, port,
1455
url.absolute(path, "j_spring_security_check"),
1456
nil, form)
1457
return resp.status == 302
1458
and (resp.header["location"] or ""):find("/welcome%.html$")
1459
and get_cookie(resp, "JSESSIONID", "^%w+$")
1460
end
1461
})
1462
1463
table.insert(fingerprints, {
1464
name = "Opencast",
1465
category = "web",
1466
paths = {
1467
{path = "/"}
1468
},
1469
target_check = function (host, port, path, response)
1470
return response.status == 302
1471
and (response.header["location"] or ""):find("/admin%-ng/login%.html%f[;\0]")
1472
and get_cookie(response, "JSESSIONID", "^%w+$")
1473
end,
1474
login_combos = {
1475
{username = "admin", password = "opencast"}
1476
},
1477
login_check = function (host, port, path, user, pass)
1478
local resp = http_post_simple(host, port,
1479
url.absolute(path, "admin-ng/j_spring_security_check"),
1480
nil, {j_username=user, j_password=pass})
1481
return resp.status == 302
1482
and (resp.header["location"] or ""):find("/admin%-ng/index%.html$")
1483
and get_cookie(resp, "JSESSIONID", "^%w+$")
1484
end
1485
})
1486
1487
table.insert(fingerprints, {
1488
name = "Plumtree Portal",
1489
category = "web",
1490
paths = {
1491
{path = "/"}
1492
},
1493
target_check = function (host, port, path, response)
1494
return response.status == 302
1495
and (response.header["location"] or ""):find("/portal/server%.pt$")
1496
end,
1497
login_combos = {
1498
{username = "Administrator", password = ""}
1499
},
1500
login_check = function (host, port, path, user, pass)
1501
local form = {in_hi_space="Login",
1502
in_hi_spaceID="0",
1503
in_hi_control="Login",
1504
in_hi_dologin="true",
1505
in_tx_username=user,
1506
in_pw_userpass=pass,
1507
in_se_authsource=""}
1508
local resp = http_post_simple(host, port,
1509
url.absolute(path, "portal/server.pt"),
1510
nil, form)
1511
return resp.status == 302
1512
and (resp.header["location"] or ""):find("/portal/server%.pt[;?]")
1513
and get_cookie(resp, "plloginoccured") == "true"
1514
end
1515
})
1516
1517
table.insert(fingerprints, {
1518
name = "GLPI",
1519
cpe = "cpe:/a:glpi-project:glpi",
1520
category = "web",
1521
paths = {
1522
{path = "/"}
1523
},
1524
target_check = function (host, port, path, response)
1525
return response.status == 200
1526
and response.body
1527
and response.body:find("GLPI", 1, true)
1528
and response.body:lower():find("<title>glpi ", 1, true)
1529
and get_tag(response.body, "input", {name="^login_name$"})
1530
end,
1531
login_combos = {
1532
{username = "glpi", password = "glpi"},
1533
{username = "tech", password = "tech"},
1534
{username = "post-only", password = "postonly"},
1535
{username = "normal", password = "normal"}
1536
},
1537
login_check = function (host, port, path, user, pass)
1538
local resp1 = http_get_simple(host, port, path)
1539
if not (resp1.status == 200 and resp1.body) then return false end
1540
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^_glpi_csrf_token$", value=""})
1541
if not token then return false end
1542
local form2 = {login_name=user,
1543
login_password=pass,
1544
submit="Post",
1545
[token.name]=token.value}
1546
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}
1547
local resp2 = http_post_simple(host, port, url.absolute(path, "login.php"),
1548
{cookies=resp1.cookies, header=header}, form2)
1549
return resp2.status == 200
1550
and (resp2.body or ""):find("%Wwindow%.location%s*=%s*(['\"])[^'\"]-/front/[%w.]+%.php%1")
1551
end
1552
})
1553
1554
table.insert(fingerprints, {
1555
name = "OTRS",
1556
cpe = "cpe:/a:otrs:otrs",
1557
category = "web",
1558
paths = {
1559
{path = "/otrs/"}
1560
},
1561
target_check = function (host, port, path, response)
1562
return response.status == 200
1563
and response.body
1564
and response.body:find("OTRS", 1, true)
1565
and response.body:find(url.absolute(path, "index.pl"), 1, true)
1566
and get_tag(response.body, "input", {name="^requestedurl$"})
1567
end,
1568
login_combos = {
1569
{username = "root@localhost", password = "root"},
1570
{username = "root@localhost", password = "changeme"}
1571
},
1572
login_check = function (host, port, path, user, pass)
1573
local form = {Action="Login",
1574
RequestedURL="",
1575
Lang="en",
1576
TimeOffset=0,
1577
User=user,
1578
Password=pass}
1579
local resp = http_post_simple(host, port, url.absolute(path, "index.pl"),
1580
nil, form)
1581
return resp.status == 302
1582
and get_cookie(resp, "OTRSAgentInterface", "^%w+$")
1583
end
1584
})
1585
1586
table.insert(fingerprints, {
1587
name = "Ilias (var.1)",
1588
cpe = "cpe:/a:ilias:ilias",
1589
category = "web",
1590
paths = {
1591
{path = "/"}
1592
},
1593
target_check = function (host, port, path, response)
1594
return response.status == 302
1595
and get_cookie(response, "ilClientId")
1596
and (response.header["location"] or ""):find("%f[^/\0]login%.php%?.*%f[^?&]client_id=")
1597
end,
1598
login_combos = {
1599
{username = "root", password = "homer"}
1600
},
1601
login_check = function (host, port, path, user, pass)
1602
local resp0 = http_get_simple(host, port, path)
1603
local furl = (resp0.header["location"] or ""):gsub("^https?://[^/]*", "")
1604
if not (resp0.status == 302 and furl:find("%f[^/\0]login%.php%?")) then
1605
return false
1606
end
1607
furl = url.absolute(path, furl)
1608
local resp1 = http_get_simple(host, port, furl, {cookies=resp0.cookies})
1609
if not (resp1.status == 200 and resp1.body) then return false end
1610
local frm = get_tag(resp1.body, "form", {name="^formlogin$", action="[?&;]client_id="})
1611
if not frm then return false end
1612
local form = {username=user,
1613
password=pass,
1614
["cmd[doStandardAuthentication]"]="Anmelden"}
1615
local resp2 = http_post_simple(host, port,
1616
url.absolute(furl, xmldecode(frm.action)),
1617
{cookies=resp0.cookies}, form)
1618
return resp2.status == 302
1619
and (resp2.header["location"] or ""):find("/ilias%.php?%?")
1620
end
1621
})
1622
1623
table.insert(fingerprints, {
1624
name = "Ilias (var.2)",
1625
cpe = "cpe:/a:ilias:ilias",
1626
category = "web",
1627
paths = {
1628
{path = "/"}
1629
},
1630
target_check = function (host, port, path, response)
1631
return response.status == 302
1632
and get_cookie(response, "ilClientId")
1633
and (response.header["location"] or ""):find("%f[^/\0]ilias%.php%f[?\0]")
1634
end,
1635
login_combos = {
1636
{username = "root", password = "homer"}
1637
},
1638
login_check = function (host, port, path, user, pass)
1639
local resp0 = http_get_simple(host, port, path)
1640
if resp0.status ~= 302 then return false end
1641
local form1 = {target="",
1642
client_id=get_cookie(resp0, "ilClientId"),
1643
cmd="force_login",
1644
lang="en"}
1645
local furl = url.absolute(path, "login.php?" .. url.build_query(form1))
1646
local resp1 = http_get_simple(host, port, furl, {cookies=resp0.cookies})
1647
if not (resp1.status == 200 and resp1.body) then return false end
1648
local frm = get_tag(resp1.body, "form", {name="^formlogin$", action="[?&;]client_id="})
1649
if not frm then return false end
1650
local form = {username=user,
1651
password=pass,
1652
["cmd[doStandardAuthentication]"]="Anmelden"}
1653
local resp2 = http_post_simple(host, port,
1654
url.absolute(furl, xmldecode(frm.action)),
1655
{cookies=resp0.cookies}, form)
1656
return resp2.status == 302
1657
and (resp2.header["location"] or ""):find("/ilias%.php?%?")
1658
end
1659
})
1660
1661
table.insert(fingerprints, {
1662
name = "Jitamin",
1663
category = "web",
1664
paths = {
1665
{path = "/"}
1666
},
1667
target_check = function (host, port, path, response)
1668
return response.status == 302
1669
and (response.header["location"] or ""):find("%?controller=Auth/AuthController&action=login$")
1670
and get_cookie(response, "JM_SID")
1671
end,
1672
login_combos = {
1673
{username = "admin", password = "admin"},
1674
{username = "[email protected]", password = "admin"}
1675
},
1676
login_check = function (host, port, path, user, pass)
1677
local lurl = path .. "?controller=Auth/AuthController&action="
1678
local resp1 = http_get_simple(host, port, lurl .. "login")
1679
if not (resp1.status == 200 and resp1.body) then return false end
1680
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrf_token$", value=""})
1681
if not token then return false end
1682
local form = {[token.name]=token.value,
1683
username=user,
1684
password=pass}
1685
local resp2 = http_post_simple(host, port, lurl .. "check",
1686
{cookies=resp1.cookies}, form)
1687
return resp2.status == 302
1688
and (resp2.header["location"] or ""):find("%?controller=Dashboard/DashboardController&action=index$")
1689
end
1690
})
1691
1692
table.insert(fingerprints, {
1693
name = "Kanboard",
1694
cpe = "cpe:/a:kanboard:kanboard",
1695
category = "web",
1696
paths = {
1697
{path = "/"},
1698
{path = "/kanboard/"}
1699
},
1700
target_check = function (host, port, path, response)
1701
return response.status == 302
1702
and (response.header["location"] or ""):find("%?controller=AuthController&action=login$")
1703
and get_cookie(response, "KB_SID")
1704
end,
1705
login_combos = {
1706
{username = "admin", password = "admin"}
1707
},
1708
login_check = function (host, port, path, user, pass)
1709
local lurl = path .. "?controller=AuthController&action="
1710
local resp1 = http_get_simple(host, port, lurl .. "login")
1711
if not (resp1.status == 200 and resp1.body) then return false end
1712
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrf_token$", value=""})
1713
if not token then return false end
1714
local form = {[token.name]=token.value,
1715
username=user,
1716
password=pass}
1717
local resp2 = http_post_simple(host, port, lurl .. "check",
1718
{cookies=resp1.cookies}, form)
1719
return resp2.status == 302
1720
and (resp2.header["location"] or ""):find("%?controller=DashboardController&action=show$")
1721
end
1722
})
1723
1724
table.insert(fingerprints, {
1725
name = "RainLoop Webmail",
1726
category = "web",
1727
paths = {
1728
{path = "/"},
1729
{path = "/rainloop/"},
1730
{path = "/webmail/"}
1731
},
1732
target_check = function (host, port, path, response)
1733
return response.status == 200
1734
and response.body
1735
and response.body:find("rainloop/v/", 1, true)
1736
and get_tag(response.body, "link", {href="^rainloop/v/%d[%d.]+%d/static/css/app%.min%.css%f[?\0]"})
1737
end,
1738
login_combos = {
1739
{username = "admin", password = "12345"}
1740
},
1741
login_check = function (host, port, path, user, pass)
1742
local resp1 = http_get_simple(host, port, path .. "?/AdminAppData")
1743
if not (resp1.status == 200 and resp1.body) then return false end
1744
local jstr = resp1.body:match('{[^{]*"Auth"%s*:.*"PluginsLink"%s*:[^}]*}')
1745
local jstatus, jout = json.parse(jstr or "{}")
1746
local token = jstatus and (jout.Token or jout.System and jout.System.token)
1747
if not token then return false end
1748
local form2 = {Login=user,
1749
Password=pass,
1750
Action="AdminLogin",
1751
XToken=token}
1752
local resp2 = http_post_simple(host, port, path .. "?/Ajax/&q[]=/0/",
1753
{cookies = resp1.cookies}, form2)
1754
if not (resp2.status == 200 and resp2.body) then return false end
1755
jstatus, jout = json.parse(resp2.body)
1756
return jstatus and jout.Action == "AdminLogin" and jout.Result
1757
end
1758
})
1759
1760
table.insert(fingerprints, {
1761
name = "TeamPass",
1762
cpe = "cpe:/a:teampass:teampass",
1763
category = "web",
1764
paths = {
1765
{path = "/"},
1766
{path = "/teampass/"},
1767
{path = "/TeamPass/"}
1768
},
1769
target_check = function (host, port, path, response)
1770
return have_openssl
1771
and tableaux.contains(openssl.supported_ciphers(), "aes-256-ecb")
1772
and tableaux.contains(openssl.supported_ciphers(), "aes-256-ctr")
1773
and response.status == 200
1774
and response.body
1775
and response.body:find("TeamPass", 1, true)
1776
and response.body:find("(['\"])sources/main%.queries%.php%1")
1777
end,
1778
login_combos = {
1779
{username = "admin", password = "admin"}
1780
},
1781
login_check = function (host, port, path, user, pass)
1782
local resp1 = http_get_simple(host, port, path)
1783
if not (resp1.status == 200 and resp1.body) then return false end
1784
local lurl = resp1.body:match("['\"]([^'\"]+)['\"]%s*,%s*{%s*type%s*:%s*['\"]identify_user['\"]")
1785
local aespwd = resp1.body:match("%Wreturn%s+Aes%.Ctr%.encrypt%s*%(%s*%w+%s*,%s*['\"](.-)['\"]%s*,%s*256%s*%)")
1786
or resp1.body:match("['\"]identify_user['\"]%s*,%s*data%s*:%s*prepareExchangedData%(%s*%w+%s*,%s*['\"]encode['\"]%s*,%s*['\"](.-)['\"]")
1787
if not (lurl and aespwd) then return false end
1788
aespwd = aespwd .. ("\0"):rep(32-#aespwd)
1789
local aeskey = openssl.encrypt("aes-256-ecb", aespwd, nil, aespwd):sub(1, 16):rep(2)
1790
local nonce = ("<I4"):pack(math.floor(stdnse.clock_ms() / 1000))
1791
.. string.char(math.random(0, 255)):rep(4)
1792
local randstr = random_alnum(10)
1793
local jin = {login=user,
1794
pw=pass,
1795
duree_session="60",
1796
screenHeight=tostring(math.random(480, 1024)),
1797
randomstring=randstr}
1798
json.make_object(jin)
1799
local ctext = base64.enc(nonce .. openssl.encrypt("aes-256-ctr", aeskey, nonce .. ("\0"):rep(8), json.generate(jin)))
1800
local resp2 = http_post_simple(host, port, url.absolute(path, lurl),
1801
{cookies = resp1.cookies},
1802
{type="identify_user",data=ctext})
1803
if not (resp2.status == 200 and resp2.body) then return false end
1804
local jstatus, jout = json.parse(resp2.body)
1805
return jstatus and jout[1] and jout[1].value == randstr
1806
end
1807
})
1808
1809
table.insert(fingerprints, {
1810
name = "CapeSoft TimeClock",
1811
category = "web",
1812
paths = {
1813
{path = "/"}
1814
},
1815
target_check = function (host, port, path, response)
1816
return response.status == 200
1817
and response.body
1818
and response.body:find("TimeClock", 1, true)
1819
and response.body:lower():find("<title>capesoft time clock web ", 1, true)
1820
and response.body:lower():find("%Whref%s*=%s*(['\"])employees%.php%1")
1821
end,
1822
login_combos = {
1823
{username = "9970", password = "password"}
1824
},
1825
login_check = function (host, port, path, user, pass)
1826
local resp = http_post_simple(host, port,
1827
url.absolute(path, "employees.php"), nil,
1828
{login=user,password=pass,action="Login"})
1829
return resp.status == 200
1830
and (resp.body or ""):find("%sclass%s*=%s*(['\"]?)logout%1[%s>]")
1831
end
1832
})
1833
1834
table.insert(fingerprints, {
1835
name = "BeEF",
1836
category = "web",
1837
paths = {
1838
{path = "/ui/authentication/"}
1839
},
1840
target_check = function (host, port, path, response)
1841
return response.status == 200
1842
and response.body
1843
and response.body:find("BeEF", 1, true)
1844
and response.body:lower():find("<title>beef authentication</title>", 1, true)
1845
end,
1846
login_combos = {
1847
{username = "beef", password = "beef"}
1848
},
1849
login_check = function (host, port, path, user, pass)
1850
local resp = http_post_simple(host, port, url.absolute(path, "login"), nil,
1851
{["username-cfrm"]=user, ["password-cfrm"]=pass})
1852
return resp.status == 200
1853
and (resp.body or ""):find("{%s*success%s*:%s*true%s*}")
1854
end
1855
})
1856
1857
table.insert(fingerprints, {
1858
name = "Greenbone Security Assistant",
1859
cpe = "cpe:/a:greenbone:greenbone_security_assistant",
1860
category = "web",
1861
paths = {
1862
{path = "/"}
1863
},
1864
target_check = function (host, port, path, response)
1865
local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")
1866
if not (response.status == 303
1867
and loc:find("/login/login%.html$")) then
1868
return false
1869
end
1870
local resp = http_get_simple(host, port, loc)
1871
return resp.status == 200
1872
and resp.body
1873
and resp.body:find("Greenbone", 1, true)
1874
and resp.body:lower():find("<title>greenbone security assistant</title>", 1, true)
1875
and get_tag(resp.body, "form", {action="/omp$"})
1876
end,
1877
login_combos = {
1878
{username = "admin", password = "admin"},
1879
{username = "sadmin", password = "changeme"}
1880
},
1881
login_check = function (host, port, path, user, pass)
1882
local lurl = url.absolute(path, "omp")
1883
local form = {cmd="login",
1884
text=lurl.."?r=1",
1885
login=user,
1886
password=pass}
1887
local resp = http_post_simple(host, port, lurl, nil, form)
1888
return resp.status == 303
1889
and (resp.header["location"] or ""):find("/omp%?.*%f[^?&]token=")
1890
end
1891
})
1892
1893
table.insert(fingerprints, {
1894
name = "Sagitta Hashstack",
1895
category = "web",
1896
paths = {
1897
{path = "/"}
1898
},
1899
target_check = function (host, port, path, response)
1900
local lurl = (response.header["location"] or ""):gsub("^https?://[^/]*", "")
1901
if not (response.status == 302 and lurl:find("/login$")) then
1902
return false
1903
end
1904
local resp = http_get_simple(host, port, lurl)
1905
return resp.status == 200
1906
and resp.body
1907
and resp.body:find("hashstack", 1, true)
1908
and resp.body:lower():find("<title>hashstack - login</title>", 1, true)
1909
and get_tag(resp.body, "form", {class="^form%-signin$"})
1910
end,
1911
login_combos = {
1912
{username = "admin", password = "admin"}
1913
},
1914
login_check = function (host, port, path, user, pass)
1915
local header = {["Accept"]="application/json, text/plain, */*",
1916
["Content-Type"]="application/json"}
1917
local jin = {username=user, password=pass}
1918
json.make_object(jin)
1919
local resp = http_post_simple(host, port, url.absolute(path, "login"),
1920
{header=header}, json.generate(jin))
1921
return resp.status == 200 and get_cookie(resp, "sid", ".")
1922
end
1923
})
1924
1925
table.insert(fingerprints, {
1926
name = "ZKSoftware WebServer",
1927
category = "web",
1928
paths = {
1929
{path = "/"}
1930
},
1931
target_check = function (host, port, path, response)
1932
return response.status == 200
1933
and response.header["server"] == "ZK Web Server"
1934
and response.body
1935
and response.body:find("%Wlocation%.href%s*=%s*(['\"])[^'\"]-/csl/login%1")
1936
end,
1937
login_combos = {
1938
{username = "administrator", password = "123456"}
1939
},
1940
login_check = function (host, port, path, user, pass)
1941
local resp1 = http_get_simple(host, port, path)
1942
if not (resp1.status == 200) then return false end
1943
local resp2 = http_post_simple(host, port, url.absolute(path, "csl/check"),
1944
{cookies=resp1.cookies},
1945
{username=user, userpwd=pass})
1946
return resp2.status == 200
1947
and get_tag(resp2.body or "", "frame", {src="/csl/menu$"})
1948
end
1949
})
1950
1951
table.insert(fingerprints, {
1952
name = "ComfortableMexicanSofa",
1953
category = "web",
1954
paths = {
1955
{path = "/admin/"}
1956
},
1957
target_check = function (host, port, path, response)
1958
if not (response.status == 302 and response.body) then return false end
1959
local loc = response.header["location"] or ""
1960
local _, pos = loc:find(url.absolute(path, "sites/"), 1, true)
1961
if not pos then return false end
1962
loc = loc:sub(pos)
1963
if not (loc == "/new" or loc:find("^/%d+/")) then return false end
1964
for _, ck in ipairs(response.cookies or {}) do
1965
if ck.name:find("_session$") then return ck.value:find("%-%-%x+$") end
1966
end
1967
return false
1968
end,
1969
login_combos = {
1970
{username = "username", password = "password"}
1971
},
1972
login_check = function (host, port, path, user, pass)
1973
return try_http_auth(host, port, url.absolute(path, "sites/new"),
1974
user, pass, false)
1975
end
1976
})
1977
1978
table.insert(fingerprints, {
1979
name = "Hippo CMS",
1980
category = "web",
1981
paths = {
1982
{path = "/"},
1983
{path = "/cms/"}
1984
},
1985
target_check = function (host, port, path, response)
1986
return response.status == 200
1987
and response.body
1988
and response.body:find("hippo-login", 1, true)
1989
and get_tag(response.body, "input", {name="^id2_hf_0$"})
1990
end,
1991
login_combos = {
1992
{username = "admin", password = "admin"},
1993
{username = "editor", password = "editor"},
1994
{username = "author", password = "author"}
1995
},
1996
login_check = function (host, port, path, user, pass)
1997
local lurl;
1998
local resp1 = http_get_simple(host, port, path)
1999
if not (resp1.status == 200 and resp1.body) then return false end
2000
local submit = get_tag(resp1.body, "input", {name="^:submit$", onclick=""})
2001
if submit then
2002
local qry = submit.onclick:match("=%s*wicketSubmitFormById%(['\"]id%d+['\"],%s*['\"](.-)['\"]")
2003
if not qry then return false end
2004
lurl = xmldecode(qry) .. "&random=" .. math.random()
2005
else
2006
local frm = get_tag(resp1.body, "form", {name="^signInForm$", action=""})
2007
if not frm then return false end
2008
lurl = frm.action
2009
end
2010
local form = {id2_hf_0="",
2011
username=user,
2012
password=pass,
2013
locale="en",
2014
[":submit"]="log in"}
2015
local resp2 = http_post_simple(host, port, url.absolute(path, lurl),
2016
{cookies=resp1.cookies}, form)
2017
return resp2.status == 302
2018
and (resp2.header["location"] or ""):sub(-#path) == path
2019
end
2020
})
2021
2022
---
2023
--ROUTERS
2024
---
2025
table.insert(fingerprints, {
2026
name = "Cisco IOS",
2027
cpe = "cpe:/o:cisco:ios",
2028
category = "routers",
2029
paths = {
2030
{path = "/"},
2031
},
2032
target_check = function (host, port, path, response)
2033
local realm = http_auth_realm(response) or ""
2034
return realm:gsub("_"," "):find("^level 15?%f[ ].* access$")
2035
end,
2036
login_combos = {
2037
{username = "", password = ""},
2038
{username = "cisco", password = "cisco"},
2039
{username = "Cisco", password = "Cisco"}
2040
},
2041
login_check = function (host, port, path, user, pass)
2042
return try_http_auth(host, port, path, user, pass, false)
2043
end
2044
})
2045
2046
table.insert(fingerprints, {
2047
name = "Cisco Small Business 200",
2048
category = "routers",
2049
paths = {
2050
{path = "/"}
2051
},
2052
target_check = function (host, port, path, response)
2053
return response.status == 200
2054
and response.body
2055
and response.body:find("/nikola_login.html", 1, true)
2056
and response.body:lower():find("<title>switch</title>", 1, true)
2057
end,
2058
login_combos = {
2059
{username = "cisco", password = "cisco"}
2060
},
2061
login_check = function (host, port, path, user, pass)
2062
local form = {uname=user,
2063
pwd2=base64.enc(pass),
2064
language_selector="en-US",
2065
err_flag=0,
2066
err_msg="",
2067
passpage="nikola_main2.html",
2068
failpage="nikola_login.html",
2069
submit_flag=0}
2070
local resp = http_post_simple(host, port,
2071
url.absolute(path, "nikola_login.html"),
2072
nil, form)
2073
return resp.status == 200 and get_cookie(resp, "SID", ".")
2074
end
2075
})
2076
2077
table.insert(fingerprints, {
2078
name = "Cisco Linksys",
2079
cpe = "cpe:/h:linksys:*",
2080
category = "routers",
2081
paths = {
2082
{path = "/"}
2083
},
2084
target_check = function (host, port, path, response)
2085
local realm = http_auth_realm(response) or ""
2086
return realm:find("^Linksys %u[%u%d]+%s*$")
2087
or realm:find("^WRT54GC%w*$")
2088
or realm == "NR041"
2089
end,
2090
login_combos = {
2091
{username = "", password = "admin"},
2092
{username = "admin", password = "admin"},
2093
},
2094
login_check = function (host, port, path, user, pass)
2095
return try_http_auth(host, port, path, user, pass, false)
2096
end
2097
})
2098
2099
table.insert(fingerprints, {
2100
name = "Cisco DPC3848VM",
2101
cpe = "cpe:/h:cisco:dpc3848vm",
2102
category = "routers",
2103
paths = {
2104
{path = "/"}
2105
},
2106
target_check = function (host, port, path, response)
2107
return response.status == 302
2108
and response.header["location"] == "Docsis_system.php"
2109
end,
2110
login_combos = {
2111
{username = "user", password = ""},
2112
{username = "", password = ""}
2113
},
2114
login_check = function (host, port, path, user, pass)
2115
local form = {username_login=user,
2116
password_login=pass,
2117
LanguageSelect="en",
2118
login="Log In"}
2119
local resp = http_post_simple(host, port, url.absolute(path, "check.php"),
2120
nil, form)
2121
if not (resp.status == 200 and resp.body) then return false end
2122
local lstatus = resp.body:match("%Wvar%s+login_status%s*=%s*(%-?%d+)")
2123
return tonumber(lstatus or "99") <= 0
2124
end
2125
})
2126
2127
table.insert(fingerprints, {
2128
name = "Cisco EPC3925",
2129
cpe = "cpe:/h:cisco:epc3925",
2130
category = "routers",
2131
paths = {
2132
{path = "/"}
2133
},
2134
target_check = function (host, port, path, response)
2135
return response.status == 200
2136
and response.body
2137
and response.body:find("Docsis", 1, true)
2138
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])Docsis_system%.asp%1")
2139
end,
2140
login_combos = {
2141
{username = "", password = ""}
2142
},
2143
login_check = function (host, port, path, user, pass)
2144
local form = {username_login=user,
2145
password_login=pass,
2146
LanguageSelect="en",
2147
Language_Submit="0",
2148
login="Log In"}
2149
local resp = http_post_simple(host, port,
2150
url.absolute(path, "goform/Docsis_system"),
2151
nil, form)
2152
return resp.status == 302
2153
and (resp.header["location"] or ""):find("/Quick_setup%.asp$")
2154
end
2155
})
2156
2157
table.insert(fingerprints, {
2158
name = "Cisco Configuration Utility (var.1)",
2159
category = "routers",
2160
paths = {
2161
{path = "/"}
2162
},
2163
target_check = function (host, port, path, response)
2164
return have_openssl
2165
and response.status == 200
2166
and response.body
2167
and response.body:find("cisco", 1, true)
2168
and response.body:find("%Wfunction%s+en_value%s*%(")
2169
and get_tag(response.body, "input", {name="^keep_name$"})
2170
end,
2171
login_combos = {
2172
{username = "cisco", password = "cisco"}
2173
},
2174
login_check = function (host, port, path, user, pass)
2175
pass = ("%s%02d"):format(pass, #pass)
2176
pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)
2177
local form = {submit_button="login",
2178
keep_name=0,
2179
enc=1,
2180
user=user,
2181
pwd=stdnse.tohex(openssl.md5(pass))}
2182
local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),
2183
nil, form)
2184
return resp.status == 200
2185
and (resp.body or ""):find("%Wvar%s+session_key%s*=%s*(['\"])%x*%1%s*;")
2186
end
2187
})
2188
2189
table.insert(fingerprints, {
2190
name = "Cisco Configuration Utility (var.2)",
2191
category = "routers",
2192
paths = {
2193
{path = "/"}
2194
},
2195
target_check = function (host, port, path, response)
2196
return have_openssl
2197
and response.status == 200
2198
and response.body
2199
and response.body:find("cisco", 1, true)
2200
and response.body:find("%Wfunction%s+en_value%s*%(")
2201
and get_tag(response.body, "input", {name="^gui_action$"})
2202
end,
2203
login_combos = {
2204
{username = "cisco", password = "cisco"}
2205
},
2206
login_check = function (host, port, path, user, pass)
2207
pass = ("%s%02d"):format(pass, #pass)
2208
pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)
2209
local form = {submit_button="login",
2210
submit_type="",
2211
gui_action="",
2212
wait_time=0,
2213
change_action="",
2214
enc=1,
2215
user=user,
2216
pwd=stdnse.tohex(openssl.md5(pass)),
2217
sel_lang="EN"}
2218
local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),
2219
nil, form)
2220
return resp.status == 200
2221
and get_tag(resp.body or "", "input", {name="^session_key$", value="^%x+$"})
2222
end
2223
})
2224
2225
table.insert(fingerprints, {
2226
name = "Cisco Router Access",
2227
category = "routers",
2228
paths = {
2229
{path = "/"}
2230
},
2231
target_check = function (host, port, path, response)
2232
return have_openssl
2233
and response.status == 200
2234
and response.body
2235
and response.body:find("%Wvar%s+nonce%s*=%s*(['\"])%x+%1")
2236
and response.body:find("%Wfunction%s+en_value%s*%(")
2237
and get_tag(response.body, "input", {name="^gui_action$"})
2238
end,
2239
login_combos = {
2240
{username = "", password = "admin"}
2241
},
2242
login_check = function (host, port, path, user, pass)
2243
local resp1 = http_get_simple(host, port, path)
2244
if not (resp1.status == 200 and resp1.body) then return false end
2245
local nonce = resp1.body:match("%Wvar%s+nonce%s*=%s*['\"](%x+)['\"]")
2246
if not nonce then return false end
2247
pass = ("%s%02d"):format(pass, #pass)
2248
pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)
2249
pass = stdnse.tohex(openssl.md5(pass))
2250
local wait_time = get_tag(resp1.body, "input", {name="^wait_time$"})
2251
local form = {submit_button="login",
2252
change_action="",
2253
gui_action="Apply",
2254
wait_time=wait_time and wait_time.value or "",
2255
submit_type="",
2256
http_username=user,
2257
http_passwd=stdnse.tohex(openssl.md5(pass .. nonce))}
2258
local resp2 = http_post_simple(host, port, url.absolute(path, "login.cgi"),
2259
nil, form)
2260
return resp2.status == 200
2261
and (resp2.body or ""):find(";session_id=%x+%W")
2262
end
2263
})
2264
2265
table.insert(fingerprints, {
2266
name = "Cisco IronPort",
2267
category = "routers",
2268
paths = {
2269
{path = "/"}
2270
},
2271
target_check = function (host, port, path, response)
2272
return response.status == 303
2273
and (response.header["server"] or ""):find("^glass/%d+%.")
2274
and (response.header["location"] or ""):find("/login%f[?\0]")
2275
and get_cookie(response, "sid", "^%w+$")
2276
end,
2277
login_combos = {
2278
{username = "admin", password = "ironport"}
2279
},
2280
login_check = function (host, port, path, user, pass)
2281
local refpath = url.absolute(path, "default")
2282
local form = {referrer=url.build(url_build_defaults(host, port, {path=refpath})),
2283
screen="login",
2284
username=user,
2285
password=pass,
2286
action="Login"}
2287
local resp = http_post_simple(host, port, url.absolute(path, "login"),
2288
nil, form)
2289
return resp.status == 303
2290
and (get_cookie(resp, "euq_authenticated", "^%w+$")
2291
or get_cookie(resp, "authenticated", "^%w+$"))
2292
end
2293
})
2294
2295
table.insert(fingerprints, {
2296
name = "Allied Telesis AR",
2297
cpe = "cpe:/h:alliedtelesyn:cable_dsl_router_at-ar*",
2298
category = "routers",
2299
paths = {
2300
{path = "/"}
2301
},
2302
target_check = function (host, port, path, response)
2303
local realm = http_auth_realm(response) or ""
2304
return realm:find("^Allied Telesis ")
2305
or realm:find("^Allied Telesyn ")
2306
or realm:find("^CentreCOM ")
2307
end,
2308
login_combos = {
2309
{username = "manager", password = "friend"}
2310
},
2311
login_check = function (host, port, path, user, pass)
2312
return try_http_auth(host, port, path, user, pass, false)
2313
end
2314
})
2315
2316
table.insert(fingerprints, {
2317
name = "HP ProCurve Switch",
2318
cpe = "cpe:/h:hp:procurve_switch",
2319
category = "routers",
2320
paths = {
2321
{path = "/"}
2322
},
2323
target_check = function (host, port, path, response)
2324
return response.status == 200
2325
and (response.header["server"] or ""):lower():find("^ehttp[/%s]")
2326
and response.body
2327
and response.body:find("ProCurve Switch", 1, true)
2328
and (response.body:find("%Wdocument%.location%s*=%s*(['\"])home%.html%1")
2329
or get_tag(response.body, "frame", {src="^nctabs%.html$"}))
2330
end,
2331
login_combos = {
2332
{username = "", password = ""}
2333
},
2334
login_check = function (host, port, path, user, pass)
2335
return try_http_auth(host, port,
2336
url.absolute(path, "security/web_access.html"),
2337
user, pass, false)
2338
end
2339
})
2340
2341
table.insert(fingerprints, {
2342
name = "Huawei USG",
2343
cpe = "cpe:/h:huawei:usg*",
2344
category = "routers",
2345
paths = {
2346
{path = "/"}
2347
},
2348
target_check = function (host, port, path, response)
2349
return response.status == 200
2350
and get_cookie(response, "SESSIONID", "&Huawei")
2351
end,
2352
login_combos = {
2353
{username = "admin", password = "Admin@123"},
2354
{username = "audit-admin", password = "Admin@123"}
2355
},
2356
login_check = function (host, port, path, user, pass)
2357
local resp1 = http_get_simple(host, port, path)
2358
local cookie
2359
for _, ck in ipairs(resp1.cookies or {}) do
2360
if ck.name == "SESSIONID" then
2361
cookie = "SESSIONID=" .. ck.value
2362
if not ck.httponly then
2363
cookie = cookie:match("^(.-)&")
2364
end
2365
break
2366
end
2367
end
2368
if not (resp1.status == 200 and cookie) then return false end
2369
local form = {["spring-security-redirect"]="",
2370
password=pass,
2371
language="en",
2372
lang="English",
2373
username=user,
2374
platcontent=""}
2375
local lurl = url.absolute(path, "default.html?dc=" .. math.floor(stdnse.clock_ms()))
2376
local resp2 = http_post_simple(host, port, lurl, {cookies=cookie}, form)
2377
return resp2.status == 200
2378
and (resp2.body or ""):find("top.location.replace(localHref)", 1, true)
2379
end
2380
})
2381
2382
table.insert(fingerprints, {
2383
name = "Moxa AirWorks",
2384
category = "routers",
2385
paths = {
2386
{path = "/Login.asp"}
2387
},
2388
target_check = function (host, port, path, response)
2389
return have_openssl
2390
and response.status == 200
2391
and response.body
2392
and response.body:find("Moxa AWK", 1, true)
2393
and response.body:find("/webNonce%W")
2394
and get_tag(response.body, "form", {action="/home%.asp$"})
2395
end,
2396
login_combos = {
2397
{username = "admin", password = "root"}
2398
},
2399
login_check = function (host, port, path, user, pass)
2400
local resp1 = http_get_simple(host, port, url.absolute(path, "Login.asp"))
2401
if not (resp1.status == 200 and resp1.body) then return false end
2402
local pcookie = resp1.body:match("%Wfunction%s+SetCookie%W[^}]-theName%s*=%s*['\"](.-)[='\"]")
2403
if not pcookie then return false end
2404
local form2 = {user=user, time=math.floor(stdnse.clock_ms())}
2405
local url2 = url.absolute(path, "webNonce?" .. url.build_query(form2))
2406
local resp2 = http_get_simple(host, port, url2,
2407
{cookies={{name=pcookie, value=""}}})
2408
if not (resp2.status == 200 and resp2.body) then return false end
2409
local cpass = stdnse.tohex(openssl.md5(pass .. resp2.body))
2410
local form3 = {Username=user,
2411
Password="",
2412
["Submit.x"]=0,
2413
["Submit.y"]=0}
2414
local resp3 = http_post_simple(host, port, url.absolute(path, "home.asp"),
2415
{cookies={{name=pcookie, value=cpass}}},
2416
form3)
2417
return resp3.status == 200
2418
and get_tag(resp3.body or "", "frame", {src="^main%.asp$"})
2419
end
2420
})
2421
2422
table.insert(fingerprints, {
2423
name = "Moxa EDR (var.1)",
2424
cpe = "cpe:/o:moxa:edr_g903_firmware",
2425
category = "routers",
2426
paths = {
2427
{path = "/Login.asp"}
2428
},
2429
target_check = function (host, port, path, response)
2430
return have_openssl
2431
and response.status == 200
2432
and response.body
2433
and response.body:find("Moxa EDR", 1, true)
2434
and response.body:find(">iGenSel2%((['\"])Username%1")
2435
and response.body:find("%Wdocument%.getElementById%(%s*(['\"])Username%1%s*%)%.value%s*%+%s*(['\"]):%2")
2436
end,
2437
login_combos = {
2438
{username = "admin", password = ""},
2439
{username = "user", password = ""}
2440
},
2441
login_check = function (host, port, path, user, pass)
2442
local cpass = stdnse.tohex(openssl.md5(#pass > 0 and pass or "NULL"))
2443
local cookies = {{name="admin:EDR", value=(user=="admin" and cpass or "")},
2444
{name="user:EDR", value=(user=="user" and cpass or "")}}
2445
local form1 = {Username=user,
2446
Password=pass,
2447
["Submit.x"]=0,
2448
["Submit.y"]=0}
2449
local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),
2450
{cookies=cookies}, form1)
2451
if resp1.status~=200 then return false end
2452
local resp2 = http_get_simple(host, port, url.absolute(path, "index.asp"),
2453
{cookies=cookies})
2454
return resp2.status == 200
2455
and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})
2456
end
2457
})
2458
2459
table.insert(fingerprints, {
2460
name = "Moxa EDR (var.2)",
2461
cpe = "cpe:/o:moxa:edr_g903_firmware",
2462
category = "routers",
2463
paths = {
2464
{path = "/Login.asp"}
2465
},
2466
target_check = function (host, port, path, response)
2467
return have_openssl
2468
and response.status == 200
2469
and response.body
2470
and response.body:find("Moxa EDR", 1, true)
2471
and response.body:find(">iGenSel2%((['\"])Username%1")
2472
and response.body:find("%Wdocument%.getElementById%(%s*(['\"])Username%1%s*%)%.value%s*;")
2473
end,
2474
login_combos = {
2475
{username = "admin", password = ""},
2476
{username = "user", password = ""}
2477
},
2478
login_check = function (host, port, path, user, pass)
2479
local cuser = #user > 0 and user or "unknown"
2480
local cpass = #pass > 0 and pass or "NULL"
2481
local cookies = {{name="NAME", value=url.escape(cuser)},
2482
{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}
2483
local form1 = {Username=user,
2484
Password=pass,
2485
["Submit.x"]=0,
2486
["Submit.y"]=0}
2487
local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),
2488
{cookies=cookies}, form1)
2489
if resp1.status~=200 then return false end
2490
local resp2 = http_get_simple(host, port, url.absolute(path, "home.asp"),
2491
{cookies=cookies})
2492
return resp2.status == 200
2493
and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})
2494
end
2495
})
2496
2497
table.insert(fingerprints, {
2498
name = "Moxa EDR (var.3)",
2499
cpe = "cpe:/o:moxa:edr_g903_firmware",
2500
category = "routers",
2501
paths = {
2502
{path = "/Login.asp"}
2503
},
2504
target_check = function (host, port, path, response)
2505
return have_openssl
2506
and response.status == 200
2507
and response.body
2508
and response.body:find("Moxa EDR", 1, true)
2509
and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")
2510
and not response.body:find("sysnotify_support", 1, true)
2511
and response.body:find("%Wvar%s+rndN%s*=%s*%d+%s*;")
2512
end,
2513
login_combos = {
2514
{username = "admin", password = "moxa"},
2515
{username = "user", password = "moxa"}
2516
},
2517
login_check = function (host, port, path, user, pass)
2518
local resp1 = http_get_simple(host, port, url.absolute(path, "Login.asp"))
2519
if not (resp1.status == 200 and resp1.body) then return false end
2520
local nonce = resp1.body:match("%Wvar%s+rndN%s*=%s*(%d+)%s*;")
2521
if not nonce then return false end
2522
local cuser = #user > 0 and user or "unknown"
2523
local cpass = pass .. nonce
2524
local cookies = {{name="NAME", value=url.escape(cuser)},
2525
{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}
2526
local form2 = {Username=user,
2527
Password=pass,
2528
["Submit.x"]=0,
2529
["Submit.y"]=0}
2530
local resp2 = http_post_simple(host, port, url.absolute(path, "init.asp"),
2531
{cookies=cookies}, form2)
2532
if resp2.status~=200 then return false end
2533
local resp3 = http_get_simple(host, port, url.absolute(path, "home.asp"),
2534
{cookies=cookies})
2535
return resp3.status == 200
2536
and get_tag(resp3.body or "", "frame", {src="^name%.asp$"})
2537
end
2538
})
2539
2540
table.insert(fingerprints, {
2541
name = "Moxa EDR (var.4)",
2542
category = "routers",
2543
paths = {
2544
{path = "/Login.asp"}
2545
},
2546
target_check = function (host, port, path, response)
2547
return have_openssl
2548
and response.status == 200
2549
and response.body
2550
and response.body:find("Moxa EDR", 1, true)
2551
and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")
2552
and not response.body:find("sysnotify_support", 1, true)
2553
and not response.body:find("%Wvar%s+rndN%s*=%s*%d+%s*;")
2554
end,
2555
login_combos = {
2556
{username = "admin", password = "moxa"},
2557
{username = "user", password = "moxa"}
2558
},
2559
login_check = function (host, port, path, user, pass)
2560
local cuser = #user > 0 and user or "unknown"
2561
local cpass = #pass > 0 and pass or "NULL"
2562
local cookies = {{name="NAME", value=url.escape(cuser)},
2563
{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}
2564
local form1 = {Username=user,
2565
Password=pass,
2566
["Submit.x"]=0,
2567
["Submit.y"]=0}
2568
local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),
2569
{cookies=cookies}, form1)
2570
if resp1.status~=200 then return false end
2571
local resp2 = http_get_simple(host, port, url.absolute(path, "home.asp"),
2572
{cookies=cookies})
2573
return resp2.status == 200
2574
and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})
2575
end
2576
})
2577
2578
table.insert(fingerprints, {
2579
name = "Moxa EDR (var.5)",
2580
cpe = "cpe:/o:moxa:edr_g903_firmware",
2581
category = "routers",
2582
paths = {
2583
{path = "/Login.asp"}
2584
},
2585
target_check = function (host, port, path, response)
2586
return have_openssl
2587
and response.status == 200
2588
and response.body
2589
and response.body:find("Moxa EDR", 1, true)
2590
and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")
2591
and response.body:find("sysnotify_support", 1, true)
2592
end,
2593
login_combos = {
2594
{username = "admin", password = "moxa"},
2595
{username = "user", password = "moxa"}
2596
},
2597
login_check = function (host, port, path, user, pass)
2598
local cuser = #user > 0 and user or "unknown"
2599
local cpass = #pass > 0 and pass or "NULL"
2600
local cookies = {{name="sysnotify_support", value="yes"},
2601
{name="sysnotify_loginStatus", value="initial"},
2602
{name="lasttime", value=tostring(math.floor(stdnse.clock_ms()))},
2603
{name="sessionID", value=tostring(math.random(1000000000, 4294967295))},
2604
{name="NAME", value=url.escape(cuser)},
2605
{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))},
2606
{name="AUTHORITY", value=""}}
2607
local form = {Username=user,
2608
Password=pass,
2609
["Submit.x"]=0,
2610
["Submit.y"]=0}
2611
local resp = http_post_simple(host, port, url.absolute(path, "init.asp"),
2612
{cookies=cookies}, form)
2613
return resp.status == 200
2614
and (resp.body or ""):find("%sonLoad%s*=%s*['\"]SetAuthorityCookie%(")
2615
end
2616
})
2617
2618
table.insert(fingerprints, {
2619
name = "Ovislink AirLive (basic auth)",
2620
cpe = "cpe:/h:ovislink:airlive_*",
2621
category = "routers",
2622
paths = {
2623
{path = "/"}
2624
},
2625
target_check = function (host, port, path, response)
2626
local realm = http_auth_realm(response) or ""
2627
return realm:find("^AirLive ")
2628
or realm:find("%f[%w]admin/airlive$")
2629
or realm:find("%f[%w]airlive/airlive$")
2630
end,
2631
login_combos = {
2632
{username = "admin", password = "airlive"},
2633
{username = "airlive", password = "airlive"}
2634
},
2635
login_check = function (host, port, path, user, pass)
2636
return try_http_auth(host, port, path, user, pass, false)
2637
end
2638
})
2639
2640
table.insert(fingerprints, {
2641
name = "Ovislink AirLive AP",
2642
cpe = "cpe:/h:ovislink:airlive_*",
2643
category = "routers",
2644
paths = {
2645
{path = "/index.asp"}
2646
},
2647
target_check = function (host, port, path, response)
2648
return response.status == 200
2649
and response.body
2650
and response.body:find("AirLive", 1, true)
2651
and response.body:lower():find("<title>airlive [%w-]+</title>")
2652
and response.body:lower():find("%shref%s*=%s*(['\"]?)sts_%w+%.asp%1[%s>]")
2653
end,
2654
login_combos = {
2655
{username = "", password = "airlive"}
2656
},
2657
login_check = function (host, port, path, user, pass)
2658
local resp = http_post_simple(host, port,
2659
url.absolute(path, "goform/asp_login"),
2660
nil, {psw=pass})
2661
return resp.status == 302
2662
and (resp.header["location"] or ""):find("/sts_%w+%.asp$")
2663
end
2664
})
2665
2666
table.insert(fingerprints, {
2667
name = "Ovislink AirLive WIAS (var.1)",
2668
cpe = "cpe:/h:ovislink:airlive_*",
2669
category = "routers",
2670
paths = {
2671
{path = "/"}
2672
},
2673
target_check = function (host, port, path, response)
2674
return response.status == 200
2675
and response.body
2676
and response.body:find("WIAS", 1, true)
2677
and response.body:lower():find("<title>wias%-%d+%a</title>")
2678
and get_tag(response.body, "form", {action="^check%.shtml$"})
2679
and get_tag(response.body, "input", {name="^password$"})
2680
end,
2681
login_combos = {
2682
{username = "admin", password = "airlive"}
2683
},
2684
login_check = function (host, port, path, user, pass)
2685
local resp = http_post_simple(host, port,
2686
url.absolute(path, "check.shtml"),
2687
nil, {username=user,password=pass})
2688
return resp.status == 302
2689
and resp.header["location"] == "home.shtml"
2690
end
2691
})
2692
2693
table.insert(fingerprints, {
2694
name = "Ovislink AirLive WIAS (var.2)",
2695
cpe = "cpe:/h:ovislink:airlive_*",
2696
category = "routers",
2697
paths = {
2698
{path = "/"}
2699
},
2700
target_check = function (host, port, path, response)
2701
return response.status == 200
2702
and response.body
2703
and response.body:find("AirLive", 1, true)
2704
and response.body:lower():find("<title>airlive wias%-%d+%a</title>")
2705
and get_tag(response.body, "form", {action="^check%.shtml$"})
2706
and get_tag(response.body, "input", {name="^adm_pwd$"})
2707
end,
2708
login_combos = {
2709
{username = "admin", password = "airlive"}
2710
},
2711
login_check = function (host, port, path, user, pass)
2712
local resp = http_post_simple(host, port,
2713
url.absolute(path, "check.shtml"),
2714
nil, {adm_name=user,adm_pwd=pass})
2715
return resp.status == 302
2716
and resp.header["location"] == "home.shtml"
2717
end
2718
})
2719
2720
table.insert(fingerprints, {
2721
name = "AirTies router",
2722
cpe = "cpe:/h:airties:air_*",
2723
category = "routers",
2724
paths = {
2725
{path = "/"}
2726
},
2727
target_check = function (host, port, path, response)
2728
return response.status == 200
2729
and response.body
2730
and get_refresh_url(response.body, "/js/%.js_check%.html$")
2731
end,
2732
login_combos = {
2733
{username = "admin", password = ""}
2734
},
2735
login_check = function (host, port, path, user, pass)
2736
local form = {redirect="",
2737
self="",
2738
user=user,
2739
password=pass,
2740
gonder="OK"}
2741
local resp = http_post_simple(host, port,
2742
url.absolute(path, "cgi-bin/login"),
2743
nil, form)
2744
return resp.status == 200
2745
and get_cookie(resp, "AIRTIESSESSION", "^%x+$")
2746
and get_refresh_url(resp.body or "", "/main%.html$")
2747
end
2748
})
2749
2750
table.insert(fingerprints, {
2751
name = "Arris Touchstone",
2752
cpe = "cpe:/a:arris:touchstone_*",
2753
category = "routers",
2754
paths = {
2755
{path = "/"}
2756
},
2757
target_check = function (host, port, path, response)
2758
return response.status == 200
2759
and response.body
2760
and response.body:find("sta_wifi", 1, true)
2761
and get_tag(response.body, "form", {action="^check%.php$"})
2762
end,
2763
login_combos = {
2764
{username = "admin", password = "password"}
2765
},
2766
login_check = function (host, port, path, user, pass)
2767
local resp = http_post_simple(host, port, url.absolute(path, "check.php"),
2768
nil, {username=user,password=pass})
2769
return resp.status == 200
2770
and get_cookie(resp, "PHPSESSID", "^%w+$")
2771
and (resp.body or ""):find("%Wlocation%.href%s*=%s*(['\"])admin_password_change%.php%1")
2772
end
2773
})
2774
2775
table.insert(fingerprints, {
2776
name = "ASUS TM router",
2777
cpe = "cpe:/h:asus:tm-*",
2778
category = "routers",
2779
paths = {
2780
{path = "/"}
2781
},
2782
target_check = function (host, port, path, response)
2783
return (http_auth_realm(response) or ""):find("^TM%-%u[%u%d]+$")
2784
end,
2785
login_combos = {
2786
{username = "admin", password = "password"}
2787
},
2788
login_check = function (host, port, path, user, pass)
2789
return try_http_auth(host, port, path, user, pass, false)
2790
end
2791
})
2792
2793
table.insert(fingerprints, {
2794
name = "ASUS router",
2795
category = "routers",
2796
paths = {
2797
{path = "/"}
2798
},
2799
target_check = function (host, port, path, response)
2800
local realm = http_auth_realm(response)
2801
if not realm then return false end
2802
local type = realm:match("^(%u+)%-%u[%u%d]+$")
2803
for t in ("DSL,EA,RP,RT,TM"):gmatch("%u+") do
2804
if t == type then return true end
2805
end
2806
return false
2807
end,
2808
login_combos = {
2809
{username = "admin", password = "admin"}
2810
},
2811
login_check = function (host, port, path, user, pass)
2812
return try_http_auth(host, port, path, user, pass, false)
2813
end
2814
})
2815
2816
table.insert(fingerprints, {
2817
name = "ASUS RX3041",
2818
category = "routers",
2819
paths = {
2820
{path = "/"}
2821
},
2822
target_check = function (host, port, path, response)
2823
return (http_auth_realm(response) or ""):find("^ *RX3041%f[ \0]")
2824
end,
2825
login_combos = {
2826
{username = "admin", password = "admin"}
2827
},
2828
login_check = function (host, port, path, user, pass)
2829
return try_http_auth(host, port, path, user, pass, false)
2830
end
2831
})
2832
2833
table.insert(fingerprints, {
2834
name = "Belkin G Wireless Router",
2835
cpe = "cpe:/h:belkin:f5d7234-4",
2836
category = "routers",
2837
paths = {
2838
{path = "/"}
2839
},
2840
target_check = function (host, port, path, response)
2841
return have_openssl
2842
and response.status == 200
2843
and response.body
2844
and response.body:find("setup_top.htm", 1, true)
2845
and response.body:find("status.stm", 1, true)
2846
end,
2847
login_combos = {
2848
{username = "", password = ""}
2849
},
2850
login_check = function (host, port, path, user, pass)
2851
local resp = http_post_simple(host, port,
2852
url.absolute(path, "cgi-bin/login.exe"), nil,
2853
{totalMSec = stdnse.clock_ms()/1000,
2854
pws = stdnse.tohex(openssl.md5(pass))})
2855
return resp.status == 302
2856
and (resp.header["location"] or ""):find("/index%.htm$")
2857
end
2858
})
2859
2860
table.insert(fingerprints, {
2861
name = "Belkin/Arris 2307",
2862
category = "routers",
2863
paths = {
2864
{path = "/"}
2865
},
2866
target_check = function (host, port, path, response)
2867
return response.status == 200
2868
and response.body
2869
and response.body:find("isAPmode", 1, true)
2870
and get_tag(response.body, "meta", {name="^description$", content="^%w+ 2307$"})
2871
end,
2872
login_combos = {
2873
{username = "", password = ""}
2874
},
2875
login_check = function (host, port, path, user, pass)
2876
local form = {page="",
2877
logout="",
2878
action="submit",
2879
pws=base64.enc(pass),
2880
itsbutton1="Submit",
2881
h_language="en",
2882
is_parent_window="1"}
2883
local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),
2884
nil, form)
2885
return resp.status == 200
2886
and (resp.body or ""):find("index.html", 1, true)
2887
end
2888
})
2889
2890
table.insert(fingerprints, {
2891
name = "D-Link DIR router (var.1)",
2892
cpe = "cpe:/h:d-link:dir-*",
2893
category = "routers",
2894
paths = {
2895
{path = "/"}
2896
},
2897
target_check = function (host, port, path, response)
2898
return response.status == 200
2899
and (response.header["server"] or ""):find(" DIR%-%d+")
2900
and response.body
2901
and response.body:find("AUTH.Login(", 1, true)
2902
and response.body:find('%WOBJ%("loginusr"%)%.value%s*=%s*""')
2903
and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")
2904
end,
2905
login_combos = {
2906
{username = "admin", password = ""}
2907
},
2908
login_check = function (host, port, path, user, pass)
2909
local form = {REPORT_METHOD="xml",
2910
ACTION="login_plaintext",
2911
USER=user,
2912
PASSWD=pass,
2913
CAPTCHA=""}
2914
local resp = http_post_simple(host, port, url.absolute(path, "session.cgi"),
2915
{cookies="uid="..random_alnum(10)}, form)
2916
return resp.status == 200
2917
and (resp.body or ""):find("<RESULT>SUCCESS</RESULT>", 1, true)
2918
end
2919
})
2920
2921
table.insert(fingerprints, {
2922
name = "D-Link DIR router (var.2)",
2923
cpe = "cpe:/h:d-link:dir-*",
2924
category = "routers",
2925
paths = {
2926
{path = "/"}
2927
},
2928
target_check = function (host, port, path, response)
2929
return response.status == 200
2930
and (response.header["server"] or ""):find(" DIR%-%d+")
2931
and response.body
2932
and response.body:find("AUTH.Login(", 1, true)
2933
and response.body:find('%WOBJ%("loginusr"%)%.value%s*=%s*username%W')
2934
and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")
2935
end,
2936
login_combos = {
2937
{username = "Admin", password = ""}
2938
},
2939
login_check = function (host, port, path, user, pass)
2940
local form = {REPORT_METHOD="xml",
2941
ACTION="login_plaintext",
2942
USER=user,
2943
PASSWD=pass,
2944
CAPTCHA=""}
2945
local resp = http_post_simple(host, port, url.absolute(path, "session.cgi"),
2946
{cookies="uid="..random_alnum(10)}, form)
2947
return resp.status == 200
2948
and (resp.body or ""):find("<RESULT>SUCCESS</RESULT>", 1, true)
2949
end
2950
})
2951
2952
table.insert(fingerprints, {
2953
name = "D-Link DIR router (var.3)",
2954
cpe = "cpe:/h:d-link:dir-*",
2955
category = "routers",
2956
paths = {
2957
{path = "/"}
2958
},
2959
target_check = function (host, port, path, response)
2960
return have_openssl
2961
and response.status == 200
2962
and (response.header["server"] or ""):find(" DIR%-%d+")
2963
and response.body
2964
and response.body:find("AUTH.Login_Hash(", 1, true)
2965
and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")
2966
end,
2967
login_combos = {
2968
{username = "Admin", password = ""}
2969
},
2970
login_check = function (host, port, path, user, pass)
2971
local url2 = url.absolute(path, "authentication.cgi")
2972
local url1 = url2 .. "?captcha=&dummy=" .. math.floor(stdnse.clock_ms())
2973
local resp1 = http_get_simple(host, port, url1)
2974
if not (resp1.status == 200 and resp1.body) then return false end
2975
local jstatus, jout = json.parse(resp1.body)
2976
if not (jstatus and jout.uid and jout.challenge) then return false end
2977
local auth = stdnse.tohex(openssl.hmac("MD5", pass, user .. jout.challenge))
2978
local resp2 = http_post_simple(host, port, url2,
2979
{cookies = "uid=" .. jout.uid},
2980
{id=user, password=auth:upper()})
2981
if not (resp2.status == 200 and resp2.body) then return false end
2982
jstatus, jout = json.parse(resp2.body)
2983
return jstatus and jout.status == "ok"
2984
end
2985
})
2986
2987
table.insert(fingerprints, {
2988
name = "D-Link DIR-620",
2989
cpe = "cpe:/h:d-link:dir-620",
2990
category = "routers",
2991
paths = {
2992
{path = "/"}
2993
},
2994
target_check = function (host, port, path, response)
2995
return response.status == 200
2996
and response.body
2997
and response.body:find("DIR-620", 1, true)
2998
and response.body:lower():find("<title>dir-620</title>", 1, true)
2999
and get_tag(response.body, "form", {action="^index%.cgi$"})
3000
end,
3001
login_combos = {
3002
{username = "admin", password = "anonymous"}
3003
},
3004
login_check = function (host, port, path, user, pass)
3005
local cookies = {{name="user_ip", value="127.0.0.1"},
3006
{name="cookie_lang", value="rus"},
3007
{name="client_login", value=user},
3008
{name="client_password", value=pass}}
3009
local resp = http_post_simple(host, port, url.absolute(path, "index.cgi"),
3010
{cookies=cookies},
3011
{v2="y",rs_type="html",auth="auth"})
3012
return resp.status == 200
3013
and (resp.body or ""):find("%sid%s*=%s*(['\"])v_firmware_value%1%s*>%d")
3014
end
3015
})
3016
3017
table.insert(fingerprints, {
3018
name = "D-Link DIR router (basic auth)",
3019
cpe = "cpe:/h:d-link:dir-*",
3020
category = "routers",
3021
paths = {
3022
{path = "/"}
3023
},
3024
target_check = function (host, port, path, response)
3025
return (http_auth_realm(response) or ""):find("%f[%w]DIR%-%d%d%d%f[%u\0]")
3026
end,
3027
login_combos = {
3028
{username = "admin", password = "admin"},
3029
{username = "admin", password = ""}
3030
},
3031
login_check = function (host, port, path, user, pass)
3032
return try_http_auth(host, port, path, user, pass, false)
3033
end
3034
})
3035
3036
table.insert(fingerprints, {
3037
name = "D-Link DSL router",
3038
cpe = "cpe:/h:d-link:dsl-*",
3039
category = "routers",
3040
paths = {
3041
{path = "/"}
3042
},
3043
target_check = function (host, port, path, response)
3044
return response.status == 200
3045
and (response.header["server"] or ""):find("^mini_httpd/%d+%.")
3046
and response.body
3047
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])[^'\"]-/cgi%-bin/webproc%1")
3048
end,
3049
login_combos = {
3050
{username = "admin", password = "admin"},
3051
{username = "admin", password = "password"},
3052
},
3053
login_check = function (host, port, path, user, pass)
3054
local lurl = url.absolute(path, "cgi-bin/webproc")
3055
local resp1 = http_get_simple(host, port, lurl)
3056
if not (resp1.status == 200) then return false end
3057
local form = {getpage="html/index.html",
3058
errorpage="html/main.html",
3059
["var:menu"]="setup",
3060
["var:page"]="wizard",
3061
["obj-action"]="auth",
3062
[":username"]=user,
3063
[":password"]=pass,
3064
[":action"]="login",
3065
[":sessionid"]=get_cookie(resp1, "sessionid")}
3066
local resp2 = http_post_simple(host, port, lurl,
3067
{cookies=resp1.cookies}, form)
3068
return resp2.status == 302
3069
and (resp2.header["location"] or ""):find("/cgi-bin/webproc?getpage=html/index.html&", 1, true)
3070
end
3071
})
3072
3073
table.insert(fingerprints, {
3074
name = "D-Link DSL router (basic auth)",
3075
cpe = "cpe:/h:d-link:dsl-*",
3076
category = "routers",
3077
paths = {
3078
{path = "/"}
3079
},
3080
target_check = function (host, port, path, response)
3081
return (http_auth_realm(response) or ""):find("^DSL%-%d%d%d%d?[BRU]%f[_\0]")
3082
end,
3083
login_combos = {
3084
{username = "admin", password = "admin"},
3085
{username = "support", password = "support"}
3086
},
3087
login_check = function (host, port, path, user, pass)
3088
return try_http_auth(host, port, path, user, pass, false)
3089
end
3090
})
3091
3092
table.insert(fingerprints, {
3093
name = "D-Link DSL T router (basic auth)",
3094
cpe = "cpe:/h:d-link:dsl-*",
3095
category = "routers",
3096
paths = {
3097
{path = "/"}
3098
},
3099
target_check = function (host, port, path, response)
3100
return (http_auth_realm(response) or ""):find("%f[^ \0]DSL%-%d%d%d%d?T$")
3101
end,
3102
login_combos = {
3103
{username = "admin", password = "admin"},
3104
{username = "user", password = "user"}
3105
},
3106
login_check = function (host, port, path, user, pass)
3107
return try_http_auth(host, port, path, user, pass, false)
3108
end
3109
})
3110
3111
table.insert(fingerprints, {
3112
name = "TP-Link (basic auth)",
3113
cpe = "cpe:/o:tp-link:lm_firmware",
3114
category = "routers",
3115
paths = {
3116
{path = "/"}
3117
},
3118
target_check = function (host, port, path, response)
3119
return response.status == 401
3120
and (http_auth_realm(response) or ""):find("^TP%-LINK")
3121
end,
3122
login_combos = {
3123
{username = "admin", password = "admin"}
3124
},
3125
login_check = function (host, port, path, user, pass)
3126
return try_http_auth(host, port, path, user, pass, false)
3127
end
3128
})
3129
3130
table.insert(fingerprints, {
3131
name = "TP-Link (MD5 cookie)",
3132
cpe = "cpe:/o:tp-link:lm_firmware",
3133
category = "routers",
3134
paths = {
3135
{path = "/"}
3136
},
3137
target_check = function (host, port, path, response)
3138
return have_openssl
3139
and response.status == 200
3140
and (http_auth_realm(response) or ""):find("^TP%-LINK")
3141
and response.body
3142
and response.body:find("%spassword%s*=%s*hex_md5")
3143
end,
3144
login_combos = {
3145
{username = "admin", password = "admin"}
3146
},
3147
login_check = function (host, port, path, user, pass)
3148
local auth = base64.enc(user .. ":" .. stdnse.tohex(openssl.md5(pass)))
3149
local cookie = "Authorization=" .. url.escape("Basic " .. auth)
3150
local resp = http_get_simple(host, port,
3151
url.absolute(path, "userRpm/LoginRpm.htm?Save=Save"),
3152
{cookies=cookie})
3153
return resp.status == 200
3154
and (resp.body or ""):find(">window%.parent%.location%.href%s*=%s*(['\"])[^'\"]-/userRpm/Index%.htm%1")
3155
end
3156
})
3157
3158
table.insert(fingerprints, {
3159
name = "TP-Link (plain cookie)",
3160
cpe = "cpe:/o:tp-link:lm_firmware",
3161
category = "routers",
3162
paths = {
3163
{path = "/"}
3164
},
3165
target_check = function (host, port, path, response)
3166
return response.status == 200
3167
and (http_auth_realm(response) or ""):find("^TP%-LINK")
3168
and response.body
3169
and not response.body:find("%spassword%s*=%s*hex_md5")
3170
end,
3171
login_combos = {
3172
{username = "admin", password = "admin"}
3173
},
3174
login_check = function (host, port, path, user, pass)
3175
local auth = base64.enc(user .. ":" .. pass)
3176
local cookie = "Authorization=" .. url.escape("Basic " .. auth)
3177
local resp = http_get_simple(host, port, path, {cookies=cookie})
3178
return resp.status == 200
3179
and (resp.body or ""):find("%shref%s*=%s*(['\"])[^'\"]-/userRpm/LogoutRpm%.htm%1")
3180
end
3181
})
3182
3183
table.insert(fingerprints, {
3184
name = "Comtrend NexusLink-5631",
3185
category = "routers",
3186
paths = {
3187
{path = "/"}
3188
},
3189
target_check = function (host, port, path, response)
3190
return http_auth_realm(response) == "DSL Router"
3191
end,
3192
login_combos = {
3193
{username = "apuser", password = "apuser"},
3194
{username = "root", password = "12345"}
3195
},
3196
login_check = function (host, port, path, user, pass)
3197
return try_http_auth(host, port, path, user, pass, false)
3198
end
3199
})
3200
3201
table.insert(fingerprints, {
3202
name = "iBall Baton",
3203
category = "routers",
3204
paths = {
3205
{path = "/"}
3206
},
3207
target_check = function (host, port, path, response)
3208
return (http_auth_realm(response) or ""):find("^iBall Baton ")
3209
end,
3210
login_combos = {
3211
{username = "admin", password = "admin"},
3212
{username = "support", password = "support"},
3213
{username = "user", password = "user"}
3214
},
3215
login_check = function (host, port, path, user, pass)
3216
return try_http_auth(host, port, path, user, pass, false)
3217
end
3218
})
3219
3220
table.insert(fingerprints, {
3221
name = "Link-Net LW/LWH router",
3222
category = "routers",
3223
paths = {
3224
{path = "/"}
3225
},
3226
target_check = function (host, port, path, response)
3227
if not (response.status == 302
3228
and (response.header["location"] or ""):find("/home%.asp$")) then
3229
return false
3230
end
3231
local resp = http_get_simple(host, port,
3232
url.absolute(path, "home.asp"))
3233
return resp.status == 200
3234
and resp.body
3235
and resp.body:find("LINK-NET", 1, true)
3236
and resp.body:find("%svendor%s*=%s*(['\"])LINK%-NET%1")
3237
and resp.body:lower():find("[%s>]wireless router</title>")
3238
end,
3239
login_combos = {
3240
{username = "admin", password = "admin"}
3241
},
3242
login_check = function (host, port, path, user, pass)
3243
return try_http_auth(host, port, url.absolute(path, "internet/wan.asp"),
3244
user, pass, false)
3245
end
3246
})
3247
3248
table.insert(fingerprints, {
3249
name = "Planex Broad Lanner",
3250
cpe = "cpe:/h:planex:brl-*",
3251
category = "routers",
3252
paths = {
3253
{path = "/"}
3254
},
3255
target_check = function (host, port, path, response)
3256
return response.status == 200
3257
and response.body
3258
and response.body:find("Planex Communications", 1, true)
3259
and get_tag(response.body, "meta", {content="^B%a%a%-04FM%a HTML"})
3260
and get_tag(response.body, "frame", {src="^top%.htm$"})
3261
end,
3262
login_combos = {
3263
{username = "", password = "password"}
3264
},
3265
login_check = function (host, port, path, user, pass)
3266
return try_http_auth(host, port, url.absolute(path, "top.htm"),
3267
user, pass, false)
3268
end
3269
})
3270
3271
table.insert(fingerprints, {
3272
name = "TrendChip ADSL Modem",
3273
category = "routers",
3274
paths = {
3275
{path = "/"}
3276
},
3277
target_check = function (host, port, path, response)
3278
return http_auth_realm(response) == "ADSL Modem"
3279
and (response.header["server"] or ""):find("^Boa/%d+%.")
3280
and get_cookie(response, "SESSIONID", "^%x+$")
3281
end,
3282
login_combos = {
3283
{username = "admin", password = "admin"},
3284
{username = "admin", password = "1234"},
3285
{username = ("qwertyuiop"):rep(13):sub(1, 128),
3286
password = ("1234567890"):rep(13):sub(1, 128)},
3287
{username = "user3",
3288
password = ("1234567890"):rep(13):sub(1, 128)},
3289
},
3290
login_check = function (host, port, path, user, pass)
3291
local resp1 = http_get_simple(host, port, path)
3292
if not resp1.status then return false end
3293
local auth = {username = user, password = pass}
3294
local resp2 = http_get_simple(host, port, path,
3295
{auth=auth, cookies=resp1.cookies})
3296
return resp2.status == 200
3297
end
3298
})
3299
3300
table.insert(fingerprints, {
3301
name = "Westell",
3302
category = "routers",
3303
paths = {
3304
{path = "/"}
3305
},
3306
target_check = function (host, port, path, response)
3307
return response.status == 302
3308
and (response.header["location"] or ""):find("/htmlV/PasswordChange%.asp$")
3309
end,
3310
login_combos = {
3311
{username = "admin", password = "password"}
3312
},
3313
login_check = function (host, port, path, user, pass)
3314
return try_http_auth(host, port,
3315
url.absolute(path, "htmlV/PasswordChange.asp"),
3316
user, pass, true)
3317
end
3318
})
3319
3320
table.insert(fingerprints, {
3321
name = "Yamaha RT 10.x",
3322
cpe = "cpe:/o:yahama:rt*",
3323
category = "routers",
3324
paths = {
3325
{path = "/"}
3326
},
3327
target_check = function (host, port, path, response)
3328
local lurl = response.status == 200
3329
and get_refresh_url(response.body or "", "/user/index[_%a]*.html$")
3330
if not lurl then return false end
3331
local resp = http_get_simple(host, port, lurl)
3332
return (http_auth_realm(resp) or ""):find("^YAMAHA%-RT ")
3333
end,
3334
login_combos = {
3335
{username = "", password = ""}
3336
},
3337
login_check = function (host, port, path, user, pass)
3338
local resp = http_get_simple(host, port, path)
3339
local lurl = resp.status == 200
3340
and get_refresh_url(resp.body or "", "/user/index[_%a]*.html$")
3341
if not lurl then return false end
3342
return try_http_auth(host, port, lurl, user, pass, false)
3343
end
3344
})
3345
3346
table.insert(fingerprints, {
3347
name = "Yamaha RT 11.x",
3348
cpe = "cpe:/o:yahama:rt*",
3349
category = "routers",
3350
paths = {
3351
{path = "/"}
3352
},
3353
target_check = function (host, port, path, response)
3354
return (http_auth_realm(response) or ""):find("^YAMAHA%-RT ")
3355
end,
3356
login_combos = {
3357
{username = "", password = ""}
3358
},
3359
login_check = function (host, port, path, user, pass)
3360
return try_http_auth(host, port, path, user, pass, false)
3361
end
3362
})
3363
3364
table.insert(fingerprints, {
3365
name = "Yamaha SWX",
3366
category = "routers",
3367
paths = {
3368
{path = "/login.html"}
3369
},
3370
target_check = function (host, port, path, response)
3371
return response.status == 200
3372
and response.body
3373
and response.body:find("Yamaha Corporation", 1, true)
3374
and get_tag(response.body, "form", {action="/goform/authenticate%.json$"})
3375
and get_tag(response.body, "input", {name="^URL$", value="/dashboard/index%.html$"})
3376
end,
3377
login_combos = {
3378
{username="", password=""}
3379
},
3380
login_check = function (host, port, path, user, pass)
3381
local form = {URL=url.absolute(path, "/dashboard/index.html"),
3382
USER=user,
3383
PASS=pass}
3384
local resp = http_post_simple(host, port,
3385
url.absolute(path, "goform/authenticate.json"),
3386
nil, form)
3387
if not (resp.status == 200 and resp.body) then return false end
3388
local jstatus, jout = json.parse(resp.body)
3389
return jstatus and jout.result == "SUCCESS"
3390
end
3391
})
3392
3393
table.insert(fingerprints, {
3394
name = "Zoom ADSL X5",
3395
category = "routers",
3396
paths = {
3397
{path = "/"}
3398
},
3399
target_check = function (host, port, path, response)
3400
return response.status == 301
3401
and (response.header["server"] or ""):find("^Nucleus/%d+%.")
3402
and (response.header["location"] or ""):find("/hag/pages/home%.htm$")
3403
end,
3404
login_combos = {
3405
{username = "admin", password = "zoomadsl"}
3406
},
3407
login_check = function (host, port, path, user, pass)
3408
return try_http_auth(host, port, url.absolute(path, "hag/pages/home.htm"),
3409
user, pass, false)
3410
end
3411
})
3412
3413
table.insert(fingerprints, {
3414
name = "ZTE F660",
3415
cpe = "cpe:/h:zte:f660",
3416
category = "routers",
3417
paths = {
3418
{path = "/"}
3419
},
3420
target_check = function (host, port, path, response)
3421
return response.status == 200
3422
and response.body
3423
and response.body:find("ZTE", 1, true)
3424
and response.body:lower():find("<title>f660</title>", 1, true)
3425
end,
3426
login_combos = {
3427
{username = "admin", password = "admin"}
3428
},
3429
login_check = function (host, port, path, user, pass)
3430
local resp1 = http_get_simple(host, port, path)
3431
if not (resp1.status == 200 and resp1.body) then return false end
3432
local ltoken = resp1.body:match("%WgetObj%(%s*['\"]Frm_Logintoken['\"]%s*%)%.value%s*=%s*['\"](%d+)['\"]%s*;")
3433
if not ltoken then return false end
3434
local form = {frashnum="",
3435
action="login",
3436
Frm_Logintoken=ltoken,
3437
Username=user,
3438
Password=pass}
3439
local resp2 = http_post_simple(host, port, path, {cookies=resp1.cookies}, form)
3440
return resp2.status == 302
3441
and (resp2.header["location"] or ""):find("/start%.ghtml$")
3442
end
3443
})
3444
3445
table.insert(fingerprints, {
3446
name = "ZTE ZXV10 I5xx",
3447
category = "routers",
3448
paths = {
3449
{path = "/"}
3450
},
3451
target_check = function (host, port, path, response)
3452
return response.status == 200
3453
and response.body
3454
and response.body:find("ZTE", 1, true)
3455
and get_tag(response.body, "form", {name="^flogin$", action="^getpage%.gch%?pid=1001$"})
3456
end,
3457
login_combos = {
3458
{username = "admin", password = "admin"}
3459
},
3460
login_check = function (host, port, path, user, pass)
3461
local resp1 = http_get_simple(host, port, path)
3462
if not (resp1.status == 200 and resp1.body) then return false end
3463
local stime = resp1.body:match("%Wdocument%.getElementById%(%s*['\"]submittime['\"]%s*%)%.value%s*=%s*['\"](%d+)['\"]%s*;")
3464
if not stime then return false end
3465
local form = {submenu=-1,
3466
menuPos=-1,
3467
nosubmenu=1,
3468
nextpage="welcome.gch",
3469
nextgch="",
3470
nextjs="welcome.js",
3471
title="Come In to Configuration",
3472
path="Welcome",
3473
submittime=stime,
3474
tUsername=user,
3475
tPassword=pass}
3476
local resp2 = http_post_simple(host, port,
3477
url.absolute(path, "getpage.gch?pid=1001"),
3478
nil, form)
3479
return resp2.status == 200
3480
and (resp2.body or ""):lower():find("<title>[^<]-configuration")
3481
end
3482
})
3483
3484
table.insert(fingerprints, {
3485
name = "ZTE ZXV10 W300",
3486
cpe = "cpe:/o:zte:zxv10_w300_firmware",
3487
category = "routers",
3488
paths = {
3489
{path = "/"}
3490
},
3491
target_check = function (host, port, path, response)
3492
return (http_auth_realm(response) or ""):find("^ZXV10 W300$")
3493
end,
3494
login_combos = {
3495
{username = "admin", password = "admin"}
3496
},
3497
login_check = function (host, port, path, user, pass)
3498
return try_http_auth(host, port, path, user, pass, false)
3499
end
3500
})
3501
3502
table.insert(fingerprints, {
3503
name = "3Com OfficeConnect VPN Firewall",
3504
cpe = "cpe:/h:3com:3cr870-95",
3505
category = "routers",
3506
paths = {
3507
{path = "/"}
3508
},
3509
target_check = function (host, port, path, response)
3510
return response.status == 200
3511
and response.body
3512
and response.body:find("3Com", 1, true)
3513
and response.body:find("%Wtop%.document%.location%s*=%s*(['\"])[^'\"]-/default%.htm%1")
3514
and get_tag(response.body, "meta", {["http-equiv"]="^3cnumber$"})
3515
end,
3516
login_combos = {
3517
{username = "", password = "admin"}
3518
},
3519
login_check = function (host, port, path, user, pass)
3520
local resp = http_post_simple(host, port,
3521
url.absolute(path, "cgi-bin/admin?page=x"),
3522
nil, {AdminPassword=pass,next=10,page="x"})
3523
return resp.status == 200
3524
and get_tag(resp.body or "", "input", {name="^tk$"})
3525
end
3526
})
3527
3528
table.insert(fingerprints, {
3529
name = "Corega",
3530
cpe = "cpe:/o:corega:cg-*",
3531
category = "routers",
3532
paths = {
3533
{path = "/"}
3534
},
3535
target_check = function (host, port, path, response)
3536
local realm = http_auth_realm(response) or ""
3537
return realm:find("^CG%-%u*BAR")
3538
or realm:find("^corega BAR ")
3539
end,
3540
login_combos = {
3541
{username = "root", password = ""}
3542
},
3543
login_check = function (host, port, path, user, pass)
3544
return try_http_auth(host, port, path, user, pass, false)
3545
end
3546
})
3547
3548
table.insert(fingerprints, {
3549
name = "Netgear ProSafe Firewall FVS318",
3550
cpe = "cpe:/h:netgear:fvs318",
3551
category = "routers",
3552
paths = {
3553
{path = "/"}
3554
},
3555
target_check = function (host, port, path, response)
3556
return response.status == 200
3557
and response.header["server"] == "Netgear"
3558
and response.body
3559
and get_tag(response.body, "frame", {src="^top%.html$"})
3560
end,
3561
login_combos = {
3562
{username = "admin", password = "password"}
3563
},
3564
login_check = function (host, port, path, user, pass)
3565
return try_http_auth(host, port, url.absolute(path, "top.html"),
3566
user, pass, false)
3567
end
3568
})
3569
3570
table.insert(fingerprints, {
3571
name = "Netgear Router (legacy)",
3572
category = "routers",
3573
paths = {
3574
{path = "/"}
3575
},
3576
target_check = function (host, port, path, response)
3577
return (http_auth_realm(response) or ""):find("^R[PT][13]1[14]$")
3578
end,
3579
login_combos = {
3580
{username = "admin", password = "1234"}
3581
},
3582
login_check = function (host, port, path, user, pass)
3583
return try_http_auth(host, port, path, user, pass, false)
3584
end
3585
})
3586
3587
table.insert(fingerprints, {
3588
name = "Netgear Router",
3589
category = "routers",
3590
paths = {
3591
{path = "/"}
3592
},
3593
target_check = function (host, port, path, response)
3594
local realm = http_auth_realm(response) or ""
3595
return realm:find("^NETGEAR %u+%d+[%w-]+%s*$")
3596
or realm == "Netgear"
3597
or realm == "FR114P"
3598
end,
3599
login_combos = {
3600
{username = "admin", password = "password"}
3601
},
3602
login_check = function (host, port, path, user, pass)
3603
return try_http_auth(host, port, path, user, pass, false)
3604
end
3605
})
3606
3607
table.insert(fingerprints, {
3608
name = "Netgear ProSafe Plus Switch",
3609
cpe = "cpe:/h:netgear:gs108*",
3610
category = "routers",
3611
paths = {
3612
{path = "/"}
3613
},
3614
target_check = function (host, port, path, response)
3615
return response.status == 200
3616
and response.body
3617
and response.body:find("loginTData", 1, true)
3618
and response.body:lower():find("<title>netgear ", 1, true)
3619
end,
3620
login_combos = {
3621
{username = "", password = "password"}
3622
},
3623
login_check = function (host, port, path, user, pass)
3624
local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),
3625
nil, {password=pass})
3626
return resp.status == 200 and get_cookie(resp, "GS108SID", ".")
3627
end
3628
})
3629
3630
table.insert(fingerprints, {
3631
name = "Netgear Smart Switch",
3632
category = "routers",
3633
paths = {
3634
{path = "/"}
3635
},
3636
target_check = function (host, port, path, response)
3637
return response.status == 200
3638
and response.body
3639
and response.body:find("document.forms[0].pwd.focus();", 1, true)
3640
and response.body:lower():find("%saction%s*=%s*(['\"])[^'\"]-/base/%w+_login%.html%1")
3641
and response.body:lower():find("<title>netgear ", 1, true)
3642
end,
3643
login_combos = {
3644
{username = "", password = "password"}
3645
},
3646
login_check = function (host, port, path, user, pass)
3647
local resp1 = http_get_simple(host, port, path)
3648
if not (resp1.status == 200 and resp1.body) then return false end
3649
local lurl = resp1.body:match("['\"]([^'\"]-/base/%w+_login%.html)")
3650
if not lurl then return false end
3651
local button = lurl:find("main_login", 1, true) and "" or "_button"
3652
local form = {pwd=pass,
3653
["login" .. button .. ".x"]=0,
3654
["login" .. button .. ".y"]=0,
3655
err_flag=0,
3656
err_msg=""}
3657
local resp2 = http_post_simple(host, port, lurl, nil, form)
3658
return resp2.status == 200 and get_cookie(resp2, "SID", ".")
3659
end
3660
})
3661
3662
table.insert(fingerprints, {
3663
name = "Netgear Intelligent Edge",
3664
category = "routers",
3665
paths = {
3666
{path = "/"}
3667
},
3668
target_check = function (host, port, path, response)
3669
return response.status == 200
3670
and response.body
3671
and response.body:find("document.forms[0].uname.focus();", 1, true)
3672
and response.body:lower():find("%saction%s*=%s*(['\"])[^'\"]-/base/%w+_login%.html%1")
3673
and response.body:lower():find("<title>netgear ", 1, true)
3674
end,
3675
login_combos = {
3676
{username = "admin", password = ""}
3677
},
3678
login_check = function (host, port, path, user, pass)
3679
local resp1 = http_get_simple(host, port, path)
3680
if not (resp1.status == 200 and resp1.body) then return false end
3681
local lurl = resp1.body:match("['\"]([^'\"]-/base/%w+_login%.html)")
3682
if not lurl then return false end
3683
local form = {uname=user,
3684
pwd=pass,
3685
["login_button.x"]=0,
3686
["login_button.y"]=0,
3687
err_flag=0,
3688
err_msg="",
3689
submt=""}
3690
local resp2 = http_post_simple(host, port, lurl, nil, form)
3691
return resp2.status == 200 and get_cookie(resp2, "SID", ".")
3692
end
3693
})
3694
3695
table.insert(fingerprints, {
3696
name = "Netgear Gigabit Enterprise Switch",
3697
category = "routers",
3698
paths = {
3699
{path = "/"}
3700
},
3701
target_check = function (host, port, path, response)
3702
return response.status == 200
3703
and response.body
3704
and response.body:find("/base/web_main.html", 1, true)
3705
and response.body:lower():find("<title>netgear system login</title>", 1, true)
3706
end,
3707
login_combos = {
3708
{username = "admin", password = ""}
3709
},
3710
login_check = function (host, port, path, user, pass)
3711
return try_http_auth(host, port, url.absolute(path, "base/web_main.html"),
3712
user, pass, false)
3713
end
3714
})
3715
3716
table.insert(fingerprints, {
3717
name = "PLANET Smart Gigabit Switch",
3718
category = "routers",
3719
paths = {
3720
{path = "/"}
3721
},
3722
target_check = function (host, port, path, response)
3723
return response.status == 200
3724
and response.body
3725
and response.body:find(">Welcome to PLANET ", 1, true)
3726
and get_tag(response.body, "form", {action="/pass$"})
3727
end,
3728
login_combos = {
3729
{username = "", password = "admin"}
3730
},
3731
login_check = function (host, port, path, user, pass)
3732
local form = {password=pass,
3733
x=0,
3734
y=0}
3735
local resp = http_post_simple(host, port, url.absolute(path, "pass"),
3736
nil, form)
3737
if not (resp.status == 200
3738
and get_tag(resp.body or "", "frame", {src="/planet%.htm$"})) then
3739
return false
3740
end
3741
http_get_simple(host, port, url.absolute(path, "logout?submit=Apply"))
3742
return true
3743
end
3744
})
3745
3746
table.insert(fingerprints, {
3747
name = "PLANET Managed Switch (var.1)",
3748
category = "routers",
3749
paths = {
3750
{path = "/"}
3751
},
3752
target_check = function (host, port, path, response)
3753
local server = response.header["server"] or ""
3754
return (http_auth_realm(response) or ""):find("^Loging?$")
3755
and (server == "Vitesse Web Server"
3756
or server == "WebServer")
3757
and response.body
3758
and response.body:find(">Authorization required to access this URL.<", 1, true)
3759
end,
3760
login_combos = {
3761
{username = "admin", password = "admin"}
3762
},
3763
login_check = function (host, port, path, user, pass)
3764
return try_http_auth(host, port, path, user, pass, false)
3765
end
3766
})
3767
3768
table.insert(fingerprints, {
3769
name = "PLANET Managed Switch (var.2)",
3770
category = "routers",
3771
paths = {
3772
{path = "/"}
3773
},
3774
target_check = function (host, port, path, response)
3775
local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")
3776
if not (response.status == 302
3777
and loc:find("/default%.html$")) then
3778
return false
3779
end
3780
local resp = http_get_simple(host, port, loc)
3781
return resp.status == 200
3782
and resp.body
3783
and resp.body:find("1366X768", 1, true)
3784
and resp.body:lower():find("<title>switch web management (1366x768 is recommended)</title>", 1, true)
3785
and get_tag(resp.body, "form", {action="/goform/WebSetting%.html$"})
3786
end,
3787
login_combos = {
3788
{username = "admin", password = "admin"}
3789
},
3790
login_check = function (host, port, path, user, pass)
3791
local form = {name=user,
3792
pwd=pass,
3793
app="login"}
3794
local resp = http_post_simple(host, port,
3795
url.absolute(path, "goform/WebSetting.html"),
3796
nil, form)
3797
return resp.status == 203
3798
and resp.body
3799
and get_tag(resp.body, "frame", {src="/frontboard%.html$"})
3800
end
3801
})
3802
3803
table.insert(fingerprints, {
3804
name = "PLANET Managed Switch (var.3)",
3805
category = "routers",
3806
paths = {
3807
{path = "/"}
3808
},
3809
target_check = function (host, port, path, response)
3810
return response.status == 200
3811
and response.body
3812
and response.body:find("/cgi-bin/get.cgi?cmd=portlink&lg=", 1, true)
3813
and get_tag(response.body, "frame", {src="/cgi%-bin/get%.cgi%?cmd=portlink&lg=%w+$"})
3814
and response.body:lower():find("<title>managed switch</title>", 1, true)
3815
end,
3816
login_combos = {
3817
{username = "admin", password = "admin"}
3818
},
3819
login_check = function (host, port, path, user, pass)
3820
return try_http_auth(host, port,
3821
url.absolute(path, "cgi-bin/get.cgi?cmd=portlink&lg=en"),
3822
user, pass, false)
3823
end
3824
})
3825
3826
table.insert(fingerprints, {
3827
name = "PLANET Wireless Router",
3828
category = "routers",
3829
paths = {
3830
{path = "/"}
3831
},
3832
target_check = function (host, port, path, response)
3833
return response.status == 200
3834
and response.body
3835
and response.body:find("PLANET Technology", 1, true)
3836
and response.body:find("(['\"])dataCenter%.js%1")
3837
and response.body:find("%Wauth_action%s*:%s*(['\"])login%1")
3838
end,
3839
login_combos = {
3840
{username = "admin", password = "admin"},
3841
{username = "admin", password = ""}
3842
},
3843
login_check = function (host, port, path, user, pass)
3844
local form = {username=user,
3845
password=base64.enc(pass:gsub("%s", "@")),
3846
getPage="index.html",
3847
action="Apply",
3848
auth_action="login",
3849
mode="AUTH",
3850
_flg=0}
3851
local resp = http_post_simple(host, port,
3852
url.absolute(path, "postCenter.js"),
3853
nil, form)
3854
if not (resp.status == 200 and resp.body) then return false end
3855
local jstatus, jout = json.parse(resp.body:gsub("'", "\""))
3856
if not (jstatus and jout.result == "0") then return false end
3857
http_get_simple(host, port, url.absolute(path, "login.html"))
3858
return true
3859
end
3860
})
3861
3862
table.insert(fingerprints, {
3863
name = "Rubytech chassis",
3864
category = "routers",
3865
paths = {
3866
{path = "/"}
3867
},
3868
target_check = function (host, port, path, response)
3869
return response.status == 200
3870
and response.body
3871
and response.body:find("fake_server.html", 1, true)
3872
and get_tag(response.body, "form", {action="^fake_server%.html$"})
3873
and get_tag(response.body, "input", {name="^textpass$"})
3874
end,
3875
login_combos = {
3876
{username = "admin", password = "admin"}
3877
},
3878
login_check = function (host, port, path, user, pass)
3879
local form = stdnse.output_table()
3880
form.textuser=user
3881
form.textpass=pass
3882
form.Submit="Login"
3883
form.randstr=math.random()
3884
local resp = http_post_simple(host, port,
3885
url.absolute(path, "fake_server.html"),
3886
nil, form)
3887
return resp.status == 200
3888
and (resp.body or ""):find("%Wlocation%.href%s*=%s*['\"][^'\"]-/main_frame%.html%?")
3889
end
3890
})
3891
3892
table.insert(fingerprints, {
3893
name = "ZyXEL Prestige",
3894
category = "routers",
3895
paths = {
3896
{path = "/"}
3897
},
3898
target_check = function (host, port, path, response)
3899
local realm = http_auth_realm(response) or ""
3900
return realm:find("^Prestige ")
3901
or realm:find("^P[%u-]*645ME")
3902
end,
3903
login_combos = {
3904
{username = "admin", password = "1234"}
3905
},
3906
login_check = function (host, port, path, user, pass)
3907
return try_http_auth(host, port, path, user, pass, false)
3908
end
3909
})
3910
3911
table.insert(fingerprints, {
3912
name = "ZyXEL ZyWALL (var.1)",
3913
category = "routers",
3914
paths = {
3915
{path = "/"}
3916
},
3917
target_check = function (host, port, path, response)
3918
return have_openssl
3919
and response.status == 200
3920
and (response.header["server"] or ""):find("^RomPager/%d+%.")
3921
and response.body
3922
and response.body:find("rpAuth.html", 1, true)
3923
and response.body:find("%WchangeURL%(%s*(['\"])[^'\"]-%f[%w]rpAuth%.html%1%s*%)")
3924
end,
3925
login_combos = {
3926
{username = "", password = "1234"}
3927
},
3928
login_check = function (host, port, path, user, pass)
3929
local form = {LoginPassword="ZyXEL ZyWALL Series",
3930
hiddenPassword=stdnse.tohex(openssl.md5(pass)),
3931
Prestige_Login="Login"}
3932
local resp = http_post_simple(host, port,
3933
url.absolute(path, "Forms/rpAuth_1"),
3934
nil, form)
3935
return resp.status == 303
3936
and (resp.header["location"] or ""):find("/passWarning%.html$")
3937
end
3938
})
3939
3940
table.insert(fingerprints, {
3941
name = "ZyXEL ZyWALL (var.2)",
3942
category = "routers",
3943
paths = {
3944
{path = "/"}
3945
},
3946
target_check = function (host, port, path, response)
3947
return response.status == 200
3948
and response.body
3949
and response.body:find("ZyWALL", 1, true)
3950
and response.body:lower():find("<title>zywall %w")
3951
and get_tag(response.body, "input", {name="^pwd_r$"})
3952
end,
3953
login_combos = {
3954
{username = "admin", password = "1234"}
3955
},
3956
login_check = function (host, port, path, user, pass)
3957
local form = {username=user,
3958
pwd=pass,
3959
pwd_r="",
3960
password=pass}
3961
local resp = http_post_simple(host, port, path, nil, form)
3962
return resp.status == 302
3963
and resp.header["location"] == "ext-js/web-pages/login/chgpw.html"
3964
and get_cookie(resp, "authtok", "^[%w+-]+$")
3965
end
3966
})
3967
3968
table.insert(fingerprints, {
3969
name = "Adtran NetVanta",
3970
cpe = "cpe:/h:adtran:netvanta_*",
3971
category = "routers",
3972
paths = {
3973
{path = "/"}
3974
},
3975
target_check = function (host, port, path, response)
3976
return (http_auth_realm(response) or ""):find("^NetVanta %d+%f[ \0]")
3977
end,
3978
login_combos = {
3979
{username = "admin", password = "password"}
3980
},
3981
login_check = function (host, port, path, user, pass)
3982
return try_http_auth(host, port, path, user, pass, false)
3983
end
3984
})
3985
3986
table.insert(fingerprints, {
3987
name = "Siemens Gigaset SX762/763",
3988
cpe = "cpe:/h:siemens:gigaset_sx76*",
3989
category = "routers",
3990
paths = {
3991
{path = "/"}
3992
},
3993
target_check = function (host, port, path, response)
3994
return response.status == 303
3995
and (response.header["server"] or ""):find("^SiemensGigaset%-Server/%d+%.")
3996
and (response.header["location"] or ""):find("/UE/welcome_login%.html$")
3997
end,
3998
login_combos = {
3999
{username = "", password = "admin"}
4000
},
4001
login_check = function (host, port, path, user, pass)
4002
local form = {form_submission_type="login",
4003
form_submission_parameter="",
4004
current_page="welcome_login.html",
4005
next_page="home_security.html",
4006
i=1,
4007
admin_role_name="administrator",
4008
operator_role_name="operator",
4009
subscriber_role_name="subscriber",
4010
choose_role=0,
4011
your_password=pass,
4012
Login="OK"}
4013
local resp = http_post_simple(host, port,
4014
url.absolute(path, "UE/ProcessForm"),
4015
nil, form)
4016
return resp.status == 303
4017
and (resp.header["location"] or ""):find("/UE/home_security%.html$")
4018
end
4019
})
4020
4021
table.insert(fingerprints, {
4022
name = "Siemens Scalance X-200",
4023
cpe = "cpe:/o:siemens:scalance_x-200_series_firmware",
4024
category = "routers",
4025
paths = {
4026
{path = "/"}
4027
},
4028
target_check = function (host, port, path, response)
4029
return have_openssl
4030
and response.status == 200
4031
and get_cookie(response, "siemens_ad_session", "^%x+")
4032
and response.body
4033
and response.body:find(" SCALANCE X ", 1, true)
4034
and get_tag(response.body, "input", {name="^nonceA$"})
4035
end,
4036
login_combos = {
4037
{username = "admin", password = "admin"},
4038
{username = "user", password = "user"}
4039
},
4040
login_check = function (host, port, path, user, pass)
4041
local resp1 = http_get_simple(host, port, path)
4042
if not (resp1.status == 200 and resp1.body) then return false end
4043
local nonce = get_tag(resp1.body, "input", {name="^nonceA$", value="^%x+$"})
4044
if not nonce then return false end
4045
local auth = stdnse.tohex(openssl.md5(table.concat({user, pass, nonce.value}, ":")))
4046
local resp2 = http_post_simple(host, port, path, {cookies=resp1.cookies},
4047
{encoded=user..":"..auth, nonceA=nonce.value})
4048
return resp2.status == 200
4049
and (resp2.body or ""):find("%Wlocation%.href%s*=%s*(['\"])index1%.html%1")
4050
end
4051
})
4052
4053
table.insert(fingerprints, {
4054
name = "Siemens Scalance M873/M875",
4055
category = "routers",
4056
paths = {
4057
{path = "/"}
4058
},
4059
target_check = function (host, port, path, response)
4060
return (http_auth_realm(response) or ""):find("^SCALANCE M%-?87%d%f[%D]")
4061
end,
4062
login_combos = {
4063
{username = "admin", password = "scalance"}
4064
},
4065
login_check = function (host, port, path, user, pass)
4066
return try_http_auth(host, port, path, user, pass, true)
4067
end
4068
})
4069
4070
table.insert(fingerprints, {
4071
name = "Siemens RUGGEDCOM WIN",
4072
cpe = "cpe:/h:siemens:ruggedcom_win*",
4073
category = "routers",
4074
paths = {
4075
{path = "/"}
4076
},
4077
target_check = function (host, port, path, response)
4078
return http_auth_realm(response) == ""
4079
and get_cookie(response, "sessionId", "^%d+$")
4080
and (response.header["server"] or ""):find("^BS/%d+%.")
4081
end,
4082
login_combos = {
4083
{username = "admin", password = "generic"}
4084
},
4085
login_check = function (host, port, path, user, pass)
4086
local resp1 = http_get_simple(host, port, path)
4087
if not get_cookie(resp1, "sessionId", "^%d+$") then return false end
4088
local resp2 = http_get_simple(host, port, path,
4089
{cookies=resp1.cookies,
4090
auth={username=user,password=pass}})
4091
return resp2.status == 200
4092
and get_refresh_url(resp2.body, "/0/m%d+$")
4093
end
4094
})
4095
4096
table.insert(fingerprints, {
4097
name = "Siemens RUGGEDCOM ROS (var.1)",
4098
cpe = "cpe:/o:siemens:ruggedcom_rugged_operating_system",
4099
category = "routers",
4100
paths = {
4101
{path = "/"}
4102
},
4103
target_check = function (host, port, path, response)
4104
local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")
4105
if not (response.status == 302
4106
and loc:find("/InitialPage%.asp$")) then
4107
return false
4108
end
4109
local resp = http_get_simple(host, port, loc)
4110
return resp.status == 200
4111
and resp.body
4112
and resp.body:find("RuggedSwitch Operating System", 1, true)
4113
and get_tag(resp.body, "a", {href="^Menu%.asp%?UID=%d+$"})
4114
end,
4115
login_combos = {
4116
{username = "admin", password = "admin"},
4117
{username = "operator", password = "operator"},
4118
{username = "guest", password = "guest"}
4119
},
4120
login_check = function (host, port, path, user, pass)
4121
local resp1 = http_get_simple(host, port,
4122
url.absolute(path, "InitialPage.asp"))
4123
if not (resp1.status == 200 and resp1.body) then return false end
4124
local llink = get_tag(resp1.body, "a", {href="^Menu%.asp%?UID=%d+$"})
4125
if not llink then return false end
4126
local lurl = url.absolute(path, llink.href)
4127
local resp2 = http_get_simple(host, port, lurl)
4128
if resp2.status ~= 401 then return false end
4129
return try_http_auth(host, port, lurl, user, pass, false)
4130
end
4131
})
4132
4133
table.insert(fingerprints, {
4134
name = "Siemens RUGGEDCOM ROS (var.2)",
4135
cpe = "cpe:/o:siemens:ruggedcom_rugged_operating_system",
4136
category = "routers",
4137
paths = {
4138
{path = "/"}
4139
},
4140
target_check = function (host, port, path, response)
4141
local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")
4142
if not (response.status == 302
4143
and loc:find("/InitialPage%.asp$")) then
4144
return false
4145
end
4146
local resp = http_get_simple(host, port, loc)
4147
return resp.status == 200
4148
and resp.body
4149
and resp.body:find("goahead.gif", 1, true)
4150
and resp.body:find("LogIn", 1, true)
4151
and get_tag(resp.body, "form", {action="/goform/postLoginData%?UID=%d+$"})
4152
end,
4153
login_combos = {
4154
{username = "admin", password = "admin"},
4155
{username = "operator", password = "operator"},
4156
{username = "guest", password = "guest"}
4157
},
4158
login_check = function (host, port, path, user, pass)
4159
local resp1 = http_get_simple(host, port,
4160
url.absolute(path, "InitialPage.asp"))
4161
if not (resp1.status == 200 and resp1.body) then return false end
4162
local frm = get_tag(resp1.body, "form", {action="/goform/postLoginData%?UID=%d+$"})
4163
if not frm then return false end
4164
local form = {User=user,
4165
Password=pass,
4166
choice="LogIn"}
4167
local resp2 = http_post_simple(host, port, url.absolute(path, frm.action),
4168
nil, form)
4169
return (resp2.status == 203 or resp2.status == 200)
4170
and get_tag(resp2.body or "", "a", {href="/logout%.asp%?uid=%d+$"})
4171
end
4172
})
4173
4174
table.insert(fingerprints, {
4175
name = "Siemens RUGGEDCOM ROX",
4176
category = "routers",
4177
paths = {
4178
{path = "/login.html"}
4179
},
4180
target_check = function (host, port, path, response)
4181
return response.status == 200
4182
and response.body
4183
and response.body:find("/skins/macified/styles/master.css", 1, true)
4184
and response.body:find("confdLogin();", 1, true)
4185
and get_tag(response.body, "a", {onclick="^confdlogin%(%);"})
4186
and get_tag(response.body, "body", {onload="^loadbannercontent%(%);"})
4187
end,
4188
login_combos = {
4189
{username = "admin", password = "admin"},
4190
{username = "oper", password = "oper"},
4191
{username = "guest", password = "guest"}
4192
},
4193
login_check = function (host, port, path, user, pass)
4194
local resp = http_post_simple(host, port, url.absolute(path, "confd/login"),
4195
nil, {user=user,passwd=pass})
4196
return resp.status == 200
4197
and (resp.body or ""):find("^(['\"])sess%d+%1$")
4198
end
4199
})
4200
4201
table.insert(fingerprints, {
4202
name = "VideoFlow DVP",
4203
category = "routers",
4204
paths = {
4205
{path = "/login.html"}
4206
},
4207
target_check = function (host, port, path, response)
4208
return response.status == 200
4209
and response.body
4210
and response.body:find("/skins/macified/styles/master.css", 1, true)
4211
and response.body:find("confdLogin();", 1, true)
4212
and get_tag(response.body, "a", {onclick="^confdlogin%(%);"})
4213
and get_tag(response.body, "body", {onload="^document%.form%.username%.focus%(%);"})
4214
end,
4215
login_combos = {
4216
{username = "root", password = "videoflow"},
4217
{username = "admin", password = "admin"},
4218
{username = "oper", password = "oper"},
4219
{username = "private", password = "private"},
4220
{username = "public", password = "public"},
4221
{username = "devel", password = "leved"}
4222
},
4223
login_check = function (host, port, path, user, pass)
4224
local resp = http_post_simple(host, port, url.absolute(path, "confd/login"),
4225
nil, {user=user,passwd=pass})
4226
return resp.status == 200
4227
and (resp.body or ""):find("^(['\"])sess%d+%1$")
4228
end
4229
})
4230
4231
table.insert(fingerprints, {
4232
name = "Foxconn Femtocell",
4233
category = "routers",
4234
paths = {
4235
{path = "/"}
4236
},
4237
target_check = function (host, port, path, response)
4238
return response.status == 200
4239
and response.body
4240
and response.body:find("login.cgi", 1, true)
4241
and get_tag(response.body, "form", {action="^cgi%-bin/login%.cgi$"})
4242
and response.body:lower():find("<title>femtocell management system</title>", 1, true)
4243
end,
4244
login_combos = {
4245
{username = "admin", password = "admin"}
4246
},
4247
login_check = function (host, port, path, user, pass)
4248
local lurl = ("cgi-bin/login.cgi?username=%s&password=%s&Submit=Login"):format(
4249
url.escape(user), url.escape(pass))
4250
local resp = http_get_simple(host, port, url.absolute(path, lurl))
4251
return resp.status == 200
4252
and get_cookie(resp, "sessionID", ".")
4253
and (resp.body or ""):find("%Wwindow%.location%s*=%s*(['\"])mainFrame%.cgi%1")
4254
end
4255
})
4256
4257
table.insert(fingerprints, {
4258
name = "Datum Systems SnIP",
4259
cpe = "cpe:/o:datumsystems:snip",
4260
category = "routers",
4261
paths = {
4262
{path = "/"}
4263
},
4264
target_check = function (host, port, path, response)
4265
return (http_auth_realm(response) or ""):find("^SnIP%d+$")
4266
end,
4267
login_combos = {
4268
{username = "admin", password = "admin"}
4269
},
4270
login_check = function (host, port, path, user, pass)
4271
return try_http_auth(host, port, path, user, pass, false)
4272
end
4273
})
4274
4275
table.insert(fingerprints, {
4276
name = "Option GlobeSurfer II",
4277
category = "routers",
4278
paths = {
4279
{path = "/"}
4280
},
4281
target_check = function (host, port, path, response)
4282
return have_openssl
4283
and response.status == 200
4284
and response.body
4285
and response.body:find("GlobeSurfer II", 1, true)
4286
and response.body:find("%Wf%.action%s*=%s*(['\"])[^'\"]-/cache/%d+/upgrade%.cgi%1")
4287
and get_cookie(response, "session_id", "^%d+$")
4288
end,
4289
login_combos = {
4290
{username = "admin", password = "admin"},
4291
{username = "admin", password = ""}
4292
},
4293
login_check = function (host, port, path, user, pass)
4294
local resp1 = http_get_simple(host, port, path)
4295
if not (resp1.status == 200 and resp1.body) then return false end
4296
local page2 = get_tag(resp1.body, "input", {name="^active_page$", value="^%d+$"})
4297
local url2 = resp1.body:match(".*%Wfunction%s+mimic_button%s*%([^}]-%Wcase%s+0%s*:[^}]-%Wf%.action%s*=%s*['\"]([^'\"]-/cache/%d+/index%.cgi)['\"]")
4298
if not (page2 and url2) then return false end
4299
local form2 = {active_page=page2.value,
4300
prev_page=0,
4301
page_title="Connection status",
4302
nav_stack_0=page2.value,
4303
mimic_button_field="sidebar: sidebar_logout..",
4304
button_value="",
4305
transaction_id=0}
4306
local resp2 = http_post_simple(host, port, url2,
4307
{cookies=resp1.cookies}, form2)
4308
if not (resp2.status == 200 and resp2.body) then return false end
4309
local authkey = get_tag(resp2.body, "input", {name="^auth_key$", value="^%d+$"})
4310
local transid = get_tag(resp2.body, "input", {name="^transaction_id$", value="^%d+$"})
4311
local page3 = get_tag(resp2.body, "input", {name="^active_page$", value="^%d+$"})
4312
local url3 = resp2.body:match(".*%Wfunction%s+mimic_button%s*%([^}]-%Wcase%s+0%s*:[^}]-%Wf%.action%s*=%s*['\"]([^'\"]-/cache/(%d+)/index%.cgi)['\"]")
4313
if not (authkey and transid and page3 and url3) then return false end
4314
local form3 = {active_page=page3.value,
4315
prev_page=page2.value,
4316
page_title="Login",
4317
nav_stack_0=page3.value,
4318
["nav_" .. page3.value .. "_button_value"]="sidebar_logout",
4319
mimic_button_field="submit_button_login_submit: ..",
4320
button_value="sidebar_logout",
4321
transaction_id=transid.value,
4322
lang=0,
4323
user_name=user,
4324
["password_" .. get_cookie(resp2, "session_id")]="",
4325
md5_pass=stdnse.tohex(openssl.md5(pass .. authkey.value)),
4326
auth_key=authkey.value}
4327
local resp3 = http_post_simple(host, port, url3,
4328
{cookies=resp2.cookies}, form3)
4329
return resp3.status == 200
4330
and (resp3.body or ""):find("sidebar%5Fadvanced..", 1, true)
4331
end
4332
})
4333
4334
table.insert(fingerprints, {
4335
name = "Option GlobeSurfer III",
4336
category = "routers",
4337
paths = {
4338
{path = "/"}
4339
},
4340
target_check = function (host, port, path, response)
4341
return have_openssl
4342
and response.status == 200
4343
and response.body
4344
and response.body:find("md5_pass", 1, true)
4345
and response.body:lower():find("<title>[^<]-globesurfer%W")
4346
and get_cookie(response, "rg_cookie_session_id", "^%d+$")
4347
end,
4348
login_combos = {
4349
{username = "admin", password = "admin"},
4350
{username = "admin", password = ""}
4351
},
4352
login_check = function (host, port, path, user, pass)
4353
local resp1 = http_get_simple(host, port, path)
4354
if not (resp1.status == 200 and resp1.body) then return false end
4355
local authkey = get_tag(resp1.body, "input", {name="^auth_key$", value="^%d+$"})
4356
if not authkey then return false end
4357
local form = {active_page="page_login",
4358
prev_page="",
4359
page_title="Login",
4360
mimic_button_field="submit_button_login_submit: ..",
4361
button_value="",
4362
strip_page_top=0,
4363
page_title_text="Login",
4364
page_icon_number=30,
4365
defval_lang=0,
4366
defval_username="",
4367
md5_pass=stdnse.tohex(openssl.md5(pass .. authkey.value)),
4368
auth_key=authkey.value,
4369
lang=0,
4370
username=user,
4371
["password_" .. get_cookie(resp1, "rg_cookie_session_id")]=""}
4372
local resp2 = http_post_simple(host, port, url.absolute(path, "index.cgi"),
4373
{cookies=resp1.cookies}, form)
4374
return resp2.status == 302
4375
and (resp2.header["location"] or ""):find("active%5fpage=page%5fhome", 1, true)
4376
end
4377
})
4378
4379
table.insert(fingerprints, {
4380
name = "Digi TransPort",
4381
category = "routers",
4382
paths = {
4383
{path = "/login.asp"}
4384
},
4385
target_check = function (host, port, path, response)
4386
return response.status == 200
4387
and response.body
4388
and response.body:find("TransPort WR", 1, true)
4389
and response.body:lower():find("<title>transport wr", 1, true)
4390
and get_cookie(response, "SID", "^%x+$")
4391
end,
4392
login_combos = {
4393
{username = "username", password = "password"}
4394
},
4395
login_check = function (host, port, path, user, pass)
4396
local resp1 = http_get_simple(host, port, path)
4397
if not (resp1.status == 200 and resp1.cookies) then return false end
4398
local form = {username=user,
4399
password=pass,
4400
login="LOG IN"}
4401
local resp2 = http_post_simple(host, port, path,
4402
{cookies=resp1.cookies}, form)
4403
return resp2.status == 302
4404
and (resp2.header["location"] or ""):find("/default%.asp$")
4405
end
4406
})
4407
4408
table.insert(fingerprints, {
4409
name = "Sea Tel MXP",
4410
category = "routers",
4411
paths = {
4412
{path = "/"}
4413
},
4414
target_check = function (host, port, path, response)
4415
return response.status == 200
4416
and response.header["server"] == "Micro Digital Web Server"
4417
and response.body
4418
and response.body:find("MXP", 1, true)
4419
and response.body:lower():find("%Wwindow%.location%.href%s*=%s*(['\"])login%.html%1")
4420
end,
4421
login_combos = {
4422
{username = "Dealer", password = "seatel1"},
4423
{username = "SysAdmin", password = "seatel2"},
4424
{username = "User", password = "seatel3"}
4425
},
4426
login_check = function (host, port, path, user, pass)
4427
local form = {uId=user,
4428
uPwd=pass,
4429
uLoginMode="in",
4430
callConter=0}
4431
local resp = http_post_simple(host, port,
4432
url.absolute(path, "cgi-bin/userValidate"),
4433
nil, form)
4434
return resp.status == 200
4435
and (resp.body or ""):find("^%s*%^true%s*$")
4436
end
4437
})
4438
4439
table.insert(fingerprints, {
4440
name = "Thrane & Thrane Sailor 900 VSAT (var.1)",
4441
category = "routers",
4442
paths = {
4443
{path = "/"}
4444
},
4445
target_check = function (host, port, path, response)
4446
return response.status == 200
4447
and get_cookie(response, "tt_adm", "^%l+$")
4448
and response.body
4449
and get_tag(response.body, "form", {action="%?pageid=%w+$"})
4450
and get_tag(response.body, "input", {name="^pass_login$"})
4451
end,
4452
login_combos = {
4453
{username = "admin", password = "1234"}
4454
},
4455
login_check = function (host, port, path, user, pass)
4456
local resp1 = http_get_simple(host, port, path)
4457
if not (resp1.status == 200 and resp1.body) then return false end
4458
local frm = get_tag(resp1.body, "form", {action="%?pageid=%w+$"})
4459
if not frm then return false end
4460
local resp2 = http_post_simple(host, port, url.absolute(path, frm.action),
4461
nil, {user_login=user,pass_login=pass})
4462
return resp2.status == 200
4463
and url.unescape(get_cookie(resp2, "tt_adm", "%%3[Aa]") or ""):find(":" .. user .. ":", 1, true)
4464
end
4465
})
4466
4467
table.insert(fingerprints, {
4468
name = "Thrane & Thrane Sailor 900 VSAT (var.2)",
4469
category = "routers",
4470
paths = {
4471
{path = "/"}
4472
},
4473
target_check = function (host, port, path, response)
4474
return response.status == 200
4475
and get_cookie(response, "tt_adm", "^%l+$")
4476
and response.body
4477
and response.body:find("900 VSAT", 1, true)
4478
and get_tag(response.body, "a", {href="%?pageid=administration$"})
4479
end,
4480
login_combos = {
4481
{username = "admin", password = "1234"}
4482
},
4483
login_check = function (host, port, path, user, pass)
4484
local resp1 = http_get_simple(host, port, path)
4485
if not (resp1.status == 200 and resp1.body) then return false end
4486
local llink = get_tag(resp1.body, "a", {href="%?pageid=administration$"})
4487
if not llink then return false end
4488
local resp2 = http_post_simple(host, port, url.absolute(path, llink.href),
4489
nil, {user_login=user,pass_login=pass})
4490
return resp2.status == 200
4491
and url.unescape(get_cookie(resp2, "tt_adm", "%%3[Aa]") or ""):find(":" .. user .. ":", 1, true)
4492
end
4493
})
4494
4495
table.insert(fingerprints, {
4496
name = "Ubiquiti AirOS",
4497
category = "routers",
4498
paths = {
4499
{path = "/"}
4500
},
4501
target_check = function (host, port, path, response)
4502
if not (response.status == 302
4503
and (response.header["location"] or ""):find("/cookiechecker?uri=/", 1, true)) then
4504
return false
4505
end
4506
for _, ck in ipairs(response.cookies or {}) do
4507
if ck.name == "AIROS_SESSIONID" or ck.name:find("^AIROS_%x+$") then
4508
return ck.value:find("^%x+$")
4509
end
4510
end
4511
return false
4512
end,
4513
login_combos = {
4514
{username = "ubnt", password = "ubnt"}
4515
},
4516
login_check = function (host, port, path, user, pass)
4517
local resp = http_post_multipart(host, port,
4518
url.absolute(path, "login.cgi"), nil,
4519
{uri=path, username=user, password=pass})
4520
return resp.status == 302
4521
and resp.header["location"] == path
4522
end
4523
})
4524
4525
table.insert(fingerprints, {
4526
name = "Ubiquiti EdgeOS",
4527
category = "routers",
4528
paths = {
4529
{path = "/"}
4530
},
4531
target_check = function (host, port, path, response)
4532
return response.status == 200
4533
and response.body
4534
and response.body:find(">EdgeOS<", 1, true)
4535
and response.body:find("%WEDGE%.Config%s*=")
4536
and response.body:lower():find("<title>edgeos</title>")
4537
end,
4538
login_combos = {
4539
{username = "ubnt", password = "ubnt"}
4540
},
4541
login_check = function (host, port, path, user, pass)
4542
local resp = http_post_simple(host, port, path, nil,
4543
{username=user,password=pass})
4544
return (resp.status == 302 or resp.status == 303)
4545
and (resp.header["location"] or ""):sub(-#path) == path
4546
and get_cookie(resp, "PHPSESSID", "^%w+$")
4547
end
4548
})
4549
4550
table.insert(fingerprints, {
4551
name = "Ubiquiti EdgeSwitch",
4552
category = "routers",
4553
paths = {
4554
{path = "/"}
4555
},
4556
target_check = function (host, port, path, response)
4557
return response.status == 200
4558
and response.body
4559
and response.body:find(">Ubiquiti EdgeSwitch<", 1, true)
4560
and response.body:lower():find("<title>ubiquiti edgeswitch</title>")
4561
and get_tag(response.body, "script", {src="/static/scripts/bundle%-%x+%.js$"})
4562
end,
4563
login_combos = {
4564
{username = "ubnt", password = "ubnt"}
4565
},
4566
login_check = function (host, port, path, user, pass)
4567
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path})),
4568
["Content-Type"]="application/json",
4569
["Accept"]="application/json, text/plain, */*"}
4570
local jin = {username=user, password=pass}
4571
json.make_object(jin)
4572
local resp = http_post_simple(host, port,
4573
url.absolute(path, "api/v1.0/user/login"),
4574
{header=header}, json.generate(jin))
4575
return resp.status == 200
4576
and (resp.header["x-auth-token"] or ""):find("^%x+$")
4577
end
4578
})
4579
4580
table.insert(fingerprints, {
4581
name = "NetComm ADSL router",
4582
category = "routers",
4583
paths = {
4584
{path = "/"}
4585
},
4586
target_check = function (host, port, path, response)
4587
return (http_auth_realm(response) or ""):find("^NetComm ")
4588
end,
4589
login_combos = {
4590
{username = "admin", password = "admin"}
4591
},
4592
login_check = function (host, port, path, user, pass)
4593
return try_http_auth(host, port, path, user, pass, false)
4594
end
4595
})
4596
4597
table.insert(fingerprints, {
4598
name = "Netcomm NTC",
4599
category = "routers",
4600
paths = {
4601
{path = "/index.html"}
4602
},
4603
target_check = function (host, port, path, response)
4604
return response.status == 200
4605
and response.body
4606
and response.body:find("NetComm", 1, true)
4607
and response.body:lower():find("/netcomm_gui_banner.jpg", 1, true)
4608
and get_cookie(response, "_appwebSessionId_", "^%x+$")
4609
end,
4610
login_combos = {
4611
{username = "root", password = "admin"},
4612
{username = "admin", password = "admin"}
4613
},
4614
login_check = function (host, port, path, user, pass)
4615
local resp = http_post_simple(host, port, path, nil,
4616
{username=user,password=pass})
4617
return resp.status == 302
4618
and (resp.header["location"] or ""):find("/st[as]tus%.html%f[?\0]")
4619
end
4620
})
4621
4622
table.insert(fingerprints, {
4623
name = "Netcomm 3G17Wn",
4624
category = "routers",
4625
paths = {
4626
{path = "/"}
4627
},
4628
target_check = function (host, port, path, response)
4629
return response.status == 200
4630
and response.body
4631
and response.body:find(">3G17Wn", 1, true)
4632
and get_cookie(response, "_appwebSessionId_", "^%x+$")
4633
end,
4634
login_combos = {
4635
{username = "admin", password = "admin"}
4636
},
4637
login_check = function (host, port, path, user, pass)
4638
local resp = http_post_simple(host, port, path, nil,
4639
{username=user,password=pass})
4640
return resp.status == 302
4641
and (resp.header["location"] or ""):find("/adm/status%.asp$")
4642
end
4643
})
4644
4645
table.insert(fingerprints, {
4646
name = "NetComm 3G21WB",
4647
category = "routers",
4648
paths = {
4649
{path = "/"}
4650
},
4651
target_check = function (host, port, path, response)
4652
return response.status == 200
4653
and response.body
4654
and response.body:find("3G21WB", 1, true)
4655
and response.body:lower():find("<title>3g21wb", 1, true)
4656
and get_tag(response.body, "frame", {src="^menu%.html$"})
4657
end,
4658
login_combos = {
4659
{username = "admin", password = "admin"}
4660
},
4661
login_check = function (host, port, path, user, pass)
4662
return try_http_auth(host, port, url.absolute(path, "menu.html"),
4663
user, pass, false)
4664
end
4665
})
4666
4667
table.insert(fingerprints, {
4668
name = "NetComm 3G42WT",
4669
category = "routers",
4670
paths = {
4671
{path = "/"}
4672
},
4673
target_check = function (host, port, path, response)
4674
return response.status == 200
4675
and response.body
4676
and response.body:find("3G42WT", 1, true)
4677
and response.body:lower():find("<title>3g42wt", 1, true)
4678
and get_tag(response.body, "frame", {src="^login%.html$"})
4679
end,
4680
login_combos = {
4681
{username = "admin", password = "admin"}
4682
},
4683
login_check = function (host, port, path, user, pass)
4684
return try_http_auth(host, port, url.absolute(path, "login.html"),
4685
user, pass, false)
4686
end
4687
})
4688
4689
table.insert(fingerprints, {
4690
name = "PacketFront DRG600",
4691
category = "routers",
4692
paths = {
4693
{path = "/"}
4694
},
4695
target_check = function (host, port, path, response)
4696
return http_auth_realm(response) == "drg600.wifi"
4697
end,
4698
login_combos = {
4699
{username = "admin", password = ""}
4700
},
4701
login_check = function (host, port, path, user, pass)
4702
return try_http_auth(host, port, path, user, pass, false)
4703
end
4704
})
4705
4706
table.insert(fingerprints, {
4707
name = "Airlink ACEmanager",
4708
cpe = "cpe:/h:sierrawireless:airlink_mp_*",
4709
category = "routers",
4710
paths = {
4711
{path = "/"}
4712
},
4713
target_check = function (host, port, path, response)
4714
return response.status == 200
4715
and response.body
4716
and response.body:find("Sierra Wireless AirLink", 1, true)
4717
and response.body:lower():find("<title>:+%s+acemanager%s+:+</title>")
4718
end,
4719
login_combos = {
4720
{username = "user", password = "12345"}
4721
},
4722
login_check = function (host, port, path, user, pass)
4723
local encuser = xmlencode(user)
4724
local header = {["Content-Type"]="text/xml"}
4725
local msg = [=[
4726
<request xmlns="urn:acemanager">
4727
<connect>
4728
<login>__USER__</login>
4729
<password><![CDATA[__PASS__]]></password>
4730
</connect>
4731
</request>
4732
]=]
4733
msg = msg:gsub("%f[^\0\n]%s+", "")
4734
msg = msg:gsub("__%w+__", {__USER__=encuser, __PASS__=pass})
4735
local resp = http_post_simple(host, port,
4736
url.absolute(path, "xml/Connect.xml"),
4737
{header=header}, msg)
4738
return resp.status == 200 and get_cookie(resp, "token", "^%d+$")
4739
end
4740
})
4741
4742
table.insert(fingerprints, {
4743
name = "Mimosa Relay",
4744
category = "routers",
4745
paths = {
4746
{path = "/"}
4747
},
4748
target_check = function (host, port, path, response)
4749
return response.status == 200
4750
and response.body
4751
and response.body:find("Mimosa", 1, true)
4752
and response.body:find("%Wmimosa%.isConnected%s*=")
4753
end,
4754
login_combos = {
4755
{username = "configure", password = "mimosa"}
4756
},
4757
login_check = function (host, port, path, user, pass)
4758
local resp = http_post_simple(host, port,
4759
path .. "?q=index.login&mimosa_ajax=1",
4760
nil, {username=user,password=pass})
4761
if not (resp.status == 200 and resp.body) then return false end
4762
local jstatus, jout = json.parse(resp.body)
4763
return jstatus and (jout.role or 0) ~= 0
4764
end
4765
})
4766
4767
table.insert(fingerprints, {
4768
name = "IRTE Digital Radio Link",
4769
category = "routers",
4770
paths = {
4771
{path = "/"}
4772
},
4773
target_check = function (host, port, path, response)
4774
return response.status == 200
4775
and response.header["server"] == "Z-World Rabbit"
4776
and response.body
4777
and get_tag(response.body, "frame", {src="^objsum00%.html$"})
4778
end,
4779
login_combos = {
4780
{username = "", password = "0000"},
4781
{username = "", password = "111111"}
4782
},
4783
login_check = function (host, port, path, user, pass)
4784
local form1 = stdnse.output_table()
4785
form1.infield5 = 1
4786
form1.infield6 = pass
4787
local resp1 = http_post_multipart(host, port,
4788
url.absolute(path, "pswd.cgi"), nil, form1)
4789
if not (resp1.status == 200 and (resp1.body or ""):find("(['\"])password%.html%1")) then
4790
return false
4791
end
4792
local resp2 = http_get_simple(host, port,
4793
url.absolute(path, "password.html"))
4794
return resp2.status == 200
4795
and get_tag(resp2.body or "", "input", {name="^infield5$", value="^2$"})
4796
end
4797
})
4798
4799
table.insert(fingerprints, {
4800
name = "Motorola AP",
4801
category = "routers",
4802
paths = {
4803
{path = "/"}
4804
},
4805
target_check = function (host, port, path, response)
4806
return response.status == 200
4807
and (response.header["server"] or ""):find("^lighttpd/%d+%.")
4808
and response.body
4809
and response.body:find(">Motorola", 1, true)
4810
and response.body:lower():find("<title>motorola solutions</title>", 1, true)
4811
end,
4812
login_combos = {
4813
{username = "admin", password = "motorola"}
4814
},
4815
login_check = function (host, port, path, user, pass)
4816
local form = {_dc = math.floor(stdnse.clock_ms()),
4817
username = user,
4818
password = pass}
4819
local lurl = url.absolute(path, "rest.fcgi/services/rest/login?" .. url.build_query(form))
4820
local resp = http_get_simple(host, port, lurl)
4821
if not (resp.status == 200 and resp.body) then return false end
4822
local jstatus, jout = json.parse(resp.body)
4823
return jstatus and jout.status
4824
end
4825
})
4826
4827
table.insert(fingerprints, {
4828
name = "Motorola RF Switch",
4829
category = "routers",
4830
paths = {
4831
{path = "/"}
4832
},
4833
target_check = function (host, port, path, response)
4834
return response.status == 200
4835
and (response.header["server"] or ""):find("^thttpd/%d+%.")
4836
and response.body
4837
and response.body:find(">Motorola", 1, true)
4838
and response.body:lower():find("<title>motorola wireless network management</title>", 1, true)
4839
end,
4840
login_combos = {
4841
{username = "admin", password = "superuser"}
4842
},
4843
login_check = function (host, port, path, user, pass)
4844
local login = ("J20K34NMMT89XPIJ34S login %s %s"):format(stdnse.tohex(user), stdnse.tohex(pass))
4845
local lurl = url.absolute(path, "usmCgi.cgi/?" .. url.escape(login))
4846
local resp = http_get_simple(host, port, lurl)
4847
return resp.status == 200
4848
and (resp.body or ""):find("^login 0 ")
4849
end
4850
})
4851
4852
table.insert(fingerprints, {
4853
name = "Pakedge C36 Macrocell Controller",
4854
category = "routers",
4855
paths = {
4856
{path = "/"}
4857
},
4858
target_check = function (host, port, path, response)
4859
return response.status == 302
4860
and response.header["location"] == "./c36/login.php"
4861
end,
4862
login_combos = {
4863
{username = "pakedge", password = "pakedgec"}
4864
},
4865
login_check = function (host, port, path, user, pass)
4866
local form = {rtype="login",
4867
username=user,
4868
password=pass}
4869
local resp = http_post_simple(host, port,
4870
url.absolute(path, "c36/ajax/login.php"),
4871
nil, form)
4872
if not (resp.status == 200 and resp.body) then return false end
4873
local jstatus, jout = json.parse(resp.body)
4874
return jstatus and jout.ok
4875
end
4876
})
4877
4878
table.insert(fingerprints, {
4879
name = "ArubaOS WebUI",
4880
cpe = "cpe:/o:arubanetworks:arubaos",
4881
category = "routers",
4882
paths = {
4883
{path = "/"}
4884
},
4885
target_check = function (host, port, path, response)
4886
return response.status == 401
4887
and response.body
4888
and response.body:find("/images/arubalogo.gif", 1, true)
4889
and response.body:find("/screens/wms/wms.login", 1, true)
4890
end,
4891
login_combos = {
4892
{username = "admin", password = "admin"}
4893
},
4894
login_check = function (host, port, path, user, pass)
4895
local form = {opcode="login",
4896
url="/",
4897
needxml=0,
4898
uid=user,
4899
passwd=pass}
4900
local resp = http_post_simple(host, port,
4901
url.absolute(path, "screens/wms/wms.login"),
4902
nil, form)
4903
return resp.status == 200
4904
and (resp.body or ""):find("/screens/wmsi/monitor.summary.html", 1, true)
4905
end
4906
})
4907
4908
table.insert(fingerprints, {
4909
name = "Aruba AirWave",
4910
cpe = "cpe:/a:arubanetworks:airwave",
4911
category = "routers",
4912
paths = {
4913
{path = "/"}
4914
},
4915
target_check = function (host, port, path, response)
4916
return response.status == 200
4917
and response.body
4918
and response.body:find("/noauth/theme/airwave/favicon.ico", 1, true)
4919
and response.body:lower():find("%shref%s*=%s*(['\"])[^'\"]-/mercury%.%d+%.css%1")
4920
end,
4921
login_combos = {
4922
{username = "admin", password = "admin"}
4923
},
4924
login_check = function (host, port, path, user, pass)
4925
local form = {credential_0=user,
4926
credential_1=pass,
4927
destination=url.absolute(path, "index.html")}
4928
local resp = http_post_simple(host, port, url.absolute(path, "LOGIN"),
4929
nil, form)
4930
return resp.status == 302
4931
and (resp.header["location"] or ""):find("/index%.html$")
4932
end
4933
})
4934
4935
table.insert(fingerprints, {
4936
name = "Nortel VPN Router",
4937
cpe = "cpe:/h:nortel:vpn_router_*",
4938
category = "routers",
4939
paths = {
4940
{path = "/"}
4941
},
4942
target_check = function (host, port, path, response)
4943
return response.status == 200
4944
and response.header["server"] == "HTTP Server"
4945
and response.body
4946
and response.body:find(">Nortel", 1, true)
4947
and response.body:lower():find("<title>nortel vpn router</title>", 1, true)
4948
end,
4949
login_combos = {
4950
{username = "admin", password = "setup"}
4951
},
4952
login_check = function (host, port, path, user, pass)
4953
return try_http_auth(host, port, url.absolute(path, "manage/bdy_sys.htm"),
4954
user, pass, false)
4955
end
4956
})
4957
4958
table.insert(fingerprints, {
4959
name = "pfSense (var.1)",
4960
cpe = "cpe:/a:bsdperimeter:pfsense",
4961
category = "routers",
4962
paths = {
4963
{path = "/"}
4964
},
4965
target_check = function (host, port, path, response)
4966
return response.status == 200
4967
and response.body
4968
and response.body:find("/pfsense/login.css", 1, true)
4969
and get_tag(response.body, "form", {name="^login_iform$"})
4970
end,
4971
login_combos = {
4972
{username = "admin", password = "pfsense"}
4973
},
4974
login_check = function (host, port, path, user, pass)
4975
local form = {usernamefld=user,
4976
passwordfld=pass,
4977
login="Login"}
4978
local resp = http_post_simple(host, port, url.absolute(path, "index.php"),
4979
nil, form)
4980
return resp.status == 302
4981
and resp.header["location"] == path
4982
and get_cookie(resp, "PHPSESSID", "^%x+$")
4983
end
4984
})
4985
4986
table.insert(fingerprints, {
4987
name = "pfSense (var.2)",
4988
cpe = "cpe:/a:pfsense:pfsense",
4989
category = "routers",
4990
paths = {
4991
{path = "/"}
4992
},
4993
target_check = function (host, port, path, response)
4994
return response.status == 200
4995
and response.body
4996
and response.body:find("pfSense", 1, true)
4997
and get_tag(response.body, "input", {name="^__csrf_magic$"})
4998
end,
4999
login_combos = {
5000
{username = "admin", password = "pfsense"}
5001
},
5002
login_check = function (host, port, path, user, pass)
5003
local resp1 = http_get_simple(host, port, path)
5004
if not (resp1.status == 200 and resp1.body) then return false end
5005
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^__csrf_magic$", value=""})
5006
if not token then return false end
5007
local form = {[token.name]=token.value,
5008
usernamefld=user,
5009
passwordfld=pass,
5010
login=""}
5011
local resp2 = http_post_simple(host, port, url.absolute(path, "index.php"),
5012
{cookies=resp1.cookies}, form)
5013
return resp2.status == 302
5014
and resp2.header["location"] == path
5015
and get_cookie(resp2, "PHPSESSID", "^%w+$")
5016
end
5017
})
5018
5019
table.insert(fingerprints, {
5020
name = "ScreenOS",
5021
cpe = "cpe:/o:juniper:netscreen_screenos",
5022
category = "routers",
5023
paths = {
5024
{path = "/"}
5025
},
5026
target_check = function (host, port, path, response)
5027
return response.status == 200
5028
and (response.header["server"] or ""):find("^Virata%-EmWeb/R%d+_")
5029
and response.body
5030
and response.body:lower():find("admin_pw", 1, true)
5031
end,
5032
login_combos = {
5033
{username = "netscreen", password = "netscreen"}
5034
},
5035
login_check = function (host, port, path, user, pass)
5036
local form = {admin_id="",
5037
admin_pw="",
5038
time=tostring(math.floor(stdnse.clock_ms())):sub(5),
5039
un=base64.enc(user),
5040
pw=base64.enc(pass)}
5041
local resp = http_post_simple(host, port, url.absolute(path, "index.html"),
5042
nil, form)
5043
return resp.status == 303
5044
and (resp.header["location"] or ""):find("/nswebui.html?", 1, true)
5045
end
5046
})
5047
5048
table.insert(fingerprints, {
5049
name = "F5 TMOS",
5050
cpe = "cpe:/o:f5:tmos",
5051
category = "routers",
5052
paths = {
5053
{path = "/"}
5054
},
5055
target_check = function (host, port, path, response)
5056
return response.status == 200
5057
and response.body
5058
and response.body:find("F5 Networks", 1, true)
5059
and response.body:find("BIG-IP", 1, true)
5060
and response.body:find("/tmui/tmui/system/settings/redirect.jsp", 1, true)
5061
end,
5062
login_combos = {
5063
{username = "admin", password = "admin"}
5064
},
5065
login_check = function (host, port, path, user, pass)
5066
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "tmui/login.jsp")}))}
5067
local resp = http_post_simple(host, port,
5068
url.absolute(path, "tmui/logmein.html?"),
5069
{header=header}, {username=user,passwd=pass})
5070
return resp.status == 302
5071
and get_cookie(resp, "BIGIPAuthCookie", "^%x+$")
5072
end
5073
})
5074
5075
table.insert(fingerprints, {
5076
name = "F5 BIG-IQ",
5077
cpe = "cpe:/a:f5:big-iq_centralized_management",
5078
category = "routers",
5079
paths = {
5080
{path = "/"}
5081
},
5082
target_check = function (host, port, path, response)
5083
return response.status == 301
5084
and response.header["server"] == "webd"
5085
and (response.header["location"] or ""):find("/ui/login/?$")
5086
end,
5087
login_combos = {
5088
{username = "admin", password = "admin"}
5089
},
5090
login_check = function (host, port, path, user, pass)
5091
local header = {["Content-Type"]="application/json;charset=utf-8"}
5092
local jin = {username=user, password=pass, needsToken=true}
5093
json.make_object(jin)
5094
local resp = http_post_simple(host, port,
5095
url.absolute(path, "mgmt/shared/authn/login"),
5096
{header=header}, json.generate(jin))
5097
if not (resp.status == 200 and resp.body) then return false end
5098
local jstatus, jout = json.parse(resp.body)
5099
return jstatus and jout.username == user and jout.token
5100
end
5101
})
5102
5103
table.insert(fingerprints, {
5104
name = "Citrix NetScaler",
5105
cpe = "cpe:/a:citrix:netscaler",
5106
category = "routers",
5107
paths = {
5108
{path = "/"}
5109
},
5110
target_check = function (host, port, path, response)
5111
return response.status == 200
5112
and response.body
5113
and response.body:find("NetScaler", 1, true)
5114
and response.body:lower():find("<title>citrix login</title>", 1, true)
5115
end,
5116
login_combos = {
5117
{username = "nsroot", password = "nsroot"}
5118
},
5119
login_check = function (host, port, path, user, pass)
5120
local form = {username=user,
5121
password=pass,
5122
url="",
5123
timezone_offset=0}
5124
local resp = http_post_simple(host, port,
5125
url.absolute(path, "login/do_login"),
5126
nil, form)
5127
return resp.status == 302
5128
and (resp.header["location"] or ""):find("/menu/neo$")
5129
and get_cookie(resp, "startupapp") == "neo"
5130
end
5131
})
5132
5133
table.insert(fingerprints, {
5134
name = "Citrix NetScaler MAS",
5135
category = "routers",
5136
paths = {
5137
{path = "/"}
5138
},
5139
target_check = function (host, port, path, response)
5140
return response.status == 302
5141
and (response.header["location"] or ""):find("/admin_ui/mas/ent/login%.html$")
5142
end,
5143
login_combos = {
5144
{username = "nsroot", password = "nsroot"}
5145
},
5146
login_check = function (host, port, path, user, pass)
5147
local jin = {login={username=user,password=pass}}
5148
json.make_object(jin)
5149
local resp = http_post_simple(host, port,
5150
url.absolute(path, "nitro/v1/config/login"),
5151
nil, {object=json.generate(jin)})
5152
if not (resp.status == 200 and resp.body) then return false end
5153
local jstatus, jout = json.parse(resp.body)
5154
return jstatus and jout.errorcode == 0 and jout.resourceName == user
5155
end
5156
})
5157
5158
---
5159
--VoIP
5160
---
5161
table.insert(fingerprints, {
5162
name = "Aastra IP Phone",
5163
category = "voip",
5164
paths = {
5165
{path = "/"}
5166
},
5167
target_check = function (host, port, path, response)
5168
return (http_auth_realm(response) or ""):find("^Aastra %d+i$")
5169
end,
5170
login_combos = {
5171
{username = "admin", password = "22222"}
5172
},
5173
login_check = function (host, port, path, user, pass)
5174
return try_http_auth(host, port, path, user, pass, false)
5175
end
5176
})
5177
5178
table.insert(fingerprints, {
5179
name = "Aastra AXS 5000",
5180
category = "voip",
5181
paths = {
5182
{path = "/"}
5183
},
5184
target_check = function (host, port, path, response)
5185
local lurl = response.header["location"] or ""
5186
if not (response.status == 302 and lurl:find("/rhm$")) then return false end
5187
local resp = http_get_simple(host, port, lurl)
5188
return http_auth_realm(resp) == "Aastra 5000"
5189
end,
5190
login_combos = {
5191
{username = "admin", password = "admin"}
5192
},
5193
login_check = function (host, port, path, user, pass)
5194
return try_http_auth(host, port, url.absolute(path, "rhm"),
5195
user, pass, false)
5196
end
5197
})
5198
5199
table.insert(fingerprints, {
5200
name = "Aastra OpenCom 1000",
5201
category = "voip",
5202
paths = {
5203
{path = "/"}
5204
},
5205
target_check = function (host, port, path, response)
5206
return have_openssl
5207
and response.status == 200
5208
and response.body
5209
and response.body:find("OpenCom", 1, true)
5210
and response.body:lower():find("<title>opencom 1000</title>", 1, true)
5211
and get_tag(response.body, "frame", {src="/login%.html$"})
5212
end,
5213
login_combos = {
5214
{username = "Admin", password = "Admin"}
5215
},
5216
login_check = function (host, port, path, user, pass)
5217
local resp1 = http_get_simple(host, port, url.absolute(path, "login.html"))
5218
if not (resp1.status == 200 and resp1.body) then return false end
5219
local token = get_tag(resp1.body, "input", {name="^login$", value="^%x+$"})
5220
if not token then return false end
5221
pass = stdnse.tohex(openssl.md5(pass))
5222
local form2 = {login=stdnse.tohex(openssl.md5(token.value .. pass)),
5223
user=user,
5224
password="",
5225
ButtonOK="OK"}
5226
local resp2 = http_post_simple(host, port,
5227
url.absolute(path, "summary.html"),
5228
nil, form2)
5229
return resp2.status == 302
5230
and (resp2.header["location"] or ""):find("/%?uid=0x%x+$")
5231
end
5232
})
5233
5234
table.insert(fingerprints, {
5235
name = "Cisco TelePresence",
5236
category = "voip",
5237
paths = {
5238
{path = "/"}
5239
},
5240
target_check = function (host, port, path, response)
5241
return response.status == 302
5242
and (response.header["location"] or ""):find("/web/signin$")
5243
end,
5244
login_combos = {
5245
{username = "admin", password = ""}
5246
},
5247
login_check = function (host, port, path, user, pass)
5248
local resp = http_post_simple(host, port,
5249
url.absolute(path, "web/signin/open"), nil,
5250
{username=user, password=pass})
5251
if not (resp.status == 200 and resp.body) then return false end
5252
local jstatus, jout = json.parse(resp.body)
5253
return jstatus and jout.result == "ok"
5254
end
5255
})
5256
5257
table.insert(fingerprints, {
5258
name = "Dialogic PowerMedia XMS Console",
5259
category = "voip",
5260
paths = {
5261
{path = "/"}
5262
},
5263
target_check = function (host, port, path, response)
5264
return response.status == 200
5265
and response.body
5266
and response.body:find("/verifyLogin/", 1, true)
5267
and response.body:lower():find("<title>%s*dialogic xms admin console%s*</title>")
5268
end,
5269
login_combos = {
5270
{username = "viewer", password = "admin"},
5271
{username = "admin", password = "admin"},
5272
{username = "superadmin", password = "admin"}
5273
},
5274
login_check = function (host, port, path, user, pass)
5275
local resp = http_post_simple(host, port,
5276
url.absolute(path, "index.php/verifyLogin/login"),
5277
nil, {usernameId=user, passwordId=pass})
5278
return resp.status == 200
5279
and get_cookie(resp, "ci_session", "USERNAME")
5280
end
5281
})
5282
5283
table.insert(fingerprints, {
5284
name = "Dialogic PowerMedia XMS NodeController",
5285
category = "voip",
5286
paths = {
5287
{path = "/"}
5288
},
5289
target_check = function (host, port, path, response)
5290
return http_auth_realm(response) == "NodeController"
5291
end,
5292
login_combos = {
5293
{username = "admin", password = "admin"}
5294
},
5295
login_check = function (host, port, path, user, pass)
5296
return try_http_auth(host, port, path, user, pass, false)
5297
end
5298
})
5299
5300
table.insert(fingerprints, {
5301
name = "Dialogic PowerMedia XMS RESTful API",
5302
category = "voip",
5303
paths = {
5304
{path = "/"}
5305
},
5306
target_check = function (host, port, path, response)
5307
return http_auth_realm(response) == "XMS RESTful API"
5308
end,
5309
login_combos = {
5310
{username = "admin", password = "admin"}
5311
},
5312
login_check = function (host, port, path, user, pass)
5313
return try_http_auth(host, port, path, user, pass, false)
5314
end
5315
})
5316
5317
table.insert(fingerprints, {
5318
name = "Grandstream VoIP Device",
5319
category = "voip",
5320
paths = {
5321
{path = "/cgi-bin/login"}
5322
},
5323
target_check = function (host, port, path, response)
5324
return response.status == 200
5325
and response.body
5326
and response.body:find("Grandstream", 1, true)
5327
and response.body:lower():find("<title>grandstream ?device configuration</title>")
5328
and get_tag(response.body, "input", {name="^gnkey$", type="^hidden$", value="^0b82$"})
5329
end,
5330
login_combos = {
5331
{username = "", password = "admin"},
5332
{username = "", password = "123"}
5333
},
5334
login_check = function (host, port, path, user, pass)
5335
local resp = http_post_simple(host, port, url.absolute(path, "dologin"),
5336
nil, {P2=pass,Login="Login",gnkey="0b82"})
5337
return resp.status == 200 and get_cookie(resp, "session_id", "^%x+$")
5338
end
5339
})
5340
5341
table.insert(fingerprints, {
5342
name = "Grandstream GXP2200",
5343
category = "voip",
5344
paths = {
5345
{path = "/"}
5346
},
5347
target_check = function (host, port, path, response)
5348
return response.status == 200
5349
and response.body
5350
and response.body:find("%Wdocument%.title%s*=%s*(['\"])GXP2200%1")
5351
and response.body:lower():find("enterprise multimedia phone for android", 1, true)
5352
end,
5353
login_combos = {
5354
{username = "admin", password = "admin"},
5355
{username = "user", password = "123"}
5356
},
5357
login_check = function (host, port, path, user, pass)
5358
local form = {action="login",
5359
Username=user,
5360
Secret=pass,
5361
time=math.floor(stdnse.clock_ms())}
5362
local resp = http_get_simple(host, port,
5363
url.absolute(path, "manager?" .. url.build_query(form)))
5364
return resp.status == 200 and get_cookie(resp, "phonecookie", "^%x+$")
5365
end
5366
})
5367
5368
table.insert(fingerprints, {
5369
name = "Polycom SoundPoint (var.1)",
5370
category = "voip",
5371
paths = {
5372
{path = "/"}
5373
},
5374
target_check = function (host, port, path, response)
5375
return response.status == 200
5376
and response.body
5377
and response.body:find("Polycom", 1, true)
5378
and response.body:find("submitLoginInfo", 1, true)
5379
and response.body:lower():find("<title>polycom - configuration utility</title>", 1, true)
5380
and get_tag(response.body, "body", {onload="^document%.login%.password%.focus%(%)$"})
5381
end,
5382
login_combos = {
5383
{username = "Polycom", password = "456"},
5384
{username = "User", password = "123"}
5385
},
5386
login_check = function (host, port, path, user, pass)
5387
local qstr = url.build_query({t=os.date("!%a, %d %b %Y %H:%M:%S GMT")})
5388
return try_http_auth(host, port, url.absolute(path, "auth.htm?" .. qstr),
5389
user, pass, false)
5390
end
5391
})
5392
5393
table.insert(fingerprints, {
5394
name = "Polycom SoundPoint (var.2)",
5395
category = "voip",
5396
paths = {
5397
{path = "/"}
5398
},
5399
target_check = function (host, port, path, response)
5400
return response.status == 200
5401
and response.body
5402
and response.body:find("Polycom", 1, true)
5403
and response.body:find("submitLoginInfo", 1, true)
5404
and response.body:lower():find("<title>polycom - configuration utility</title>", 1, true)
5405
and get_tag(response.body, "input", {name="^password$", autocomplete="^off$"})
5406
end,
5407
login_combos = {
5408
{username = "Polycom", password = "456"},
5409
{username = "User", password = "123"}
5410
},
5411
login_check = function (host, port, path, user, pass)
5412
local creds = {username = user, password = pass, digest = false}
5413
local resp = http_post_simple(host, port,
5414
url.absolute(path, "form-submit/auth.htm"),
5415
{auth=creds}, "")
5416
return resp.status == 200
5417
and (resp.body or ""):find("|SUCCESS|", 1, true)
5418
end
5419
})
5420
5421
table.insert(fingerprints, {
5422
name = "Polycom SoundPoint (basic auth)",
5423
cpe = "cpe:/h:polycom:soundpoint_ip_*",
5424
category = "voip",
5425
paths = {
5426
{path = "/"}
5427
},
5428
target_check = function (host, port, path, response)
5429
return response.header["server"] == "Polycom SoundPoint IP Telephone HTTPd"
5430
and http_auth_realm(response) == "SPIP Configuration"
5431
end,
5432
login_combos = {
5433
{username = "Polycom", password = "456"}
5434
},
5435
login_check = function (host, port, path, user, pass)
5436
return try_http_auth(host, port, path, user, pass, false)
5437
end
5438
})
5439
5440
table.insert(fingerprints, {
5441
name = "Polycom RSS 4000",
5442
cpe = "cpe:/h:polycom:recording_and_streaming_server_4000",
5443
category = "voip",
5444
paths = {
5445
{path = "/portal/login.jsf"}
5446
},
5447
target_check = function (host, port, path, response)
5448
return response.status == 200
5449
and response.body
5450
and response.body:find("Polycom", 1, true)
5451
and response.body:lower():find("<title>polycom rss 4000</title>", 1, true)
5452
and get_tag(response.body, "input", {id="^loginform:username$"})
5453
end,
5454
login_combos = {
5455
{username = "admin", password = "admin"}
5456
},
5457
login_check = function (host, port, path, user, pass)
5458
local resp1 = http_get_simple(host, port, path)
5459
if not (resp1.status == 200 and resp1.body) then return false end
5460
local vstate = get_tag(resp1.body, "input", {name="^javax%.faces%.viewstate$", value="^%-?%d+:%-?%d+$"})
5461
if not vstate then return false end
5462
local opts2 = {header={["Faces-Request"]="partial/ajax"},
5463
cookies=resp1.cookies}
5464
local form2 = {loginForm="loginForm",
5465
["loginForm:userName"]=user,
5466
["loginForm:password"]=pass,
5467
["loginForm:domain"]="LOCAL",
5468
["javax.faces.ViewState"]=vstate.value,
5469
["javax.faces.source"]="loginForm:loginBt",
5470
["javax.faces.partial.event"]="click",
5471
["javax.faces.partial.execute"]="loginForm:loginBt @component",
5472
["javax.faces.partial.render"]="@component",
5473
["org.richfaces.ajax.component"]="loginForm:loginBt",
5474
["loginForm:loginBt"]="loginForm:loginBt",
5475
["AJAX:EVENTS_COUNT"]=1,
5476
["javax.faces.partial.ajax"]="true"}
5477
local resp2 = http_post_simple(host, port, path, opts2, form2)
5478
return resp2.status == 200
5479
and (resp2.body or ""):find("<complete>checkLogin('')", 1, true)
5480
end
5481
})
5482
5483
table.insert(fingerprints, {
5484
name = "Polycom RMX 500",
5485
cpe = "cpe:/h:polycom:rmx_500",
5486
category = "voip",
5487
paths = {
5488
{path = "/"}
5489
},
5490
target_check = function (host, port, path, response)
5491
return response.status == 200
5492
and response.body
5493
and response.body:find("<RMX1000_UI>", 1, true)
5494
and response.body:lower():find("<title></title>", 1, true)
5495
end,
5496
login_combos = {
5497
{username = "POLYCOM", password = "POLYCOM"}
5498
},
5499
login_check = function (host, port, path, user, pass)
5500
local msg = [[
5501
<?xml version="1.0" encoding="UTF-8" ?>
5502
<RMX1000_UI version="1.0.0.0">
5503
<FROM_PAGE id="login">
5504
<SESSION_ID value="" />
5505
<_CGI_NO_REFRESH value="YES" />
5506
<SEL_LANG value="en" />
5507
<IS_CGI value="YES" />
5508
<DEV_IP_V4 value="" />
5509
<LOGINNAME value="__USER__" />
5510
<PASSWD value="__PASS__" />
5511
<rmx1000_ip value="127.0.0.1" />
5512
<proxy_log_ip value="" />
5513
<LOGIN_FLAG value="__IPADDR__.__TSTAMP__" />
5514
<_CGI_UI_LANG value="en" />
5515
<cfg_ui_hide value="YES" />
5516
<_CGI_TIME value="__TIME__" />
5517
</FROM_PAGE>
5518
</RMX1000_UI>]]
5519
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
5520
msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),
5521
__PASS__=xmlencode(pass),
5522
__IPADDR__=xmlencode(host.ip),
5523
__TSTAMP__=math.floor(stdnse.clock_ms()),
5524
__TIME__=xmlencode(os.date("!%a %b %d %Y %H:%M:%S GMT+0000"))})
5525
local qstr = url.build_query({_dst_in_xml_raw=msg})
5526
local resp = http_get_simple(host, port,
5527
url.absolute(path, "cgi-bin/rmx_cgi?" .. qstr))
5528
return resp.status == 200
5529
and (resp.body or ""):find("<SESSION_ID>%x+</SESSION_ID>")
5530
end
5531
})
5532
5533
table.insert(fingerprints, {
5534
name = "Polycom RMX 1000",
5535
cpe = "cpe:/h:polycom:rmx_1000",
5536
category = "voip",
5537
paths = {
5538
{path = "/"}
5539
},
5540
target_check = function (host, port, path, response)
5541
return response.status == 200
5542
and response.body
5543
and response.body:find("<RMX1000_UI>", 1, true)
5544
and response.body:lower():find("<title>polycom rmx 1000</title>", 1, true)
5545
end,
5546
login_combos = {
5547
{username = "POLYCOM", password = "POLYCOM"}
5548
},
5549
login_check = function (host, port, path, user, pass)
5550
local msg = [[
5551
<?xml version="1.0" encoding="UTF-8" ?>
5552
<RMX1000_UI version="1.0.0.0">
5553
<FROM_PAGE id="login">
5554
<SESSION_ID value="" />
5555
<_CGI_NO_REFRESH value="NO" />
5556
<SEL_LANG value="en" />
5557
<IS_CGI value="YES" />
5558
<DEV_IP_V4 value="" />
5559
<LOGINNAME value="__USER__" />
5560
<PASSWD value="__PASS__" />
5561
<rmx1000_ip value="127.0.0.1" />
5562
<proxy_log_ip value="" />
5563
<_CGI_UI_LANG value="en" />
5564
<cfg_ui_hide value="YES" />
5565
<_CGI_TIME value="__TIME__" />
5566
</FROM_PAGE>
5567
</RMX1000_UI>]]
5568
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
5569
msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),
5570
__PASS__=xmlencode(stdnse.tohex(pass)),
5571
__TIME__=xmlencode(os.date("!%a %b %d %Y %H:%M:%S GMT+0000"))})
5572
local resp = http_post_simple(host, port,
5573
url.absolute(path, "cgi-bin/rmx1000_cgi"),
5574
nil, {_dst_in_xml_raw=msg})
5575
return resp.status == 200
5576
and (resp.body or ""):find("<SESSION_ID>%x+</SESSION_ID>")
5577
end
5578
})
5579
5580
table.insert(fingerprints, {
5581
name = "Polycom RPAD",
5582
category = "voip",
5583
paths = {
5584
{path = "/"}
5585
},
5586
target_check = function (host, port, path, response)
5587
return response.status == 200
5588
and response.header["server"] == "Polycom RPAD"
5589
and response.body
5590
and get_refresh_url(response.body, "/edge/$")
5591
end,
5592
login_combos = {
5593
{username = "LOCAL\\admin", password = "admin"}
5594
},
5595
login_check = function (host, port, path, user, pass)
5596
local form = {j_username=base64.enc(user),
5597
j_password=base64.enc(pass)}
5598
local resp = http_post_simple(host, port,
5599
url.absolute(path, "edge/security/check"),
5600
nil, form)
5601
if not (resp.status == 200 and resp.body) then return false end
5602
local jstatus, jout = json.parse(b64decode(resp.body:gsub("%s+","")) or "")
5603
return jstatus and jout.success
5604
end
5605
})
5606
5607
table.insert(fingerprints, {
5608
name = "Teles Gateway",
5609
category = "voip",
5610
paths = {
5611
{path = "/"}
5612
},
5613
target_check = function (host, port, path, response)
5614
return response.status == 200
5615
and response.header["server"] == "TELES AG"
5616
and response.body
5617
and get_tag(response.body, "frame", {src="/common/navibar_[%w_]+_login%.html$"})
5618
end,
5619
login_combos = {
5620
{username = "teles-admin", password = "tcs-admin"},
5621
{username = "teles-user", password = "tcs-user"},
5622
{username = "teles-carrier", password = "tcs-carrier"}
5623
},
5624
login_check = function (host, port, path, user, pass)
5625
local resp1 = http_get_simple(host, port, path)
5626
if not (resp1.status == 200 and resp1.body) then return false end
5627
local frame = get_tag(resp1.body, "frame", {src="/common/navibar_[%w_]+_login%.html$"})
5628
if not frame then return false end
5629
local nurl = url.absolute(path, frame.src)
5630
local resp2 = http_get_simple(host, port, nurl)
5631
if not (resp2.status == 200 and resp2.body) then return false end
5632
local lurl = resp2.body:lower():match("<a%f[%s][^>]-%shref%s*=%s*['\"]?([^'\">%s]*)[^>]*>login</a")
5633
if not lurl then return false end
5634
return try_http_auth(host, port, url.absolute(nurl, lurl), user, pass, false)
5635
end
5636
})
5637
5638
table.insert(fingerprints, {
5639
name = "Mediatrix",
5640
category = "voip",
5641
paths = {
5642
{path = "/"}
5643
},
5644
target_check = function (host, port, path, response)
5645
return response.status == 302
5646
and (response.header["location"] or ""):find("%f[^/\0]system_info%.esp$")
5647
end,
5648
login_combos = {
5649
{username = "admin", password = "admin"},
5650
{username = "admin", password = "administrator"},
5651
{username = "public", password = ""}
5652
},
5653
login_check = function (host, port, path, user, pass)
5654
local resp = http_post_simple(host, port, url.absolute(path, "login.esp"),
5655
nil, {username=user,passwd=pass})
5656
return resp.status == 302
5657
and (resp.header["location"] or ""):find("%f[^/\0]system_info%.esp$")
5658
end
5659
})
5660
5661
table.insert(fingerprints, {
5662
name = "Mediatrix (basic auth)",
5663
category = "voip",
5664
paths = {
5665
{path = "/"}
5666
},
5667
target_check = function (host, port, path, response)
5668
local realm = http_auth_realm(response)
5669
return (realm == "Mediatrix" or realm == "default")
5670
and (response.body or ""):lower():find("<title>authentication error: access denied, authorization required.</title>", 1, true)
5671
end,
5672
login_combos = {
5673
{username = "admin", password = "1234"},
5674
{username = "root", password = "5678"}
5675
},
5676
login_check = function (host, port, path, user, pass)
5677
return try_http_auth(host, port, path, user, pass, true)
5678
end
5679
})
5680
5681
table.insert(fingerprints, {
5682
name = "Mediatrix iPBX",
5683
category = "voip",
5684
paths = {
5685
{path = "/"}
5686
},
5687
target_check = function (host, port, path, response)
5688
return response.status == 200
5689
and response.body
5690
and response.body:find("PBX Administration", 1, true)
5691
and get_tag(response.body, "a", {href="^admin/$"})
5692
and response.body:lower():find("<title>ipbx</title>", 1, true)
5693
end,
5694
login_combos = {
5695
{username = "admin", password = "admin"}
5696
},
5697
login_check = function (host, port, path, user, pass)
5698
return try_http_auth(host, port, url.absolute(path, "admin/config.php"),
5699
user, pass, false)
5700
end
5701
})
5702
5703
table.insert(fingerprints, {
5704
name = "Openstage IP Phone",
5705
category = "voip",
5706
paths = {
5707
{path = "/"}
5708
},
5709
target_check = function (host, port, path, response)
5710
return response.status == 200
5711
and response.body
5712
and response.body:find("Unify", 1, true)
5713
and get_tag(response.body, "frame", {src="[?&]page=webmp_user_login%f[&\0]"})
5714
end,
5715
login_combos = {
5716
{username = "", password = "123456"}
5717
},
5718
login_check = function (host, port, path, user, pass)
5719
local form = {page_submit="WEBMp_Admin_Login",
5720
lang="en",
5721
AdminPassword=pass}
5722
local resp = http_post_simple(host, port, url.absolute(path, "page.cmd"),
5723
nil, form)
5724
return resp.status == 200
5725
and get_cookie(resp, "webm", "%d+|[%d-]*[1-9a-f][%d-]*")
5726
end
5727
})
5728
5729
table.insert(fingerprints, {
5730
name = "Yealink IP Phone",
5731
cpe = "cpe:/o:yealink:voip_phone_firmware",
5732
category = "voip",
5733
paths = {
5734
{path = "/"}
5735
},
5736
target_check = function (host, port, path, response)
5737
return (http_auth_realm(response) or ""):find(" IP [Pp]hone SIP%-%u%d+%u?$")
5738
end,
5739
login_combos = {
5740
{username = "admin", password = "admin"},
5741
{username = "user", password = "user"},
5742
{username = "var", password = "var"}
5743
},
5744
login_check = function (host, port, path, user, pass)
5745
return try_http_auth(host, port, path, user, pass, false)
5746
end
5747
})
5748
5749
---
5750
--Digital recorders
5751
---
5752
table.insert(fingerprints, {
5753
name = "DM Digital Sprite 2",
5754
category = "security",
5755
paths = {
5756
{path = "/"}
5757
},
5758
target_check = function (host, port, path, response)
5759
return response.status == 200
5760
and response.body
5761
and response.body:find("Dedicated Micros", 1, true)
5762
and response.body:find("webpages/index.shtml", 1, true)
5763
and get_tag(response.body, "meta", {name="^author$", content="^dedicated micros "})
5764
end,
5765
login_combos = {
5766
{username = "dm", password = "web"}
5767
},
5768
login_check = function (host, port, path, user, pass)
5769
return try_http_auth(host, port, url.absolute(path, "frmpages/index.html"),
5770
user, pass, true)
5771
end
5772
})
5773
5774
table.insert(fingerprints, {
5775
name = "DM NetVu",
5776
category = "security",
5777
paths = {
5778
{path = "/"}
5779
},
5780
target_check = function (host, port, path, response)
5781
return response.status == 200
5782
and response.body
5783
and response.body:find("Dedicated Micros", 1, true)
5784
and response.body:find("/gui/gui_outer_frame.shtml", 1, true)
5785
and get_tag(response.body, "meta", {name="^author$", content="^dedicated micros "})
5786
end,
5787
login_combos = {
5788
{username = "", password = ""}
5789
},
5790
login_check = function (host, port, path, user, pass)
5791
local lurl = url.absolute(path, "gui/frmpages/gui_system.shtml")
5792
local resp = http_get_simple(host, port, lurl)
5793
if resp.status == 200 then
5794
return (resp.body or ""):find('top.render_table("System Page"', 1, true)
5795
end
5796
return try_http_auth(host, port, lurl, user, pass, true)
5797
end
5798
})
5799
5800
table.insert(fingerprints, {
5801
name = "LevelOne WCS-0050 Camera",
5802
category = "security",
5803
paths = {
5804
{path = "/"}
5805
},
5806
target_check = function (host, port, path, response)
5807
return http_auth_realm(response) == "LevelOne WCS-0050"
5808
end,
5809
login_combos = {
5810
{username = "admin", password = "admin"}
5811
},
5812
login_check = function (host, port, path, user, pass)
5813
return try_http_auth(host, port, path, user, pass, false)
5814
end
5815
})
5816
5817
table.insert(fingerprints, {
5818
name = "LG Smart IP Device",
5819
category = "security",
5820
paths = {
5821
{path = "/"}
5822
},
5823
target_check = function (host, port, path, response)
5824
return response.status == 200
5825
and response.body
5826
and response.body:find(">LG Smart IP Device<", 1, true)
5827
and get_tag(response.body, "frame", {src="^login_org%.php$"})
5828
end,
5829
login_combos = {
5830
{username = "admin", password = "admin"}
5831
},
5832
login_check = function (host, port, path, user, pass)
5833
return try_http_auth(host, port, url.absolute(path, "digest.php"),
5834
user, pass, false)
5835
end
5836
})
5837
5838
table.insert(fingerprints, {
5839
name = "MOBOTIX Camera",
5840
category = "security",
5841
paths = {
5842
{path = "/"},
5843
{path = "/control/userimage.html"}
5844
},
5845
target_check = function (host, port, path, response)
5846
return response.status == 401
5847
and http_auth_realm(response)
5848
and response.body
5849
and response.body:find("MOBOTIX AG", 1, true)
5850
end,
5851
login_combos = {
5852
{username = "admin", password = "meinsm"}
5853
},
5854
login_check = function (host, port, path, user, pass)
5855
return try_http_auth(host, port, path, user, pass, false)
5856
end
5857
})
5858
5859
table.insert(fingerprints, {
5860
name = "OEM GoAhead-Webs IP Camera",
5861
category = "security",
5862
paths = {
5863
{path = "/"}
5864
},
5865
target_check = function (host, port, path, response)
5866
return response.header["server"] == "GoAhead-Webs"
5867
and http_auth_realm(response) == "GoAhead"
5868
end,
5869
login_combos = {
5870
{username = "admin", password = "888888"},
5871
{username = "admin", password = "12345"},
5872
{username = "admin", password = "123456"},
5873
{username = "admin", password = ""}
5874
},
5875
login_check = function (host, port, path, user, pass)
5876
return try_http_auth(host, port, path, user, pass, true)
5877
end
5878
})
5879
5880
table.insert(fingerprints, {
5881
name = "IPCC P2P Camera",
5882
category = "security",
5883
paths = {
5884
{path = "/"}
5885
},
5886
target_check = function (host, port, path, response)
5887
return response.header["server"] == "GoAhead-Webs"
5888
and http_auth_realm(response) == "WIFICAM"
5889
end,
5890
login_combos = {
5891
{username = "admin", password = "admin"}
5892
},
5893
login_check = function (host, port, path, user, pass)
5894
return try_http_auth(host, port, path, user, pass, true)
5895
end
5896
})
5897
5898
table.insert(fingerprints, {
5899
name = "AXIS 2100 Network Camera",
5900
cpe = "cpe:/h:axis:2100_network_camera",
5901
category = "security",
5902
paths = {
5903
{path = "/"}
5904
},
5905
target_check = function (host, port, path, response)
5906
return response.status == 200
5907
and (response.header["server"] or ""):find("^Boa/%d+%.")
5908
and response.body
5909
and response.body:find("AXIS", 1, true)
5910
and response.body:lower():find("<title>axis ", 1, true)
5911
end,
5912
login_combos = {
5913
{username = "root", password = "pass"},
5914
{username = "admin", password = "admin"}
5915
},
5916
login_check = function (host, port, path, user, pass)
5917
return try_http_auth(host, port, url.absolute(path, "view/view.shtml"),
5918
user, pass, false)
5919
end
5920
})
5921
5922
table.insert(fingerprints, {
5923
name = "AXIS C/M/P/V Series Device",
5924
category = "security",
5925
paths = {
5926
{path = "/"}
5927
},
5928
target_check = function (host, port, path, response)
5929
if response.status == 302 then
5930
if not (response.header["location"] or ""):find("/index%.shtml$") then
5931
return false
5932
end
5933
response = http_get_simple(host, port,
5934
url.absolute(path, "index.shtml"))
5935
end
5936
return response.status == 200
5937
and response.body
5938
and response.body:find("/axis-cgi/pwdroot/set_language.cgi?", 1, true)
5939
and response.body:lower():find("<title>index page</title>", 1, true)
5940
end,
5941
login_combos = {
5942
{username = "root", password = ""}
5943
},
5944
login_check = function (host, port, path, user, pass)
5945
local resp = http_get_simple(host, port,
5946
url.absolute(path, "pwdroot/pwdRoot.shtml"))
5947
return resp.status == 200
5948
and resp.body
5949
and get_tag(resp.body, "input", {value="^" .. user .. "$"})
5950
and get_tag(resp.body, "input", {name="^pwd_confirm$"})
5951
end
5952
})
5953
5954
table.insert(fingerprints, {
5955
name = "AXIS Network Video Door Station",
5956
category = "security",
5957
paths = {
5958
{path = "/"}
5959
},
5960
target_check = function (host, port, path, response)
5961
if response.status == 302 then
5962
if not (response.header["location"] or ""):find("/index%.shtml$") then
5963
return false
5964
end
5965
response = http_get_simple(host, port,
5966
url.absolute(path, "index.shtml"))
5967
end
5968
return response.status == 200
5969
and response.body
5970
and response.body:find("%Wvar%s+refreshUrl%s*=%s*(['\"])[^'\"]-/view/view%.shtml%?id=%d+%1")
5971
and response.body:lower():find("<title>index page</title>", 1, true)
5972
end,
5973
login_combos = {
5974
{username = "root", password = "pass"}
5975
},
5976
login_check = function (host, port, path, user, pass)
5977
local form = {id=math.random(1000,30000),
5978
imagepath=url.absolute(path, "mjpg/1/video.mjpg"),
5979
size=1}
5980
return try_http_auth(host, port,
5981
url.absolute(path, "view/view.shtml?" .. url.build_query(form)),
5982
user, pass, true)
5983
end
5984
})
5985
5986
table.insert(fingerprints, {
5987
name = "AXIS Entry Manager",
5988
category = "security",
5989
paths = {
5990
{path = "/"}
5991
},
5992
target_check = function (host, port, path, response)
5993
return response.status == 200
5994
and response.body
5995
and response.body:find("/webapp/pacs/index.shtml?id=", 1, true)
5996
and (response.body:find("%Wvar%s+refreshUrl%s*=%s*(['\"])[^'\"]-/webapp/pacs/index%.shtml%?id=%d+%1")
5997
or get_refresh_url(response.body, "/webapp/pacs/index%.shtml%?id=%d+$"))
5998
and response.body:lower():find("<title>index page</title>", 1, true)
5999
end,
6000
login_combos = {
6001
{username = "root", password = "pass"}
6002
},
6003
login_check = function (host, port, path, user, pass)
6004
local form = {action="list",
6005
group="Properties.System.Language",
6006
_=math.floor(stdnse.clock_ms())}
6007
return try_http_auth(host, port,
6008
url.absolute(path, "axis-cgi/param.cgi?" .. url.build_query(form)),
6009
user, pass, true)
6010
end
6011
})
6012
6013
table.insert(fingerprints, {
6014
name = "Panasonic Network Camera",
6015
category = "security",
6016
paths = {
6017
{path = "/"}
6018
},
6019
target_check = function (host, port, path, response)
6020
return response.status == 200
6021
and response.body
6022
and response.body:find("./live/index2.html?Language=", 1, true)
6023
and (response.body:find("%Wlocation%.replace%((['\"])%./live/index2%.html%?Language=%d+%1")
6024
or response.body:find("%Wwindow%.open%((['\"])%./live/index2%.html%?Language=%d+%1"))
6025
and response.body:lower():find("<title>%a%a%-%a%w+ ")
6026
end,
6027
login_combos = {
6028
{username = "admin", password = "12345"}
6029
},
6030
login_check = function (host, port, path, user, pass)
6031
return try_http_auth(host, port,
6032
url.absolute(path, "live/index2.html?Language=0"),
6033
user, pass, false)
6034
end
6035
})
6036
6037
table.insert(fingerprints, {
6038
name = "Sanyo Network Camera (no auth)",
6039
category = "security",
6040
paths = {
6041
{path = "/"}
6042
},
6043
target_check = function (host, port, path, response)
6044
if not (response.status == 200
6045
and response.body
6046
and response.body:find("SANYO", 1, true)
6047
and response.body:lower():find("<title>sanyo +network camera</title>")
6048
and get_tag(response.body, "form", {name="^lang_set$"})) then
6049
return false
6050
end
6051
local resp = http_get_simple(host, port,
6052
url.absolute(path, "cgi-bin/change_id.cgi"))
6053
return resp.status == 200
6054
end,
6055
login_combos = {
6056
{username = "", password = ""}
6057
},
6058
login_check = function (host, port, path, user, pass)
6059
return true
6060
end
6061
})
6062
6063
table.insert(fingerprints, {
6064
name = "Sanyo Network Camera (admin auth)",
6065
category = "security",
6066
paths = {
6067
{path = "/"}
6068
},
6069
target_check = function (host, port, path, response)
6070
if not (response.status == 200
6071
and response.body
6072
and response.body:find("SANYO", 1, true)
6073
and response.body:lower():find("<title>sanyo +network camera</title>")
6074
and get_tag(response.body, "form", {name="^lang_set$"})) then
6075
return false
6076
end
6077
local resp = http_get_simple(host, port,
6078
url.absolute(path, "cgi-bin/change_id.cgi"))
6079
return http_auth_realm(resp) == "You need advanced ID"
6080
end,
6081
login_combos = {
6082
{username = "admin", password = "admin"},
6083
{username = "admin2", password = "admin2"},
6084
{username = "admin3", password = "admin3"},
6085
{username = "operator", password = "operator"},
6086
{username = "guest", password = "guest"}
6087
},
6088
login_check = function (host, port, path, user, pass)
6089
local lurl = url.absolute(path, "cgi-bin/change_id.cgi?" .. math.floor(stdnse.clock_ms()))
6090
return try_http_auth(host, port, lurl, user, pass, false)
6091
end
6092
})
6093
6094
table.insert(fingerprints, {
6095
name = "Sanyo Network Camera (user auth)",
6096
category = "security",
6097
paths = {
6098
{path = "/"}
6099
},
6100
target_check = function (host, port, path, response)
6101
return http_auth_realm(response) == "You need ID"
6102
and response.body
6103
and response.body:lower():find("<title>sanyo network camera</title>", 1, true)
6104
end,
6105
login_combos = {
6106
{username = "admin", password = "admin"},
6107
{username = "admin2", password = "admin2"},
6108
{username = "admin3", password = "admin3"},
6109
{username = "operator", password = "operator"},
6110
{username = "guest", password = "guest"}
6111
},
6112
login_check = function (host, port, path, user, pass)
6113
return try_http_auth(host, port, path, user, pass, false)
6114
end
6115
})
6116
6117
table.insert(fingerprints, {
6118
name = "Sony Network Camera (Boa 1)",
6119
cpe = "cpe:/h:sony:snc_*",
6120
category = "security",
6121
paths = {
6122
{path = "/en/index.html"}
6123
},
6124
target_check = function (host, port, path, response)
6125
return response.status == 200
6126
and (response.header["server"] or ""):find("^Boa/%d+%.")
6127
and response.body
6128
and response.body:lower():find("%ssrc%s*=%s*(['\"])indexbar%.html%1")
6129
end,
6130
login_combos = {
6131
{username = "admin", password = "admin"}
6132
},
6133
login_check = function (host, port, path, user, pass)
6134
return try_http_auth(host, port, url.absolute(path, "l4/index.html"),
6135
user, pass, false)
6136
end
6137
})
6138
6139
table.insert(fingerprints, {
6140
name = "Sony Network Camera (Boa 2)",
6141
cpe = "cpe:/h:sony:snc_*",
6142
category = "security",
6143
paths = {
6144
{path = "/en/index.html"}
6145
},
6146
target_check = function (host, port, path, response)
6147
return response.status == 200
6148
and (response.header["server"] or ""):find("^Boa/%d+%.")
6149
and response.body
6150
and response.body:lower():find("<title>sony network camera snc-", 1, true)
6151
end,
6152
login_combos = {
6153
{username = "admin", password = "admin"}
6154
},
6155
login_check = function (host, port, path, user, pass)
6156
local resp1 = http_get_simple(host, port, path)
6157
if not (resp1.status == 200 and resp1.body) then return false end
6158
local _, lurl = resp1.body:match("=%s*window%.open%(%s*(['\"])(.-)%1")
6159
if not lurl then return false end
6160
lurl = url.absolute(path, lurl)
6161
return try_http_auth(host, port, lurl, user, pass, false)
6162
end
6163
})
6164
6165
table.insert(fingerprints, {
6166
name = "Sony Network Camera (NetEVI/Virgo)",
6167
cpe = "cpe:/h:sony:snc_*",
6168
category = "security",
6169
paths = {
6170
{path = "/index.html"}
6171
},
6172
target_check = function (host, port, path, response)
6173
local server = response.header["server"] or ""
6174
return response.status == 200
6175
and server:find("^NetEVI/%d+%.") or server:find("^Virgo/%d+%.")
6176
and response.body
6177
and response.body:lower():find("<title>sony network camera snc-", 1, true)
6178
end,
6179
login_combos = {
6180
{username = "admin", password = "admin"}
6181
},
6182
login_check = function (host, port, path, user, pass)
6183
return try_http_auth(host, port, url.absolute(path, "home/l4/admin.html"),
6184
user, pass, false)
6185
end
6186
})
6187
6188
table.insert(fingerprints, {
6189
name = "Sony Network Camera (thttpd)",
6190
cpe = "cpe:/h:sony:snc_*",
6191
category = "security",
6192
paths = {
6193
{path = "/"}
6194
},
6195
target_check = function (host, port, path, response)
6196
return response.status == 200
6197
and (response.header["server"] or ""):find("^thttpd/%d+%.")
6198
and response.body
6199
and response.body:find("adm/file.cgi?next_file=setting.htm", 1, true)
6200
and response.body:lower():find("<title>sony network camera snc-", 1, true)
6201
end,
6202
login_combos = {
6203
{username = "admin", password = "admin"}
6204
},
6205
login_check = function (host, port, path, user, pass)
6206
return try_http_auth(host, port,
6207
url.absolute(path, "adm/file.cgi?next_file=setting.htm"),
6208
user, pass, false)
6209
end
6210
})
6211
6212
table.insert(fingerprints, {
6213
name = "Basler Camera",
6214
category = "security",
6215
paths = {
6216
{path = "/"}
6217
},
6218
target_check = function (host, port, path, response)
6219
return response.status == 200
6220
and response.body
6221
and response.body:lower():find("<title>[^<]- web client [^<]- basler ag</title>")
6222
end,
6223
login_combos = {
6224
{username = "admin", password = "admin"}
6225
},
6226
login_check = function (host, port, path, user, pass)
6227
local resp = http_post_simple(host, port,
6228
url.absolute(path, "cgi-bin/auth_if.cgi?Login"),
6229
nil, {["Auth.Username"]=user, ["Auth.Password"]=pass})
6230
return resp.status == 200
6231
and (resp.body or ""):find("[{,]%s*success%s*:%s*true%s*[,}]")
6232
end
6233
})
6234
6235
table.insert(fingerprints, {
6236
name = "IQinVision Camera (var.1)",
6237
category = "security",
6238
paths = {
6239
{path = "/"}
6240
},
6241
target_check = function (host, port, path, response)
6242
local server = response.header["server"] or ""
6243
return response.status == 401
6244
and response.body
6245
and (server:find("^IQinVision Embedded ")
6246
and response.body:find("<xmp>%s*Please Authenticate%s*</xmp>")
6247
or server:find("^IQhttpD/%d+%.")
6248
and response.body:find("Authorization required for the URL", 1, true))
6249
end,
6250
login_combos = {
6251
{username = "login", password = "access"},
6252
{username = "root", password = "system"}
6253
},
6254
login_check = function (host, port, path, user, pass)
6255
return try_http_auth(host, port, path, user, pass, false)
6256
end
6257
})
6258
6259
table.insert(fingerprints, {
6260
name = "IQinVision Camera (var.2)",
6261
category = "security",
6262
paths = {
6263
{path = "/"}
6264
},
6265
target_check = function (host, port, path, response)
6266
return have_openssl
6267
and response.status == 403
6268
and (response.header["server"] or ""):find("^IQinVision Embedded ")
6269
and get_cookie(response, "SrvrNonce", "^%x+")
6270
end,
6271
login_combos = {
6272
{username = "login", password = "access"},
6273
{username = "root", password = "system"}
6274
},
6275
login_check = function (host, port, path, user, pass)
6276
local resp1 = http_get_simple(host, port, path)
6277
local nonce = get_cookie(resp1, "SrvrNonce")
6278
if not nonce then return false end
6279
local creds = stdnse.tohex(openssl.md5(table.concat({nonce, user,
6280
pass:upper()}, ":")))
6281
local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)
6282
local resp2 = http_get_simple(host, port, path, {cookies=cookies})
6283
return resp2.status == 200
6284
end
6285
})
6286
6287
table.insert(fingerprints, {
6288
name = "IQinVision Camera (var.3)",
6289
category = "security",
6290
paths = {
6291
{path = "/"}
6292
},
6293
target_check = function (host, port, path, response)
6294
local server = response.header["server"] or ""
6295
if not (response.status == 200
6296
and response.body
6297
and (server:find("^IQinVision Embedded ")
6298
and response.body:find(">IQ", 1, true)
6299
and response.body:lower():find("<title>iq", 1, true)
6300
or server:find("^IQhttpD/%d+%.")
6301
and response.body:find("%Wself%.location%s*=%s*(['\"])dptzvid%.html%1"))) then
6302
return false
6303
end
6304
local resp = http_get_simple(host, port, url.absolute(path, "accessset.html"))
6305
return resp.status == 401
6306
end,
6307
login_combos = {
6308
{username = "root", password = "system"}
6309
},
6310
login_check = function (host, port, path, user, pass)
6311
return try_http_auth(host, port, url.absolute(path, "accessset.html"),
6312
user, pass, false)
6313
end
6314
})
6315
6316
table.insert(fingerprints, {
6317
name = "IQinVision Camera (var.4)",
6318
category = "security",
6319
paths = {
6320
{path = "/"}
6321
},
6322
target_check = function (host, port, path, response)
6323
if not (have_openssl
6324
and response.status == 200
6325
and (response.header["server"] or ""):find("^IQinVision Embedded ")
6326
and response.body
6327
and response.body:find(">IQ", 1, true)
6328
and response.body:lower():find("<title>iq", 1, true)) then
6329
return false
6330
end
6331
local resp = http_get_simple(host, port, url.absolute(path, "accessset.html"))
6332
return resp.status == 403
6333
and get_cookie(resp, "SrvrNonce", "^%x+")
6334
end,
6335
login_combos = {
6336
{username = "root", password = "system"}
6337
},
6338
login_check = function (host, port, path, user, pass)
6339
local lurl = url.absolute(path, "accessset.html")
6340
local resp1 = http_get_simple(host, port, lurl)
6341
local nonce = get_cookie(resp1, "SrvrNonce")
6342
if not nonce then return false end
6343
local creds = stdnse.tohex(openssl.md5(table.concat({nonce, user,
6344
pass:upper()}, ":")))
6345
local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)
6346
local resp2 = http_get_simple(host, port, lurl, {cookies=cookies})
6347
return resp2.status == 200
6348
end
6349
})
6350
6351
table.insert(fingerprints, {
6352
name = "Sentry360 FS-IP5000 Camera",
6353
category = "security",
6354
paths = {
6355
{path = "/"}
6356
},
6357
target_check = function (host, port, path, response)
6358
return response.status == 200
6359
and response.header["server"] == "Sentry360"
6360
and response.body
6361
and get_tag(response.body, "img", {src="^logo_cam_page%.png$"})
6362
end,
6363
login_combos = {
6364
{username = "Admin", password = "1234"}
6365
},
6366
login_check = function (host, port, path, user, pass)
6367
local rnd1 = math.random(10000000, 99999999)
6368
local rnd2 = math.random(10000000, 99999999)
6369
local lurl = url.absolute(path, ("load.set?rnd=%d&rnd=%d"):format(rnd1, rnd2))
6370
return try_http_auth(host, port, lurl, user, pass, false)
6371
end
6372
})
6373
6374
table.insert(fingerprints, {
6375
name = "SerVision TVG",
6376
cpe = "cpe:/o:servision:hvg_video_gateway_firmware",
6377
category = "security",
6378
paths = {
6379
{path = "/"}
6380
},
6381
target_check = function (host, port, path, response)
6382
return response.status == 200
6383
and (response.header["server"] or ""):find("^2%.2%.")
6384
and response.body
6385
and response.body:find("TO_LOAD", 1, true)
6386
and get_tag(response.body, "input", {name="^user_username$"})
6387
end,
6388
login_combos = {
6389
{username = "svuser", password = "servconf"},
6390
{username = "anybody", password = "Bantham"}
6391
},
6392
login_check = function (host, port, path, user, pass)
6393
local form = {user_username=user,
6394
user_password=pass,
6395
LOADED=1,
6396
TO_LOAD="index.htm"}
6397
local resp = http_post_simple(host, port, url.absolute(path, "index.htm"),
6398
nil, form)
6399
return resp.status == 201
6400
and (resp.body or ""):find("%WloadMain%((['\"])main%.htm%1%)")
6401
end
6402
})
6403
6404
table.insert(fingerprints, {
6405
name = "Speco IP Camera",
6406
category = "security",
6407
paths = {
6408
{path = "/"}
6409
},
6410
target_check = function (host, port, path, response)
6411
return response.status == 200
6412
and response.body
6413
and response.body:find('src="newlogin.html"', 1, true)
6414
and response.body:lower():find("<title>speco ip camera</title>", 1, true)
6415
end,
6416
login_combos = {
6417
{username = "admin", password = "1234"}
6418
},
6419
login_check = function (host, port, path, user, pass)
6420
local resp = http_get_simple(host, port,
6421
url.absolute(path, "httpapi?GetUserLevel&ipAddress="),
6422
{auth={username=user, password=pass}})
6423
return resp.status == 200
6424
and (resp.body or ""):lower():find("userlevel:", 1, true)
6425
end
6426
})
6427
6428
table.insert(fingerprints, {
6429
name = "Brickcom Camera",
6430
cpe = "cpe:/o:brickom:*",
6431
category = "security",
6432
paths = {
6433
{path = "/"}
6434
},
6435
target_check = function (host, port, path, response)
6436
return (http_auth_realm(response) or ""):find("^Brickcom%s")
6437
end,
6438
login_combos = {
6439
{username = "admin", password = "admin"}
6440
},
6441
login_check = function (host, port, path, user, pass)
6442
return try_http_auth(host, port, path, user, pass, false)
6443
end
6444
})
6445
6446
table.insert(fingerprints, {
6447
name = "ACTi Camera",
6448
category = "security",
6449
paths = {
6450
{path = "/"}
6451
},
6452
target_check = function (host, port, path, response)
6453
return response.status == 200
6454
and response.body
6455
and response.body:find('gPwd="123456"', 1, true)
6456
and response.body:lower():find("<title>web configurator</title>", 1, true)
6457
end,
6458
login_combos = {
6459
{username = "admin", password = "123456"}
6460
},
6461
login_check = function (host, port, path, user, pass)
6462
local lurl = ("cgi-bin/system?USER=%s&PWD=%s&LOGIN&SYSTEM_INFO"):format(
6463
url.escape(user), url.escape(pass))
6464
local resp = http_get_simple(host, port, url.absolute(path, lurl))
6465
return resp.status == 200
6466
and (resp.body or ""):find("LOGIN='1'", 1, true)
6467
end
6468
})
6469
6470
table.insert(fingerprints, {
6471
name = "Ovislink AirLive BU",
6472
cpe = "cpe:/h:ovislink:airlive_bu-*",
6473
category = "security",
6474
paths = {
6475
{path = "/"}
6476
},
6477
target_check = function (host, port, path, response)
6478
return response.status == 200
6479
and (response.header["server"] or ""):find("^Boa/%d+%.")
6480
and response.body
6481
and response.body:find("controlmenu.htm", 1, true)
6482
and get_tag(response.body, "frame", {src="^controlmenu%.htm$"})
6483
and response.body:lower():find("<title>airlive</title>", 1, true)
6484
end,
6485
login_combos = {
6486
{username = "admin", password = "airlive"}
6487
},
6488
login_check = function (host, port, path, user, pass)
6489
return try_http_auth(host, port, url.absolute(path, "setting.htm"),
6490
user, pass, false)
6491
end
6492
})
6493
6494
table.insert(fingerprints, {
6495
name = "American Dynamics IP Dome",
6496
category = "security",
6497
paths = {
6498
{path = "/"}
6499
},
6500
target_check = function (host, port, path, response)
6501
return response.status == 200
6502
and response.body
6503
and response.body:find("gbl_locale", 1, true)
6504
and response.body:lower():find("<title>american dynamics", 1, true)
6505
end,
6506
login_combos = {
6507
{username = "admin", password = "admin"}
6508
},
6509
login_check = function (host, port, path, user, pass)
6510
local form = {gbl_locale=1,
6511
accessRoute="",
6512
username=user,
6513
password=pass}
6514
local resp = http_post_simple(host, port, url.absolute(path, "index.php"),
6515
nil, form)
6516
return resp.status == 200
6517
and (resp.body or ""):find("gbl_username%s*=")
6518
end
6519
})
6520
6521
table.insert(fingerprints, {
6522
name = "exacqVision",
6523
category = "security",
6524
paths = {
6525
{path = "/"}
6526
},
6527
target_check = function (host, port, path, response)
6528
if not (response.status == 200
6529
and response.body
6530
and response.body:find("%Wlocation%.replace%(%s*(['\"])login%.web%1%s*%)%s*;")) then
6531
return false
6532
end
6533
local resp = http_get_simple(host, port, url.absolute(path, "login.web"))
6534
return resp.status == 200
6535
and resp.body
6536
and resp.body:find("exacqVision", 1, true)
6537
and resp.body:lower():find("<title>login</title>", 1, true)
6538
end,
6539
login_combos = {
6540
{username = "admin", password = "admin256"}
6541
},
6542
login_check = function (host, port, path, user, pass)
6543
local form = {u=user,
6544
p=pass,
6545
l=1,
6546
s=0,
6547
output="json",
6548
responseVersion=2,
6549
save=1}
6550
local resp = http_post_simple(host, port, url.absolute(path, "login.web"),
6551
nil, form)
6552
if not (resp.status == 200 and resp.body) then return false end
6553
local jstatus, jout = json.parse(resp.body)
6554
return jstatus and jout.login and jout.success
6555
end
6556
})
6557
6558
table.insert(fingerprints, {
6559
name = "GeoVision Camera",
6560
category = "security",
6561
paths = {
6562
{path = "/"}
6563
},
6564
target_check = function (host, port, path, response)
6565
return response.status == 200
6566
and response.header["server"] == "GeoHttpServer"
6567
and response.body
6568
and (response.body:find('action="webcam_login"', 1, true)
6569
or response.body:find('action="phoneinfo"', 1, true))
6570
end,
6571
login_combos = {
6572
{username = "admin", password = "admin"}
6573
},
6574
login_check = function (host, port, path, user, pass)
6575
local form = {id=user,
6576
pwd=pass,
6577
ViewType=2,
6578
Login="Login"}
6579
local resp = http_post_simple(host, port,
6580
url.absolute(path, "webcam_login"),
6581
nil, form)
6582
return resp.status == 200
6583
and resp.body
6584
and (resp.body:find('%sname%s*=%s*"IDKey"%f[%s][^>]-%svalue%s*=%s*"[%x-]+"')
6585
or resp.body:find('%?IDKey=[%x-]+'))
6586
end
6587
})
6588
6589
table.insert(fingerprints, {
6590
name = "GeoVision Web-Manager",
6591
category = "security",
6592
paths = {
6593
{path = "/"}
6594
},
6595
target_check = function (host, port, path, response)
6596
return have_openssl
6597
and response.status == 200
6598
and response.body
6599
and response.body:find("GeoVision", 1, true)
6600
and response.body:find("%Wlocation%.href%s*=%s*(['\"])ssi%.cgi/Login%.htm%1")
6601
and response.body:lower():find("<title>geovision ", 1, true)
6602
end,
6603
login_combos = {
6604
{username = "guest", password = "guest"},
6605
{username = "admin", password = "admin"}
6606
},
6607
login_check = function (host, port, path, user, pass)
6608
local resp1 = http_get_simple(host, port,
6609
url.absolute(path, "ssi.cgi/Login.htm"))
6610
if not (resp1.status == 200 and resp1.body) then return false end
6611
local nonce1, nonce2 = resp1.body:match("%Wvar%s+cc1%s*=%s*['\"](%x+)['\"]%s*;%s*var%s+cc2%s*=%s*['\"](%x+)['\"]")
6612
if not nonce1 then return false end
6613
local hashfnc = function (p, a, b) return stdnse.tohex(openssl.md5(table.concat({a,p:lower(),b}))):upper() end
6614
local form = {username="",
6615
password="",
6616
Apply="Apply",
6617
umd5=hashfnc(user, nonce1, nonce2),
6618
pmd5=hashfnc(pass, nonce2, nonce1),
6619
browser=1}
6620
local resp2 = http_post_simple(host, port,
6621
url.absolute(path, "LoginPC.cgi"),
6622
nil, form)
6623
return resp2.status == 200
6624
and get_cookie(resp2, "CLIENT_ID", "^%d+$")
6625
end
6626
})
6627
6628
table.insert(fingerprints, {
6629
name = "GeoVision WebControl",
6630
category = "security",
6631
paths = {
6632
{path = "/"}
6633
},
6634
target_check = function (host, port, path, response)
6635
return (http_auth_realm(response) or ""):find("^Welcome to GV%-%w+ WebControl$")
6636
end,
6637
login_combos = {
6638
{username = "admin", password = "admin"}
6639
},
6640
login_check = function (host, port, path, user, pass)
6641
return try_http_auth(host, port, path, user, pass, false)
6642
end
6643
})
6644
6645
table.insert(fingerprints, {
6646
name = "Arecont Vision (no auth)",
6647
category = "security",
6648
paths = {
6649
{path = "/"}
6650
},
6651
target_check = function (host, port, path, response)
6652
return response.status == 200
6653
and response.body
6654
and response.body:find(">Arecont Vision", 1, true)
6655
and response.body:lower():find("<title>arecont vision camera</title>", 1, true)
6656
and get_tag(response.body, "div", {class="^avmenu$"})
6657
end,
6658
login_combos = {
6659
{username = "", password = ""}
6660
},
6661
login_check = function (host, port, path, user, pass)
6662
return true
6663
end
6664
})
6665
6666
table.insert(fingerprints, {
6667
name = "Arecont Vision (basic auth)",
6668
category = "security",
6669
paths = {
6670
{path = "/"}
6671
},
6672
target_check = function (host, port, path, response)
6673
return http_auth_realm(response) == "Arecont Vision"
6674
end,
6675
login_combos = {
6676
{username = "admin", password = ""},
6677
{username = "viewer", password = ""}
6678
},
6679
login_check = function (host, port, path, user, pass)
6680
return try_http_auth(host, port, path, user, pass, false)
6681
end
6682
})
6683
6684
table.insert(fingerprints, {
6685
name = "Avigilon Camera",
6686
category = "security",
6687
paths = {
6688
{path = "/"}
6689
},
6690
target_check = function (host, port, path, response)
6691
return (http_auth_realm(response) or ""):find("^Avigilon%-%d+$")
6692
end,
6693
login_combos = {
6694
{username = "admin", password = "admin"}
6695
},
6696
login_check = function (host, port, path, user, pass)
6697
return try_http_auth(host, port, path, user, pass, true)
6698
end
6699
})
6700
6701
table.insert(fingerprints, {
6702
name = "Canon Camera",
6703
cpe = "cpe:/h:canon:network_camera_server_vb*",
6704
category = "security",
6705
paths = {
6706
{path = "/"}
6707
},
6708
target_check = function (host, port, path, response)
6709
return response.status == 200
6710
and response.body
6711
and response.body:find("img/canon_logo.gif", 1, true)
6712
and get_tag(response.body, "img", {src="^img/canon_logo%.gif$"})
6713
and response.body:lower():find("<title>network camera</title>", 1, true)
6714
end,
6715
login_combos = {
6716
{username = "root", password = "camera"}
6717
},
6718
login_check = function (host, port, path, user, pass)
6719
return try_http_auth(host, port,
6720
url.absolute(path, "admin/index.html?lang=en"),
6721
user, pass, "any")
6722
end
6723
})
6724
6725
table.insert(fingerprints, {
6726
name = "Brovotech IPCAM",
6727
category = "security",
6728
paths = {
6729
{path = "/"}
6730
},
6731
target_check = function (host, port, path, response)
6732
return response.status == 302
6733
and (response.header["location"] or ""):find("/cn/viewer_index%.asp$")
6734
end,
6735
login_combos = {
6736
{username = "admin", password = "admin"}
6737
},
6738
login_check = function (host, port, path, user, pass)
6739
return try_http_auth(host, port, url.absolute(path, "cn/viewer_index.asp"),
6740
user, pass, true)
6741
end
6742
})
6743
6744
table.insert(fingerprints, {
6745
name = "Grandstream Camera",
6746
cpe = "cpe:/o:grandstream:gxv_device_firmware",
6747
category = "security",
6748
paths = {
6749
{path = "/index.html"}
6750
},
6751
target_check = function (host, port, path, response)
6752
return response.status == 200
6753
and response.header["server"] == "GS-Webs"
6754
and response.body
6755
and response.body:lower():find("%stype%s*=%s*['\"]application/x%-vnd%-npgs_")
6756
end,
6757
login_combos = {
6758
{username = "admin", password = "admin"}
6759
},
6760
login_check = function (host, port, path, user, pass)
6761
return try_http_auth(host, port, url.absolute(path, "Pages/system.html"),
6762
user, pass, false)
6763
end
6764
})
6765
6766
table.insert(fingerprints, {
6767
name = "Hikvision (var.1)",
6768
category = "security",
6769
paths = {
6770
{path = "/index.asp"}
6771
},
6772
target_check = function (host, port, path, response)
6773
return response.status == 200
6774
and response.body
6775
and response.body:find("%Wwindow%.location%.href%s*=%s*['\"]doc/page/login%.asp['\"?]")
6776
and response.body:lower():find("<title>index</title>", 1, true)
6777
end,
6778
login_combos = {
6779
{username = "admin", password = "12345"}
6780
},
6781
login_check = function (host, port, path, user, pass)
6782
local resp = http_get_simple(host, port,
6783
url.absolute(path, "PSIA/Custom/SelfExt/userCheck"),
6784
{auth={username=user, password=pass}})
6785
return resp.status == 200
6786
and (resp.body or ""):lower():find("<statusvalue>200</statusvalue>", 1, true)
6787
end
6788
})
6789
6790
table.insert(fingerprints, {
6791
name = "Hikvision (var.2)",
6792
category = "security",
6793
paths = {
6794
{path = "/"}
6795
},
6796
target_check = function (host, port, path, response)
6797
return response.status == 200
6798
and response.body
6799
and response.body:find("%Wwindow%.location%.href%s*=%s*['\"]doc/page/login%.asp['\"?]")
6800
and response.body:lower():find("<title>index</title>", 1, true)
6801
end,
6802
login_combos = {
6803
{username = "admin", password = "12345"}
6804
},
6805
login_check = function (host, port, path, user, pass)
6806
local resp = http_get_simple(host, port,
6807
url.absolute(path, "ISAPI/Security/userCheck"),
6808
{auth={username=user, password=pass}})
6809
return resp.status == 200
6810
and (resp.body or ""):lower():find("<statusvalue>200</statusvalue>", 1, true)
6811
end
6812
})
6813
6814
table.insert(fingerprints, {
6815
name = "TI Megapixel IP Camera",
6816
category = "security",
6817
paths = {
6818
{path = "/"}
6819
},
6820
target_check = function (host, port, path, response)
6821
return http_auth_realm(response) == "Megapixel IP Camera"
6822
and response.header["server"] == "HKVision-Webs"
6823
end,
6824
login_combos = {
6825
{username = "admin", password = "admin"}
6826
},
6827
login_check = function (host, port, path, user, pass)
6828
return try_http_auth(host, port, path, user, pass, false)
6829
end
6830
})
6831
6832
table.insert(fingerprints, {
6833
name = "MayGion Camera (no auth)",
6834
category = "security",
6835
paths = {
6836
{path = "/"}
6837
},
6838
target_check = function (host, port, path, response)
6839
return response.status == 200
6840
and response.header["server"] == "WebServer(IPCamera_Logo)"
6841
and response.body
6842
and get_tag(response.body, "iframe", {src="^video%.htm$"})
6843
end,
6844
login_combos = {
6845
{username = "", password = ""}
6846
},
6847
login_check = function (host, port, path, user, pass)
6848
return true
6849
end
6850
})
6851
6852
table.insert(fingerprints, {
6853
name = "MayGion Camera",
6854
category = "security",
6855
paths = {
6856
{path = "/"}
6857
},
6858
target_check = function (host, port, path, response)
6859
return response.status == 200
6860
and response.header["server"] == "WebServer(IPCamera_Logo)"
6861
and response.body
6862
and response.body:find("login.xml", 1, true)
6863
end,
6864
login_combos = {
6865
{username = "admin", password = "admin"}
6866
},
6867
login_check = function (host, port, path, user, pass)
6868
local form = {user=user,
6869
usr=user,
6870
password=pass,
6871
pwd=pass}
6872
local lurl = "login.xml?" .. url.build_query(form)
6873
local resp = http_get_simple(host, port, url.absolute(path, lurl))
6874
return resp.status == 200
6875
and get_cookie(resp, "user") == user
6876
and get_cookie(resp, "password") == pass
6877
and get_cookie(resp, "usrLevel") == "0"
6878
end
6879
})
6880
6881
table.insert(fingerprints, {
6882
name = "OEM Boa IP Camera (var.1)",
6883
category = "security",
6884
paths = {
6885
{path = "/"}
6886
},
6887
target_check = function (host, port, path, response)
6888
return response.status == 401
6889
and (http_auth_realm(response) or ""):find(" IP Camera$")
6890
and (response.header["server"] or ""):find("^Boa/%d+%.")
6891
end,
6892
login_combos = {
6893
{username = "admin", password = "admin"}
6894
},
6895
login_check = function (host, port, path, user, pass)
6896
return try_http_auth(host, port, path, user, pass, false)
6897
end
6898
})
6899
6900
table.insert(fingerprints, {
6901
name = "OEM Boa IP Camera (var.2)",
6902
category = "security",
6903
paths = {
6904
{path = "/"}
6905
},
6906
target_check = function (host, port, path, response)
6907
return response.status == 200
6908
and (response.header["server"] or ""):find("^Boa/%d+%.")
6909
and get_tag(response.body, "script", {src="^profile$"})
6910
and get_tag(response.body, "img", {id="^setting$",onclick="%f[%w]window%.location=(['\"])setting%.htm%1$"})
6911
end,
6912
login_combos = {
6913
{username = "admin", password = "admin"}
6914
},
6915
login_check = function (host, port, path, user, pass)
6916
return try_http_auth(host, port, url.absolute(path, "setting.htm"),
6917
user, pass, false)
6918
end
6919
})
6920
6921
table.insert(fingerprints, {
6922
name = "OEM Boa IP Camera (var.3)",
6923
category = "security",
6924
paths = {
6925
{path = "/"}
6926
},
6927
target_check = function (host, port, path, response)
6928
return response.status == 200
6929
and (response.header["server"] or ""):find("^Boa/%d+%.")
6930
and get_tag(response.body, "script", {src="^profile$"})
6931
and response.body:lower():find("<title>ip camera viewer</title>", 1, true)
6932
end,
6933
login_combos = {
6934
{username = "admin", password = "12345"}
6935
},
6936
login_check = function (host, port, path, user, pass)
6937
return try_http_auth(host, port, url.absolute(path, "setting.htm"),
6938
user, pass, false)
6939
end
6940
})
6941
6942
table.insert(fingerprints, {
6943
name = "OEM Netcam",
6944
category = "security",
6945
paths = {
6946
{path = "/"},
6947
},
6948
target_check = function (host, port, path, response)
6949
return (http_auth_realm(response) or ""):find("^[Nn]etcam$")
6950
end,
6951
login_combos = {
6952
{username = "admin", password = "admin"}
6953
},
6954
login_check = function (host, port, path, user, pass)
6955
return try_http_auth(host, port, path, user, pass, false)
6956
end
6957
})
6958
6959
table.insert(fingerprints, {
6960
name = "Planet IP Cam",
6961
category = "security",
6962
paths = {
6963
{path = "/"},
6964
},
6965
target_check = function (host, port, path, response)
6966
return http_auth_realm(response) == "PLANET IP CAM"
6967
end,
6968
login_combos = {
6969
{username = "admin", password = "admin"}
6970
},
6971
login_check = function (host, port, path, user, pass)
6972
return try_http_auth(host, port, path, user, pass, false)
6973
end
6974
})
6975
6976
table.insert(fingerprints, {
6977
name = "Planet IP Surveillance",
6978
category = "security",
6979
paths = {
6980
{path = "/"},
6981
},
6982
target_check = function (host, port, path, response)
6983
return response.status == 200
6984
and response.body
6985
and response.body:find("ipcam_language", 1, true)
6986
and get_tag(response.body, "frame", {src="^asp/view%.asp$"})
6987
and response.body:lower():find("<title>planet ip surveillance web management</title>", 1, true)
6988
end,
6989
login_combos = {
6990
{username = "admin", password = ""},
6991
{username = "admin", password = "admin"}
6992
},
6993
login_check = function (host, port, path, user, pass)
6994
return try_http_auth(host, port, url.absolute(path, "asp/set.asp"),
6995
user, pass, true)
6996
end
6997
})
6998
6999
table.insert(fingerprints, {
7000
name = "TP-Link IPC",
7001
category = "security",
7002
paths = {
7003
{path = "/"}
7004
},
7005
target_check = function (host, port, path, response)
7006
return response.status == 200
7007
and response.body
7008
and response.body:find("/web-static/dynaform/class.js", 1, true)
7009
and response.body:lower():find("<title>ipc</title>", 1, true)
7010
end,
7011
login_combos = {
7012
{username = "admin", password = ""}
7013
},
7014
login_check = function (host, port, path, user, pass)
7015
local a = "RDpbLfCPsJZ7fiv"
7016
local b = pass
7017
local pwdlen = math.max(#a, #b)
7018
a = table.pack(string.byte(a .. ("\187"):rep(pwdlen - #a), 1, -1))
7019
b = table.pack(string.byte(b .. ("\187"):rep(pwdlen - #b), 1, -1))
7020
local pad = "yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW"
7021
local pwd = {}
7022
for i = 1, pwdlen do
7023
table.insert(pwd, pad:byte(1 + (a[i] ~ b[i]) % #pad))
7024
end
7025
local header = {["Accept"]="application/json, text/plain, */*",
7026
["Content-Type"]="application/json;charset=utf-8"}
7027
local jin = {method="do",
7028
login={username=user,
7029
password=string.char(table.unpack(pwd))}}
7030
json.make_object(jin)
7031
local resp = http_post_simple(host, port, path, {header=header},
7032
json.generate(jin))
7033
if not (resp.status == 200 and resp.body) then return false end
7034
local jstatus, jout = json.parse(resp.body)
7035
return jstatus and jout.stok and jout.error_code == 0
7036
end
7037
})
7038
7039
table.insert(fingerprints, {
7040
name = "Allnet Camera",
7041
category = "security",
7042
paths = {
7043
{path = "/"}
7044
},
7045
target_check = function (host, port, path, response)
7046
return http_auth_realm(response) == "NetworkPTZ"
7047
end,
7048
login_combos = {
7049
{username = "admin", password = "admin"}
7050
},
7051
login_check = function (host, port, path, user, pass)
7052
return try_http_auth(host, port, path, user, pass, false)
7053
end
7054
})
7055
7056
table.insert(fingerprints, {
7057
name = "D-Link Camera",
7058
cpe = "cpe:/h:d-link:dcs-*",
7059
category = "security",
7060
paths = {
7061
{path = "/"}
7062
},
7063
target_check = function (host, port, path, response)
7064
return (http_auth_realm(response) or ""):find("^DCS%-%d+%u?%f[_\0]")
7065
end,
7066
login_combos = {
7067
{username = "admin", password = "admin"},
7068
{username = "admin", password = ""}
7069
},
7070
login_check = function (host, port, path, user, pass)
7071
return try_http_auth(host, port, path, user, pass, false)
7072
end
7073
})
7074
7075
table.insert(fingerprints, {
7076
name = "Microseven IP camera",
7077
category = "security",
7078
paths = {
7079
{path = "/"}
7080
},
7081
target_check = function (host, port, path, response)
7082
return response.status == 200
7083
and response.body
7084
and response.body:find("/hi3510/", 1, true)
7085
and get_tag(response.body, "script", {src="/cgi%-bin/hi3510/param%.cgi%?cmd=getuserinfo$"})
7086
end,
7087
login_combos = {
7088
{username = "admin", password = "password"},
7089
{username = "guest", password = "guest"}
7090
},
7091
login_check = function (host, port, path, user, pass)
7092
return try_http_auth(host, port,
7093
url.absolute(path, "cgi-bin/hi3510/param.cgi?cmd=getuserinfo"),
7094
user, pass, false)
7095
end
7096
})
7097
7098
table.insert(fingerprints, {
7099
name = "Milesight Camera (var.1)",
7100
category = "security",
7101
paths = {
7102
{path = "/"}
7103
},
7104
target_check = function (host, port, path, response)
7105
return response.status == 200
7106
and response.body
7107
and (response.body:find(">Milesight Network Camera", 1, true)
7108
or response.body:find(">IPCAM Network Camera", 1, true))
7109
and get_tag(response.body, "input", {id="^secret$"})
7110
and not get_tag(response.body, "script", {src="/javascript/md5%.js%?"})
7111
end,
7112
login_combos = {
7113
{username = "admin", password = "ms1234"},
7114
{username = "operator", password = "ms1234"},
7115
{username = "viewer", password = "ms1234"}
7116
},
7117
login_check = function (host, port, path, user, pass)
7118
local userno = {admin=0, operator=1, viewer=2}
7119
local creds = {tostring(userno[user]),
7120
url.escape(user),
7121
url.escape(pass)}
7122
local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")
7123
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7124
return resp.status == 200
7125
and resp.body:find("OK checkpassword", 1, true)
7126
end
7127
})
7128
7129
table.insert(fingerprints, {
7130
name = "Milesight Camera (var.2)",
7131
category = "security",
7132
paths = {
7133
{path = "/"}
7134
},
7135
target_check = function (host, port, path, response)
7136
return have_openssl
7137
and response.status == 200
7138
and response.body
7139
and (response.body:find(">Milesight Network Camera", 1, true)
7140
or response.body:find(">IPCAM Network Camera", 1, true))
7141
and get_tag(response.body, "input", {id="^secret$"})
7142
and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})
7143
end,
7144
login_combos = {
7145
{username = "admin", password = "ms1234"},
7146
{username = "operator", password = "ms1234"},
7147
{username = "viewer", password = "ms1234"}
7148
},
7149
login_check = function (host, port, path, user, pass)
7150
local userno = {admin=0, operator=1, viewer=2}
7151
local creds = {tostring(userno[user]),
7152
url.escape(user),
7153
stdnse.tohex(openssl.md5(pass))}
7154
local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")
7155
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7156
return resp.status == 200
7157
and resp.body:find("OK checkpassword", 1, true)
7158
end
7159
})
7160
7161
table.insert(fingerprints, {
7162
name = "Milesight Camera (Alphafinity)",
7163
category = "security",
7164
paths = {
7165
{path = "/"}
7166
},
7167
target_check = function (host, port, path, response)
7168
return have_openssl
7169
and response.status == 200
7170
and response.body
7171
and response.body:find(">Alphafinity Network Camera", 1, true)
7172
and get_tag(response.body, "input", {id="^secret$"})
7173
and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})
7174
end,
7175
login_combos = {
7176
{username = "admin", password = "admin"}
7177
},
7178
login_check = function (host, port, path, user, pass)
7179
local userno = {admin=0, operator=1, viewer=2}
7180
local creds = {tostring(userno[user]),
7181
url.escape(user),
7182
stdnse.tohex(openssl.md5(pass))}
7183
local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")
7184
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7185
return resp.status == 200
7186
and resp.body:find("OK checkpassword", 1, true)
7187
end
7188
})
7189
7190
table.insert(fingerprints, {
7191
name = "Milesight Camera (Beward)",
7192
category = "security",
7193
paths = {
7194
{path = "/"}
7195
},
7196
target_check = function (host, port, path, response)
7197
return have_openssl
7198
and response.status == 200
7199
and response.body
7200
and (response.body:find(">BEWARD Network HD camera", 1, true)
7201
or response.body:find(">Beward Network Camera", 1, true))
7202
and get_tag(response.body, "input", {id="^secret$"})
7203
and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})
7204
end,
7205
login_combos = {
7206
{username = "admin", password = "admin"},
7207
{username = "testuser", password = "htyjdfwbz1"}
7208
},
7209
login_check = function (host, port, path, user, pass)
7210
local userno = {admin=0, testuser=1}
7211
local creds = {tostring(userno[user]),
7212
url.escape(user),
7213
stdnse.tohex(openssl.md5(pass))}
7214
local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")
7215
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7216
return resp.status == 200
7217
and resp.body:find("OK checkpassword", 1, true)
7218
end
7219
})
7220
7221
table.insert(fingerprints, {
7222
name = "Beward SIP Door Station",
7223
category = "security",
7224
paths = {
7225
{path = "/"}
7226
},
7227
target_check = function (host, port, path, response)
7228
return response.status == 401
7229
and (http_auth_realm(response) or ""):find(" SIP Door Station %- %x+$")
7230
end,
7231
login_combos = {
7232
{username = "admin", password = "admin"}
7233
},
7234
login_check = function (host, port, path, user, pass)
7235
return try_http_auth(host, port, path, user, pass, true)
7236
end
7237
})
7238
7239
table.insert(fingerprints, {
7240
name = "OEM MegapixelIPCamera",
7241
category = "security",
7242
paths = {
7243
{path = "/"}
7244
},
7245
target_check = function (host, port, path, response)
7246
local realm = http_auth_realm(response)
7247
return response.status == 401
7248
and (response.header["server"] or ""):find("^Mbedthis%-Appweb/%d+%.")
7249
and (realm == "MegapixelIPCamera" or realm == "QuasarHDIPCamera")
7250
end,
7251
login_combos = {
7252
{username = "Admin", password = "1234"},
7253
{username = "admin", password = "admin"}
7254
},
7255
login_check = function (host, port, path, user, pass)
7256
return try_http_auth(host, port, path, user, pass, false)
7257
end
7258
})
7259
7260
table.insert(fingerprints, {
7261
name = "Philips InSight",
7262
cpe = "cpe:/h:philips:in.sight*",
7263
category = "security",
7264
paths = {
7265
{path = "/"}
7266
},
7267
target_check = function (host, port, path, response)
7268
return response.status == 200
7269
and (response.header["server"] or ""):find("^lighttpd/%d+%.")
7270
and response.body
7271
and response.body:find(">Philips ", 1, true)
7272
and response.body:lower():find("%salt%s*=%s*(['\"])philips insight wireless home monitor%1")
7273
end,
7274
login_combos = {
7275
{username = "admin", password = "M100-4674448"},
7276
{username = "user", password = "M100-4674448"}
7277
},
7278
login_check = function (host, port, path, user, pass)
7279
return try_http_auth(host, port, url.absolute(path, "cgi-bin/v1/camera"),
7280
user, pass, true)
7281
end
7282
})
7283
7284
table.insert(fingerprints, {
7285
name = "Planex CS",
7286
cpe = "cpe:/o:planex:cs-*",
7287
category = "security",
7288
paths = {
7289
{path = "/"}
7290
},
7291
target_check = function (host, port, path, response)
7292
return (http_auth_realm(response) or ""):find("^CS%-%u+%d+[%u%d]*$")
7293
end,
7294
login_combos = {
7295
{username = "admin", password = "password"},
7296
{username = "supervisor", password = "dangerous"}
7297
},
7298
login_check = function (host, port, path, user, pass)
7299
return try_http_auth(host, port, path, user, pass, false)
7300
end
7301
})
7302
7303
table.insert(fingerprints, {
7304
name = "Santec IPCamera",
7305
category = "security",
7306
paths = {
7307
{path = "/"}
7308
},
7309
target_check = function (host, port, path, response)
7310
return http_auth_realm(response) == "Santec-IPCamera"
7311
end,
7312
login_combos = {
7313
{username = "admin", password = "9999"}
7314
},
7315
login_check = function (host, port, path, user, pass)
7316
return try_http_auth(host, port, path, user, pass, false)
7317
end
7318
})
7319
7320
table.insert(fingerprints, {
7321
name = "HD IPC IP camera",
7322
category = "security",
7323
paths = {
7324
{path = "/"}
7325
},
7326
target_check = function (host, port, path, response)
7327
if not (response.status == 200
7328
and (response.header["server"] or ""):find("^thttpd/%d+%.")
7329
and response.body
7330
and get_refresh_url(response.body, "/web/index%.html$")) then
7331
return false
7332
end
7333
local resp = http_get_simple(host, port,
7334
url.absolute(path, "web/index.html"))
7335
return resp.status == 200
7336
and resp.body
7337
and resp.body:find("LonginPassword", 1, true)
7338
and get_tag(resp.body, "input", {id="^longinpassword$"})
7339
end,
7340
login_combos = {
7341
{username = "admin", password = "admin"},
7342
{username = "guest", password = "guest"}
7343
},
7344
login_check = function (host, port, path, user, pass)
7345
local form = {["-name"]=user,
7346
["-passwd"]=pass,
7347
["-time"]=math.floor(stdnse.clock_ms())}
7348
local lurl = url.absolute(path, "cgi-bin/hi3510/checkuser.cgi?" .. url.build_query(form))
7349
local resp = http_get_simple(host, port, lurl)
7350
return resp.status == 200
7351
and resp.body
7352
and resp.body:find("%f[%w]var%s+check%s*=%s*(['\"]?)1%1%s*;")
7353
and resp.body:find("%f[%w]var%s+authLevel%s*=%s*['\"]?[1-9]")
7354
end
7355
})
7356
7357
table.insert(fingerprints, {
7358
name = "3S Vision",
7359
category = "security",
7360
paths = {
7361
{path = "/"}
7362
},
7363
target_check = function (host, port, path, response)
7364
if response.header["server"] ~= "httpd" then return false end
7365
local realm = http_auth_realm(response) or ""
7366
return realm == "IP Video Server"
7367
or realm == "IP SPEED DOME"
7368
or realm:find("^[%w ]- IP Camera$")
7369
end,
7370
login_combos = {
7371
{username = "3sadmin", password = "27988303"},
7372
{username = "root", password = "root"}
7373
},
7374
login_check = function (host, port, path, user, pass)
7375
return try_http_auth(host, port, path, user, pass, false)
7376
end
7377
})
7378
7379
table.insert(fingerprints, {
7380
name = "Network Video Server (var.1)",
7381
category = "security",
7382
paths = {
7383
{path = "/login.asp"}
7384
},
7385
target_check = function (host, port, path, response)
7386
return response.status == 200
7387
and response.body
7388
and response.body:find("onLoginNVS", 1, true)
7389
and response.body:lower():find("<title>web service</title>", 1, true)
7390
and get_tag(response.body, "script", {["for"]="^WebCMS$", event="^CBK_LoginResult%("})
7391
end,
7392
login_combos = {
7393
{username = "admin", password = "admin"}
7394
},
7395
login_check = function (host, port, path, user, pass)
7396
local form = {username=user,
7397
password=pass,
7398
UserID=math.random(10000000, 99999999)}
7399
local lurl = url.absolute(path, "webs/loginCMS") .. "?"
7400
.. url.build_query(form)
7401
local resp = http_get_simple(host, port, lurl)
7402
return resp.status == 200
7403
and (resp.body or ""):find("<level>%d</level>")
7404
end
7405
})
7406
7407
table.insert(fingerprints, {
7408
name = "Network Video Server (var.2)",
7409
category = "security",
7410
paths = {
7411
{path = "/login.asp"}
7412
},
7413
target_check = function (host, port, path, response)
7414
return response.status == 200
7415
and response.body
7416
and response.body:find("onLoginNVS", 1, true)
7417
and response.body:lower():find("<title>web service</title>", 1, true)
7418
and get_tag(response.body, "script", {["for"]="^NetVideoX$", event="^CBK_LoginResult%("})
7419
end,
7420
login_combos = {
7421
{username = "admin", password = "admin"}
7422
},
7423
login_check = function (host, port, path, user, pass)
7424
local form = {username=user,
7425
password=pass,
7426
UserID=math.random(10000000, 99999999)}
7427
local lurl = url.absolute(path, "webs/httplogin") .. "?"
7428
.. url.build_query(form)
7429
local resp = http_get_simple(host, port, lurl)
7430
return resp.status == 200
7431
and (resp.body or ""):find("<level>%d</level>")
7432
end
7433
})
7434
7435
table.insert(fingerprints, {
7436
name = "Network Video Server (var.3)",
7437
category = "security",
7438
paths = {
7439
{path = "/login.asp"}
7440
},
7441
target_check = function (host, port, path, response)
7442
return response.status == 200
7443
and response.body
7444
and response.body:find("onLoginNVS", 1, true)
7445
and get_tag(response.body, "script", {event="^CallBackLoginState%("})
7446
and get_tag(response.body, "script", {src="^script/base64%.js$"})
7447
end,
7448
login_combos = {
7449
{username = "admin", password = "admin"}
7450
},
7451
login_check = function (host, port, path, user, pass)
7452
local form = {action="list",
7453
group="LOGIN",
7454
UserID=math.random(10000000, 99999999)}
7455
local lurl = url.absolute(path, "cgi-bin/login.cgi") .. "?"
7456
.. url.build_query(form)
7457
local resp = http_get_simple(host, port, lurl,
7458
{auth={username=user, password=pass}})
7459
return resp.status == 200
7460
and (resp.body or ""):find("%f[%w]root.ERR.no=0%f[^%w]")
7461
end
7462
})
7463
7464
table.insert(fingerprints, {
7465
name = "Pravis Systems DVR",
7466
category = "security",
7467
paths = {
7468
{path = "/"}
7469
},
7470
target_check = function (host, port, path, response)
7471
return response.status == 200
7472
and response.body
7473
and get_refresh_url(response.body, "/cgi%-bin/design/html_template/Login%.html$")
7474
and response.body:lower():find("<title>login cgicc form</title>", 1, true)
7475
end,
7476
login_combos = {
7477
{username = "admin", password = ""}
7478
},
7479
login_check = function (host, port, path, user, pass)
7480
local resp = http_post_simple(host, port,
7481
url.absolute(path, "cgi-bin/design/html_template/Login.cgi"),
7482
nil, {login_txt_id=user, login_txt_pw=pass})
7483
return resp.status == 200
7484
and resp.body
7485
and resp.body:find("%Wlocation%s*=%s*(['\"])webviewer%.cgi%1")
7486
end
7487
})
7488
7489
table.insert(fingerprints, {
7490
name = "Foscam Netwave (var.1)",
7491
cpe = "cpe:/o:foscam:ip_camera_firmware",
7492
category = "security",
7493
paths = {
7494
{path = "/"}
7495
},
7496
target_check = function (host, port, path, response)
7497
return response.status == 200
7498
and response.header["server"] == "Netwave IP Camera"
7499
and response.body
7500
and get_tag(response.body, "script", {src="^check_user%.cgi$"})
7501
end,
7502
login_combos = {
7503
{username = "admin", password = ""}
7504
},
7505
login_check = function (host, port, path, user, pass)
7506
return try_http_auth(host, port, url.absolute(path, "check_user.cgi"),
7507
user, pass, false)
7508
end
7509
})
7510
7511
table.insert(fingerprints, {
7512
name = "Foscam Netwave (var.2)",
7513
category = "security",
7514
paths = {
7515
{path = "/"}
7516
},
7517
target_check = function (host, port, path, response)
7518
return response.status == 200
7519
and response.header["server"] == "Netwave IP Camera"
7520
and response.body
7521
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])index1%.htm%1")
7522
end,
7523
login_combos = {
7524
{username = "admin", password = ""}
7525
},
7526
login_check = function (host, port, path, user, pass)
7527
local lurl = url.absolute(path, "check_user.cgi") .. "?"
7528
.. url.build_query({user=user, pwd=pass})
7529
return try_http_auth(host, port, lurl, user, pass, false)
7530
end
7531
})
7532
7533
table.insert(fingerprints, {
7534
name = "Foscam IP Camera",
7535
category = "security",
7536
paths = {
7537
{path = "/"}
7538
},
7539
target_check = function (host, port, path, response)
7540
return response.status == 200
7541
and response.body
7542
and response.body:find("IPCam", 1, true)
7543
and response.body:lower():find("<title>ipcam client</title>", 1, true)
7544
and response.body:lower():find("%ssrc%s*=%s*['\"]js/main%.js['\"?]")
7545
end,
7546
login_combos = {
7547
{username = "admin", password = "admin"},
7548
{username = "admin", password = ""}
7549
},
7550
login_check = function (host, port, path, user, pass)
7551
local form = {usr=user,
7552
pwd=pass,
7553
cmd="logIn",
7554
usrName=user,
7555
groupId=string.sub(math.floor(stdnse.clock_ms()), -9)}
7556
local lurl = "cgi-bin/CGIProxy.fcgi?" .. url.build_query(form)
7557
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7558
return resp.status == 200
7559
and (resp.body or ""):find("<logInResult>0</logInResult>", 1, true)
7560
end
7561
})
7562
7563
table.insert(fingerprints, {
7564
name = "ITX Web Remote Viewer",
7565
category = "security",
7566
paths = {
7567
{path = "/"}
7568
},
7569
target_check = function (host, port, path, response)
7570
if response.status == 200
7571
and get_refresh_url(response.body, "/redirect%.html$") then
7572
response = http_get_simple(host, port, url.absolute(path, "redirect.html"))
7573
end
7574
return http_auth_realm(response) == "WEB Remote Viewer"
7575
end,
7576
login_combos = {
7577
{username = "ADMIN", password = "1234"}
7578
},
7579
login_check = function (host, port, path, user, pass)
7580
return try_http_auth(host, port, url.absolute(path, "html/versioninfo.htm"),
7581
user, pass, false)
7582
end
7583
})
7584
7585
table.insert(fingerprints, {
7586
name = "JVC VN-xxx Camera",
7587
category = "security",
7588
paths = {
7589
{path = "/"}
7590
},
7591
target_check = function (host, port, path, response)
7592
return response.status == 200
7593
and (response.header["server"] or ""):find("^JVC VN%-%w+ API Server%f[/\0]")
7594
and response.body
7595
and get_refresh_url(response.body, "/cgi%-bin/%w+%.cgi%?%w+%.html$")
7596
end,
7597
login_combos = {
7598
{username = "admin", password = "jvc"}
7599
},
7600
login_check = function (host, port, path, user, pass)
7601
local resp = http_get_simple(host, port, path)
7602
local lurl = resp.status == 200
7603
and get_refresh_url(resp.body or "", "/cgi%-bin/%w+%.cgi%?%w+%.html$")
7604
if not lurl then return false end
7605
return try_http_auth(host, port, lurl, user, pass, false)
7606
end
7607
})
7608
7609
table.insert(fingerprints, {
7610
name = "JVC VR-8xx DVR",
7611
category = "security",
7612
paths = {
7613
{path = "/"}
7614
},
7615
target_check = function (host, port, path, response)
7616
return http_auth_realm(response) == "VR-8xx"
7617
end,
7618
login_combos = {
7619
{username = "admin", password = "jvc"}
7620
},
7621
login_check = function (host, port, path, user, pass)
7622
return try_http_auth(host, port, path, user, pass, false)
7623
end
7624
})
7625
7626
table.insert(fingerprints, {
7627
name = "JVC Broadcaster",
7628
category = "security",
7629
paths = {
7630
{path = "/"}
7631
},
7632
target_check = function (host, port, path, response)
7633
return (http_auth_realm(response) or ""):find("^JVC Broadcaster %d+%.%d+")
7634
end,
7635
login_combos = {
7636
{username = "admin", password = "jvc1234"}
7637
},
7638
login_check = function (host, port, path, user, pass)
7639
return try_http_auth(host, port, path, user, pass, false)
7640
end
7641
})
7642
7643
table.insert(fingerprints, {
7644
name = "OEM DVR",
7645
category = "security",
7646
paths = {
7647
{path = "/"}
7648
},
7649
target_check = function (host, port, path, response)
7650
return response.status == 200
7651
and response.body
7652
and response.body:find("%Wdocument%.location%.replace%(%s*(['\"])mlogin%.cgi%1%s*%)%s*;")
7653
and response.body:lower():find("<title>dvr login</title>", 1, true)
7654
end,
7655
login_combos = {
7656
{username = "admin", password = ""}
7657
},
7658
login_check = function (host, port, path, user, pass)
7659
local form = {c_userid=user,
7660
c_password=pass,
7661
c_target=2}
7662
local resp = http_post_simple(host, port,
7663
url.absolute(path, "direct_open_setup.cgi"),
7664
nil, form)
7665
return resp.status == 200
7666
and get_tag(resp.body or "", "script", {src="^setup%.js$"})
7667
end
7668
})
7669
7670
table.insert(fingerprints, {
7671
name = "Samsung DVR",
7672
cpe = "cpe:/h:samsung:dvr",
7673
category = "security",
7674
paths = {
7675
{path = "/"}
7676
},
7677
target_check = function (host, port, path, response)
7678
return have_openssl
7679
and response.status == 200
7680
and response.body
7681
and response.body:find("Samsung", 1, true)
7682
and response.body:lower():find("<title>web viewer for samsung dvr</title>", 1, true)
7683
end,
7684
login_combos = {
7685
{username = "admin", password = "4321"}
7686
},
7687
login_check = function (host, port, path, user, pass)
7688
local cookie = ("DATA1=%s&DATA2=%s&SDATA3=%.15f"):format(base64.enc(user),
7689
base64.enc(pass),
7690
math.random())
7691
local form = {lang="en",
7692
port=0,
7693
close_user_session=0,
7694
data1=base64.enc(user),
7695
data2=stdnse.tohex(openssl.md5(pass))}
7696
local resp = http_post_simple(host, port,
7697
url.absolute(path, "cgi-bin/webviewer_cgi_login2"),
7698
{cookies=cookie}, form)
7699
return resp.status == 200
7700
and (resp.body or ""):find("%Wtop%.document%.location%.href%s*=%s*['\"]%.%./index%.htm[?'\"]")
7701
end
7702
})
7703
7704
table.insert(fingerprints, {
7705
name = "Samsung iPOLiS",
7706
cpe = "cpe:/a:samsung:ipolis_device_manager",
7707
category = "security",
7708
paths = {
7709
{path = "/"}
7710
},
7711
target_check = function (host, port, path, response)
7712
if not (response.status == 200
7713
and response.body
7714
and response.body:find("home/monitoring.cgi", 1, true)
7715
and response.body:find("%Wdocument%.location%.replace%((['\"])[^'\"]-%f[^/'\"]home/monitoring%.cgi%1%)%s*;")) then
7716
return false
7717
end
7718
local resp = http_get_simple(host, port,
7719
url.absolute(path, "home/monitoring.cgi"))
7720
return (http_auth_realm(resp) or ""):find("^iPolis%f[_\0]")
7721
end,
7722
login_combos = {
7723
{username = "admin", password = "4321"}
7724
},
7725
login_check = function (host, port, path, user, pass)
7726
return try_http_auth(host, port, url.absolute(path, "home/monitoring.cgi"),
7727
user, pass, true)
7728
end
7729
})
7730
7731
table.insert(fingerprints, {
7732
name = "Truen TCAM (var.1)",
7733
category = "security",
7734
paths = {
7735
{path = "/"}
7736
},
7737
target_check = function (host, port, path, response)
7738
return response.status == 200
7739
and response.body
7740
and response.body:find("/user/view.html", 1, true)
7741
and get_tag(response.body, "frame", {src="/user/view%.html$"})
7742
and response.body:lower():find("<title>video surveillance</title>", 1, true)
7743
end,
7744
login_combos = {
7745
{username = "admin", password = "1234"}
7746
},
7747
login_check = function (host, port, path, user, pass)
7748
return try_http_auth(host, port, url.absolute(path, "user/view.html"),
7749
user, pass, false)
7750
end
7751
})
7752
7753
table.insert(fingerprints, {
7754
name = "Truen TCAM (var.2)",
7755
category = "security",
7756
paths = {
7757
{path = "/"}
7758
},
7759
target_check = function (host, port, path, response)
7760
local lurl = response.status == 200
7761
and get_refresh_url(response.body or "", "/user/view%.html$")
7762
if not lurl then return false end
7763
local resp = http_get_simple(host, port, lurl)
7764
return (http_auth_realm(resp) or ""):find("^IPVideo_%x+$")
7765
end,
7766
login_combos = {
7767
{username = "admin", password = "1234"}
7768
},
7769
login_check = function (host, port, path, user, pass)
7770
return try_http_auth(host, port, url.absolute(path, "user/view.html"),
7771
user, pass, "any")
7772
end
7773
})
7774
7775
table.insert(fingerprints, {
7776
name = "TVT DVR",
7777
category = "security",
7778
paths = {
7779
{path = "/"}
7780
},
7781
target_check = function (host, port, path, response)
7782
if not (response.status == 200
7783
and response.body
7784
and response.body:find("Pages/login.htm", 1, true)
7785
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])Pages/login%.htm%1")) then
7786
return false
7787
end
7788
local resp = http_get_simple(host, port,
7789
url.absolute(path, "Pages/login.htm"))
7790
return resp.status == 200
7791
and resp.body
7792
and resp.body:find("IDCS_LOGIN_NBSP", 1, true)
7793
end,
7794
login_combos = {
7795
{username = "admin", password = "123456"},
7796
{username = "admin", password = "1"}
7797
},
7798
login_check = function (host, port, path, user, pass)
7799
local auth = {username = user, password = pass}
7800
local header = {["Content-Type"]="text/plain;charset=UTF-8"}
7801
local msg = [=[
7802
<?xml version="1.0" encoding="utf-8" ?>
7803
<request version="1.0" systemType="NVMS-9000" clientType="WEB"/>
7804
]=]
7805
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
7806
local resp = http_post_simple(host, port, url.absolute(path, "doLogin"),
7807
{auth=auth, header=header}, msg)
7808
return resp.status == 200
7809
and (resp.body or ""):find("<status>success</status>", 1, true)
7810
end
7811
})
7812
7813
table.insert(fingerprints, {
7814
name = "Ubiquiti UniFi Video (var.1)",
7815
category = "security",
7816
paths = {
7817
{path = "/"}
7818
},
7819
target_check = function (host, port, path, response)
7820
return response.status == 200
7821
and response.body
7822
and response.body:find(">UniFi Video<", 1, true)
7823
and response.body:lower():find("<title>unifi video</title>", 1, true)
7824
and get_tag(response.body, "main-view", {["ui-view"]=""})
7825
and get_tag(response.body, "script", {["data-headjs-load"]="^main%.js%f[\0?]"})
7826
end,
7827
login_combos = {
7828
{username = "ubnt", password = "ubnt"}
7829
},
7830
login_check = function (host, port, path, user, pass)
7831
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "login")})),
7832
["Content-Type"]="application/json",
7833
["Accept"]="application/json, text/plain, */*"}
7834
local jin = {username=user, password=pass}
7835
json.make_object(jin)
7836
local resp = http_post_simple(host, port,
7837
url.absolute(path, "api/1.1/login"),
7838
{cookies="ubntActiveUser=false", header=header},
7839
json.generate(jin))
7840
return resp.status == 200
7841
and get_cookie(resp, "authId", "^%w+$")
7842
end
7843
})
7844
7845
table.insert(fingerprints, {
7846
name = "Ubiquiti UniFi Video (var.2)",
7847
category = "security",
7848
paths = {
7849
{path = "/"}
7850
},
7851
target_check = function (host, port, path, response)
7852
return response.status == 200
7853
and response.body
7854
and response.body:find(">UniFi Video<", 1, true)
7855
and response.body:find("app-id=com.ubnt.unifivideo", 1, true)
7856
and response.body:lower():find("<title>unifi video</title>", 1, true)
7857
and get_tag(response.body, "meta", {name="^google%-play%-app$", content="^app%-id=com%.ubnt%.unifivideo$"})
7858
end,
7859
login_combos = {
7860
{username = "ubnt", password = "ubnt"}
7861
},
7862
login_check = function (host, port, path, user, pass)
7863
local resp1 = http_get_simple(host, port, path)
7864
if resp1.status ~= 200 then return false end
7865
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "login")})),
7866
["Content-Type"]="application/json",
7867
["Accept"]="application/json, text/plain, */*"}
7868
local jin = {username=user, password=pass}
7869
json.make_object(jin)
7870
local resp2 = http_post_simple(host, port,
7871
url.absolute(path, "api/2.0/login"),
7872
{cookies=resp1.cookies, header=header},
7873
json.generate(jin))
7874
return resp2.status == 200
7875
and get_cookie(resp2, "JSESSIONID_AV", "^%x+$")
7876
end
7877
})
7878
7879
table.insert(fingerprints, {
7880
name = "Xiongmai NETSurveillance",
7881
category = "security",
7882
paths = {
7883
{path = "/"}
7884
},
7885
target_check = function (host, port, path, response)
7886
return response.status == 200
7887
and response.body
7888
and response.body:find("%Wlocation%s*=%s*(['\"])Login%.htm%1%s*;")
7889
and response.body:find("%Wvar%s+gHashCookie%s*=%s*new%s+Hash%.Cookie%(%s*(['\"])NetSuveillanceWebCookie%1%s*,")
7890
end,
7891
login_combos = {
7892
{username = "admin", password = ""},
7893
{username = "default", password = "tluafed"}
7894
},
7895
login_check = function (host, port, path, user, pass)
7896
local cookie = "NetSuveillanceWebCookie="
7897
.. url.escape(('{"username":"%s"}'):format(user))
7898
local form = stdnse.output_table()
7899
form.command = "login"
7900
form.username = user
7901
form.password = pass
7902
local resp = http_post_simple(host, port, url.absolute(path, "Login.htm"),
7903
{cookies=cookie}, form)
7904
return resp.status == 200
7905
and (resp.body or ""):match("%Wvar%s+g_user%s*=%s*['\"](.-)['\"]%s*;") == user
7906
end
7907
})
7908
7909
table.insert(fingerprints, {
7910
name = "AVTech AVC DVR",
7911
category = "security",
7912
paths = {
7913
{path = "/"}
7914
},
7915
target_check = function (host, port, path, response)
7916
return response.status == 200
7917
and response.body
7918
and response.body:find("MM_goToURL", 1, true)
7919
and response.body:lower():find("<title>--- video web server ---</title>", 1, true)
7920
end,
7921
login_combos = {
7922
{username = "admin", password = "admin"}
7923
},
7924
login_check = function (host, port, path, user, pass)
7925
local form = {username=user,
7926
password=pass,
7927
Submit="Submit"}
7928
local resp = http_post_simple(host, port, url.absolute(path, "home.htm"),
7929
nil, form)
7930
return resp.status == 200
7931
and (resp.body or ""):lower():find("<object%s")
7932
end
7933
})
7934
7935
table.insert(fingerprints, {
7936
name = "AVTech IP Camera",
7937
category = "security",
7938
paths = {
7939
{path = "/"}
7940
},
7941
target_check = function (host, port, path, response)
7942
return response.status == 200
7943
and response.body
7944
and response.body:find("/nobody/", 1, true)
7945
and response.body:lower():find("<title>::: login :::</title>", 1, true)
7946
end,
7947
login_combos = {
7948
{username = "admin", password = "admin"}
7949
},
7950
login_check = function (host, port, path, user, pass)
7951
local creds = base64.enc(user .. ":" .. pass)
7952
local lurl = ("cgi-bin/nobody/VerifyCode.cgi?account=%s&rnd=%.15f"):format(
7953
creds, math.random())
7954
local resp = http_get_simple(host, port, url.absolute(path, lurl))
7955
return resp.status == 200
7956
and get_cookie(resp, "SSID") == creds
7957
end
7958
})
7959
7960
table.insert(fingerprints, {
7961
name = "EverFocus ECORHD",
7962
category = "security",
7963
paths = {
7964
{path = "/"}
7965
},
7966
target_check = function (host, port, path, response)
7967
local realm = http_auth_realm(response) or ""
7968
return realm:find("^ECOR%d+%-[%u%d]+$")
7969
or realm:find("^ELUX%d+$")
7970
end,
7971
login_combos = {
7972
{username = "admin", password = "11111111"},
7973
{username = "user1", password = "11111111"},
7974
{username = "user2", password = "11111111"}
7975
},
7976
login_check = function (host, port, path, user, pass)
7977
return try_http_auth(host, port, path, user, pass, true)
7978
end
7979
})
7980
7981
table.insert(fingerprints, {
7982
name = "Interlogix truVision",
7983
category = "security",
7984
paths = {
7985
{path = "/index.asp"}
7986
},
7987
target_check = function (host, port, path, response)
7988
return response.status == 200
7989
and response.header["server"] == "Interlogix-Webs"
7990
and response.body
7991
and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])doc/page/login%.asp%1")
7992
end,
7993
login_combos = {
7994
{username = "admin", password = "1234"}
7995
},
7996
login_check = function (host, port, path, user, pass)
7997
local header = {["Content-Type"]="text/xml"}
7998
local creds = {username = user, password = pass, digest = false}
7999
local ipaddr = ("192.168.%d.%d"):format(math.random(254), math.random(254))
8000
local macaddr = random_hex(12):gsub("..", ":%1"):sub(2)
8001
local msg = [[
8002
<?xml version="1.0" encoding="utf-8"?>
8003
<userCheck>
8004
<ipAddress>__IPADDR__</ipAddress>
8005
<macAddress>__MACADDR__</macAddress>
8006
</userCheck>]]
8007
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
8008
msg = msg:gsub("__%w+__", {__IPADDR__=ipaddr, __MACADDR__=macaddr})
8009
local resp = http_post_simple(host, port,
8010
url.absolute(path, "PSIA/Custom/SelfExt/userCheckEx"),
8011
{header=header, auth=creds}, msg)
8012
return resp.status == 200
8013
and (resp.body or ""):find("<statusValue>200</statusValue>", 1, true)
8014
end
8015
})
8016
8017
table.insert(fingerprints, {
8018
name = "LILIN NVR",
8019
category = "security",
8020
paths = {
8021
{path = "/"}
8022
},
8023
target_check = function (host, port, path, response)
8024
return (http_auth_realm(response) or ""):find("^Merit LILIN")
8025
end,
8026
login_combos = {
8027
{username = "admin", password = "1111"}
8028
},
8029
login_check = function (host, port, path, user, pass)
8030
return try_http_auth(host, port, path, user, pass, false)
8031
end
8032
})
8033
8034
table.insert(fingerprints, {
8035
name = "NUUO NVR",
8036
category = "security",
8037
paths = {
8038
{path = "/"}
8039
},
8040
target_check = function (host, port, path, response)
8041
return response.status == 200
8042
and response.body
8043
and response.body:find("NUUO", 1, true)
8044
and response.body:lower():find("<title>nuuo network video recorder login</title>", 1, true)
8045
and get_tag(response.body, "form", {name="^mainform$", action="^index%.php$"})
8046
end,
8047
login_combos = {
8048
{username = "admin", password = "admin"}
8049
},
8050
login_check = function (host, port, path, user, pass)
8051
local form = {language="English",
8052
login=user,
8053
password=pass,
8054
submit=" Login "}
8055
local resp = http_post_simple(host, port, url.absolute(path, "index.php"),
8056
nil, form)
8057
return resp.status == 302
8058
and resp.header["location"] == "screen.php"
8059
end
8060
})
8061
8062
table.insert(fingerprints, {
8063
name = "NUUO Titan NVR",
8064
category = "security",
8065
paths = {
8066
{path = "/"}
8067
},
8068
target_check = function (host, port, path, response)
8069
return response.status == 200
8070
and response.body
8071
and response.body:find("NUUO", 1, true)
8072
and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")
8073
and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})
8074
and get_tag(response.body, "img", {type="^submit$", value="^login$"})
8075
end,
8076
login_combos = {
8077
{username = "admin", password = "admin"}
8078
},
8079
login_check = function (host, port, path, user, pass)
8080
local form = {language="en",
8081
user=user,
8082
pass=pass,
8083
browser_engine="firefox"}
8084
local resp = http_post_simple(host, port, url.absolute(path, "login.php"),
8085
nil, form)
8086
return (resp.status == 302
8087
and (resp.header["location"] or ""):find("/setting%.php$"))
8088
or (resp.status == 200
8089
and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))
8090
end
8091
})
8092
8093
table.insert(fingerprints, {
8094
name = "NUUO Solo NVR",
8095
cpe = "cpe:/o:nuuo:nvrsolo",
8096
category = "security",
8097
paths = {
8098
{path = "/"}
8099
},
8100
target_check = function (host, port, path, response)
8101
return response.status == 200
8102
and response.body
8103
and response.body:find("NUUO", 1, true)
8104
and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")
8105
and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})
8106
and get_tag(response.body, "input", {type="^submit$", name="^submit$"})
8107
end,
8108
login_combos = {
8109
{username = "admin", password = "admin"}
8110
},
8111
login_check = function (host, port, path, user, pass)
8112
local form = {language="en",
8113
user=user,
8114
pass=pass,
8115
submit="Login"}
8116
local resp = http_post_simple(host, port, url.absolute(path, "login.php"),
8117
nil, form)
8118
return (resp.status == 302
8119
and (resp.header["location"] or ""):find("/setting%.php$"))
8120
or (resp.status == 200
8121
and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))
8122
end
8123
})
8124
8125
table.insert(fingerprints, {
8126
name = "NUUO Solo NVR OEM",
8127
category = "security",
8128
paths = {
8129
{path = "/"}
8130
},
8131
target_check = function (host, port, path, response)
8132
return response.status == 200
8133
and response.body
8134
and response.body:find("NUUO", 1, true)
8135
and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")
8136
and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})
8137
and get_tag(response.body, "input", {type="^image$", name="^submit$"})
8138
end,
8139
login_combos = {
8140
{username = "admin", password = "admin"}
8141
},
8142
login_check = function (host, port, path, user, pass)
8143
local form = {["submit.x"]=0,
8144
["submit.y"]=0,
8145
language="en",
8146
user=user,
8147
pass=pass,
8148
browser_engine="firefox",
8149
base_url=""}
8150
local resp = http_post_simple(host, port, url.absolute(path, "login.php"),
8151
nil, form)
8152
return (resp.status == 302
8153
and (resp.header["location"] or ""):find("/setting%.php$"))
8154
or (resp.status == 200
8155
and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))
8156
end
8157
})
8158
8159
table.insert(fingerprints, {
8160
name = "VideoIQ iCVR",
8161
category = "security",
8162
paths = {
8163
{path = "/"}
8164
},
8165
target_check = function (host, port, path, response)
8166
return response.status == 302
8167
and (response.header["location"] or ""):find("?wicket:bookmarkablePage=:com.videoiq.fusion.camerawebapi.ui.pages.LoginPage", 1, true)
8168
end,
8169
login_combos = {
8170
{username = "supervisor", password = "supervisor"}
8171
},
8172
login_check = function (host, port, path, user, pass)
8173
local resp1 = http_get_simple(host, port, path)
8174
local lurl = (resp1.header["location"] or ""):match("%f[/]/%f[^/].*")
8175
if not (resp1.status == 302 and lurl) then return false end
8176
local form = {loginForm1_hf_0="",
8177
userName=user,
8178
password=pass,
8179
login=""}
8180
local resp2 = http_post_simple(host, port,
8181
lurl .. "&wicket:interface=:0:loginPanel:loginForm::IFormSubmitListener::",
8182
{cookies=resp1.cookies}, form)
8183
return resp2.status == 302
8184
end
8185
})
8186
8187
table.insert(fingerprints, {
8188
name = "Dahua Security",
8189
cpe = "cpe:/o:dahuasecurity:dvr_firmware",
8190
category = "security",
8191
paths = {
8192
{path = "/"}
8193
},
8194
target_check = function (host, port, path, response)
8195
return have_openssl
8196
and response.status == 200
8197
and response.body
8198
and (response.body:find("js/loginEx.js", 1, true)
8199
and get_tag(response.body, "script", {src="^js/loginEx%.js%f[?\0]"})
8200
and get_tag(response.body, "script", {src="^jsCore/rpcCore%.js%f[?\0]"})
8201
or response.body:find("/js/merge.js", 1, true)
8202
and get_tag(response.body, "script", {src="/js/merge%.js$"})
8203
and get_tag(response.body, "div", {id="^download_plugins$"})
8204
or response.body:find("jsBase/widget/js/dui.tab.js", 1, true)
8205
and get_tag(response.body, "script", {src="^jsBase/widget/js/dui%.tab%.js%f[?\0]"})
8206
and get_tag(response.body, "script", {src="^jsCore/common%.js%f[?\0]"}))
8207
end,
8208
login_combos = {
8209
{username = "666666", password = "666666"},
8210
{username = "admin", password = "admin"},
8211
{username = "anonymity", password = "anonymity"}
8212
},
8213
login_check = function (host, port, path, user, pass)
8214
local lurl = url.absolute(path, "RPC2_Login")
8215
local opts = {cookies="DHLangCookie30=English",
8216
header={["X-Request"]="JSON"}}
8217
local jin = {method="global.login",
8218
params={userName=user,
8219
password="",
8220
clientType="Web3.0"},
8221
id=10000}
8222
json.make_object(jin)
8223
local resp1 = http_post_simple(host, port, lurl, opts, json.generate(jin))
8224
if not (resp1.status == 200 and resp1.body) then return false end
8225
local jstatus, jout = json.parse(resp1.body)
8226
local params = jstatus and jout.params
8227
if not params then return false end
8228
local passtype
8229
if not params.encryption then
8230
elseif params.encryption == "Basic" then
8231
pass = base64.enc(user .. ":" .. pass)
8232
elseif params.encryption == "Default" then
8233
local hashfnc = function (...)
8234
local text = table.concat({...}, ":")
8235
return stdnse.tohex(openssl.md5(text)):upper()
8236
end
8237
if not (params.random and params.realm) then return false end
8238
pass = hashfnc(user, params.random, hashfnc(user, params.realm, pass))
8239
passtype = "Default"
8240
elseif params.encryption == "OldDigest" then
8241
local hash = openssl.md5(pass)
8242
local ptbl = {}
8243
for i = 1, #hash, 2 do
8244
local a, b = hash:byte(i, i + 1)
8245
a = (a + b) % 62
8246
if a <= 9 then
8247
b = 48
8248
elseif a <= 35 then
8249
b = 55
8250
else
8251
b = 61
8252
end
8253
table.insert(ptbl, string.char(a + b))
8254
end
8255
pass = table.concat(ptbl)
8256
else
8257
return false
8258
end
8259
opts.cookies = opts.cookies .. "; DhWebClientSessionID=" .. jout.session
8260
jin.session = jout.session
8261
jin.params.password = pass
8262
jin.params.passwordType = passtype
8263
jin.params.authorityType = params.encryption
8264
local resp2 = http_post_simple(host, port, lurl, opts, json.generate(jin))
8265
if not (resp2.status == 200 and resp2.body) then return false end
8266
jstatus, jout = json.parse(resp2.body)
8267
return jstatus and jout.result
8268
end
8269
})
8270
8271
table.insert(fingerprints, {
8272
name = "Digital Watchdog",
8273
category = "security",
8274
paths = {
8275
{path = "/"}
8276
},
8277
target_check = function (host, port, path, response)
8278
return have_openssl
8279
and response.status == 301
8280
and (response.header["location"] or ""):find("/static/index%.html$")
8281
and (response.header["server"] or ""):find("(Digital Watchdog)", 1, true)
8282
end,
8283
login_combos = {
8284
{username = "admin", password = "admin"}
8285
},
8286
login_check = function (host, port, path, user, pass)
8287
local lurl = url.absolute(path, "api/getCurrentUser")
8288
local resp1 = http_get_simple(host, port, lurl, {cookies="Authorization=Digest"})
8289
local realm = get_cookie(resp1, "realm")
8290
local nonce = get_cookie(resp1, "nonce")
8291
if not (resp1.status == 401 and realm and nonce) then return false end
8292
user = user:lower()
8293
local hashfnc = function (...)
8294
local text = table.concat({...}, ":")
8295
return stdnse.tohex(openssl.md5(text))
8296
end
8297
local hash = hashfnc(hashfnc(user, realm, pass), nonce, hashfnc("GET:"))
8298
local auth = url.escape(base64.enc(table.concat({user, nonce, hash}, ":")))
8299
table.insert(resp1.cookies, {name="Authorization", value="Digest", path=path})
8300
table.insert(resp1.cookies, {name="auth", value=auth, path=path})
8301
local resp2 = http_get_simple(host, port, lurl, {cookies=resp1.cookies})
8302
return resp2.status == 200
8303
and resp2.header["content-type"] == "application/json"
8304
end
8305
})
8306
8307
table.insert(fingerprints, {
8308
name = "Loxone Intercom Video",
8309
category = "security",
8310
paths = {
8311
{path = "/"}
8312
},
8313
target_check = function (host, port, path, response)
8314
return response.status == 200
8315
and (response.header["server"] or ""):find("HyNetOS/%d+%.")
8316
and response.body
8317
and response.body:find("Loxone", 1, true)
8318
and response.body:lower():find("<title>loxone intercom video</title>", 1, true)
8319
end,
8320
login_combos = {
8321
{username = "admin", password = "admin"}
8322
},
8323
login_check = function (host, port, path, user, pass)
8324
return try_http_auth(host, port, url.absolute(path, "setup.cgi"),
8325
user, pass, false)
8326
end
8327
})
8328
8329
table.insert(fingerprints, {
8330
name = "Loxone Smart Home",
8331
category = "security",
8332
paths = {
8333
{path = "/"}
8334
},
8335
target_check = function (host, port, path, response)
8336
return have_openssl
8337
and response.status == 200
8338
and response.body
8339
and response.body:find("Loxone", 1, true)
8340
and response.body:lower():find("<title>loxone smart home</title>", 1, true)
8341
end,
8342
login_combos = {
8343
{username = "admin", password = "admin"}
8344
},
8345
login_check = function (host, port, path, user, pass)
8346
local resp1 = http_get_simple(host, port,
8347
url.absolute(path, "jdev/cfg/apiKey"))
8348
if not (resp1.status == 200 and resp1.body) then return false end
8349
local jstatus, jout = json.parse(resp1.body)
8350
if not (jstatus and jout.LL.value) then return false end
8351
jstatus, jout = json.parse(jout.LL.value:gsub("'", '"'))
8352
if not (jstatus and jout.key) then return false end
8353
local key = stdnse.fromhex(jout.key)
8354
local auth = stdnse.tohex(openssl.hmac("SHA1", key, user .. ":" .. pass))
8355
local lurl = "jdev/sps/LoxAPPversion3?" .. url.build_query({auth=auth,user=user})
8356
local resp2 = http_get_simple(host, port, url.absolute(path, lurl))
8357
return resp2.status == 200
8358
end
8359
})
8360
8361
table.insert(fingerprints, {
8362
name = "Automa Lilliput2",
8363
category = "security",
8364
paths = {
8365
{path = "/login.php"}
8366
},
8367
target_check = function (host, port, path, response)
8368
return response.status == 200
8369
and response.body
8370
and response.body:find("Automa", 1, true)
8371
and response.body:lower():find("<title>[^<]-%sautoma srl</title>")
8372
end,
8373
login_combos = {
8374
{username = "admin", password = "admin"}
8375
},
8376
login_check = function (host, port, path, user, pass)
8377
local resp = http_post_simple(host, port, path, nil,
8378
{username=user,password=pass,submit="Login"})
8379
return resp.status == 302
8380
and resp.header["location"] == "index.php"
8381
end
8382
})
8383
8384
table.insert(fingerprints, {
8385
name = "Siedle Door Controller",
8386
category = "security",
8387
paths = {
8388
{path = "/"}
8389
},
8390
target_check = function (host, port, path, response)
8391
return response.status == 200
8392
and response.header["server"] == "Z-World Rabbit"
8393
and response.body
8394
and response.body:lower():find("<title></title>", 1, true)
8395
and response.body:lower():find("%Wparent%.location%s*=%s*(['\"])[^'\"]-/index%.zht%1")
8396
end,
8397
login_combos = {
8398
{username = "Service", password = "Siedle"}
8399
},
8400
login_check = function (host, port, path, user, pass)
8401
local resp1 = http_get_simple(host, port, url.absolute(path, "login.zht"))
8402
if not (resp1.status == 200 and resp1.body) then return false end
8403
local lang = resp1.body:lower():match("<select%f[%s][^>]-%sname%s*=%s*['\"]m_webdata%.m_cgilogin%.m_lang['\"].-<option%f[%s]([^>]-%sselected%f[%s>][^>]*)")
8404
lang = (lang or ""):match("%svalue%s*=%s*['\"](%w+)['\"]")
8405
if not lang then return false end
8406
local form2 = stdnse.output_table()
8407
form2["m_webdata.m_cgiLogin.m_user"] = user
8408
form2["m_webdata.m_cgiLogin.m_passwd"] = pass
8409
form2["m_webdata.m_cgiLogin.m_lang"] = lang
8410
form2["action.x"] = 0
8411
form2["action.y"] = 0
8412
local resp2 = http_post_simple(host, port, url.absolute(path, "login.cgi"),
8413
nil, form2)
8414
return resp2.status == 302
8415
and (resp2.header["location"] or ""):find("/index%.zht$")
8416
and get_cookie(resp2, "DCRABBIT", "^%-?%d+$")
8417
end
8418
})
8419
8420
table.insert(fingerprints, {
8421
name = "Genetec Synergis",
8422
category = "security",
8423
paths = {
8424
{path = "/"}
8425
},
8426
target_check = function (host, port, path, response)
8427
if not (response.status == 200
8428
and response.header["server"] == "Microsoft-HTTPAPI/2.0"
8429
and response.body
8430
and get_refresh_url(response.body, "/ui$")) then
8431
return false
8432
end
8433
local resp = http_get_simple(host, port,
8434
url.absolute(path, "ui/LogOn?ReturnUrl=%2fui"))
8435
return resp.status == 200
8436
and resp.body
8437
and resp.body:find("/genetec.")
8438
end,
8439
login_combos = {
8440
{username = "admin", password = "softwire"}
8441
},
8442
login_check = function (host, port, path, user, pass)
8443
local form = {UserName=user,
8444
Password=pass,
8445
Language="En",
8446
TimeZoneOffset=0}
8447
local resp = http_post_simple(host, port,
8448
url.absolute(path, "ui/LogOn?ReturnUrl=%2fui"),
8449
nil, form)
8450
return resp.status == 302
8451
and (resp.header["location"] or ""):find("/ui$")
8452
end
8453
})
8454
8455
---
8456
--Industrial systems
8457
---
8458
table.insert(fingerprints, {
8459
name = "Schneider Modicon Web",
8460
category = "industrial",
8461
paths = {
8462
{path = "/"}
8463
},
8464
target_check = function (host, port, path, response)
8465
return response.status == 302
8466
and (response.header["server"] or ""):find("^Schneider%-WEB/V%d+%.")
8467
and (response.header["location"] or ""):find("/index%.htm$")
8468
end,
8469
login_combos = {
8470
{username = "USER", password = "USER"}
8471
},
8472
login_check = function (host, port, path, user, pass)
8473
return try_http_auth(host, port,
8474
url.absolute(path, "secure/embedded/http_passwd_config.htm?Language=English"),
8475
user, pass, false)
8476
end
8477
})
8478
8479
table.insert(fingerprints, {
8480
name = "Schneider Xflow",
8481
category = "industrial",
8482
paths = {
8483
{path = "/"}
8484
},
8485
target_check = function (host, port, path, response)
8486
return have_openssl
8487
and response.status == 200
8488
and response.body
8489
and response.body:find("Xflow", 1, true)
8490
and get_tag(response.body, "input", {name="^rsakey1$"})
8491
end,
8492
login_combos = {
8493
{username = "TEST", password = "TEST"}
8494
},
8495
login_check = function (host, port, path, user, pass)
8496
local resp1 = http_get_simple(host, port, path)
8497
if not (resp1.status == 200 and resp1.body) then return false end
8498
local rsakey1 = get_tag(resp1.body, "input", {name="^rsakey1$", value="^%d+$"})
8499
local rsakey2 = get_tag(resp1.body, "input", {name="^rsakey2$", value="^%d+$"})
8500
if not (rsakey1 and rsakey2) then return false end
8501
local p = openssl.bignum_dec2bn(rsakey1.value)
8502
local m = openssl.bignum_dec2bn(rsakey2.value)
8503
local encpass = {}
8504
local r = 0
8505
for _, s in ipairs({pass:byte(1, -1)}) do
8506
local a = openssl.bignum_dec2bn(r + s)
8507
local b = openssl.bignum_bn2dec(openssl.bignum_mod_exp(a, p, m))
8508
table.insert(encpass, ("%04x"):format(b))
8509
r = s
8510
end
8511
table.insert(encpass, 1, ("0000"):rep(16-#encpass))
8512
local form2 = {language="EN",
8513
login="home.xml",
8514
username=user,
8515
rsakey1=rsakey1.value,
8516
rsakey2=rsakey2.value,
8517
pwd=table.concat(encpass):upper(),
8518
enter="Log in"}
8519
local resp2 = http_post_simple(host, port, url.absolute(path, "kw"),
8520
nil, form2)
8521
return resp2.status == 200
8522
and (resp2.body or ""):find("%Wvar%s+sessionid%s*=%s*(['\"])%x+%1")
8523
end
8524
})
8525
8526
table.insert(fingerprints, {
8527
name = "TCS Basys Controls Communication Center",
8528
category = "industrial",
8529
paths = {
8530
{path = "/"}
8531
},
8532
target_check = function (host, port, path, response)
8533
return http_auth_realm(response) == "Private"
8534
end,
8535
login_combos = {
8536
{username = "admin", password = "password"}
8537
},
8538
login_check = function (host, port, path, user, pass)
8539
return try_http_auth(host, port, path, user, pass, false)
8540
end
8541
})
8542
8543
table.insert(fingerprints, {
8544
name = "Adcon Telemetry Gateway",
8545
category = "industrial",
8546
paths = {
8547
{path = "/"}
8548
},
8549
target_check = function (host, port, path, response)
8550
return response.status == 200
8551
and response.body
8552
and response.body:find("Adcon", 1, true)
8553
and response.body:lower():find("<title>%s*adcon telemetry gateway%s*</title>")
8554
and get_tag(response.body, "a", {href="%f[%w]configurator%.jnlp$"})
8555
end,
8556
login_combos = {
8557
{username = "root", password = "840sw"},
8558
{username = "adv", password = "addvantage"}
8559
},
8560
login_check = function (host, port, path, user, pass)
8561
return try_http_auth(host, port, url.absolute(path, "getconfig"),
8562
user, pass, false)
8563
end
8564
})
8565
8566
table.insert(fingerprints, {
8567
name = "Lantronix ThinWeb Manager",
8568
category = "industrial",
8569
paths = {
8570
{path = "/"}
8571
},
8572
target_check = function (host, port, path, response)
8573
return have_openssl
8574
and response.status == 200
8575
and (response.header["server"] or ""):find("^Gordian Embedded")
8576
and response.body
8577
and response.body:find("Lantronix", 1, true)
8578
and response.body:lower():find("<title>lantronix %w*web manager%W")
8579
end,
8580
login_combos = {
8581
{username = "", password = "system"}
8582
},
8583
login_check = function (host, port, path, user, pass)
8584
local resp0 = http_get_simple(host, port, path)
8585
if not (resp0.status == 200 and resp0.body) then return false end
8586
local lurl = get_tag(resp0.body, "frame", {src="^summary%.html$"})
8587
and "server.html"
8588
or resp0.body:lower():match("<a%f[%s][^>]-%shref%s*=%s*['\"]([^'\"]+)['\"]%s*>server properties</a>")
8589
if not lurl then return false end
8590
lurl = url.absolute(path, lurl)
8591
local resp1 = http_get_simple(host, port, lurl)
8592
local nonce = resp1.status == 403 and get_cookie(resp1, "SrvrNonce", ".")
8593
if not nonce then return false end
8594
local creds = stdnse.tohex(openssl.md5(nonce .. ":" .. pass:upper()))
8595
local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)
8596
local resp2 = http_get_simple(host, port, lurl, {cookies=cookies})
8597
return resp2.status == 200
8598
end
8599
})
8600
8601
table.insert(fingerprints, {
8602
name = "Lantronix XPort",
8603
category = "industrial",
8604
paths = {
8605
{path = "/"}
8606
},
8607
target_check = function (host, port, path, response)
8608
return response.status == 200
8609
and response.body
8610
and response.body:find("secure/ltx_conf.htm", 1, true)
8611
end,
8612
login_combos = {
8613
{username = "", password = ""}
8614
},
8615
login_check = function (host, port, path, user, pass)
8616
return try_http_auth(host, port, url.absolute(path, "secure/ltx_conf.htm"),
8617
user, pass, false)
8618
end
8619
})
8620
8621
table.insert(fingerprints, {
8622
name = "Moxa MiiNePort",
8623
cpe = "cpe:/o:moxa:miineport_*",
8624
category = "industrial",
8625
paths = {
8626
{path = "/"}
8627
},
8628
target_check = function (host, port, path, response)
8629
return have_openssl
8630
and response.status == 307
8631
and (response.header["location"] or ""):find("/moxa/home%.htm$")
8632
end,
8633
login_combos = {
8634
{username = "admin", password = ""}
8635
},
8636
login_check = function (host, port, path, user, pass)
8637
local form = {Username=user,
8638
Password="",
8639
MD5Password=stdnse.tohex(openssl.md5(pass)),
8640
Submit="Login"}
8641
local resp = http_post_simple(host, port,
8642
url.absolute(path, "moxa/Login.htm"),
8643
nil, form)
8644
return resp.status == 200
8645
and (resp.body or ""):find("%Wwindow%.open%((['\"])home%.htm%1")
8646
end
8647
})
8648
8649
table.insert(fingerprints, {
8650
name = "MBus Webserver",
8651
category = "industrial",
8652
paths = {
8653
{path = "/"}
8654
},
8655
target_check = function (host, port, path, response)
8656
return http_auth_realm(response) == "MBus Webserver"
8657
and response.header["server"] == "MBus WebServer"
8658
end,
8659
login_combos = {
8660
{username = "admin", password = "admin"}
8661
},
8662
login_check = function (host, port, path, user, pass)
8663
return try_http_auth(host, port, path, user, pass, false)
8664
end
8665
})
8666
8667
table.insert(fingerprints, {
8668
name = "Silex Server (var.1)",
8669
cpe = "cpe:/o:silex:*",
8670
category = "industrial",
8671
paths = {
8672
{path = "/"}
8673
},
8674
target_check = function (host, port, path, response)
8675
return response.status == 200
8676
and response.body
8677
and response.body:find("/status/devstat.htm", 1, true)
8678
and response.body:lower():find("<title>%a%a%a?%-%w%w%-?%w+</title>")
8679
end,
8680
login_combos = {
8681
{username="root", password=""},
8682
{username="admin", password="admin"},
8683
{username="admin", password="1234"}
8684
},
8685
login_check = function (host, port, path, user, pass)
8686
local resp = http_get_simple(host, port, path)
8687
if not (resp.status == 200 and resp.body) then return false end
8688
local frm = get_tag(resp.body, "frame", {src="/%w+/status/devstat%.htm$"})
8689
if not frm then return false end
8690
local lang = frm.src:match("/(%w+)/status/devstat%.htm$")
8691
return try_http_auth(host, port,
8692
url.absolute(path, lang .. "/mnt/adpass.htm"),
8693
user, pass, false)
8694
end
8695
})
8696
8697
table.insert(fingerprints, {
8698
name = "Silex Server (var.2)",
8699
cpe = "cpe:/o:silex:*",
8700
category = "industrial",
8701
paths = {
8702
{path = "/"}
8703
},
8704
target_check = function (host, port, path, response)
8705
return response.status == 200
8706
and response.body
8707
and response.body:find("status.hti?", 1, true)
8708
and response.body:lower():find("<title>silex ", 1, true)
8709
end,
8710
login_combos = {
8711
{username="", password="ACCESS"}
8712
},
8713
login_check = function (host, port, path, user, pass)
8714
local form = {access="",
8715
password="",
8716
language=0,
8717
access_psw=pass,
8718
action="Submit"}
8719
local resp = http_post_simple(host, port, url.absolute(path, "login"),
8720
nil, form)
8721
return resp.status == 200
8722
and get_tag(resp.body or "", "frame", {src="^status%.hti%?access=%x+&"})
8723
end
8724
})
8725
8726
table.insert(fingerprints, {
8727
name = "Wago I/O System 750",
8728
cpe = "cpe:/h:wago:wago_i%2fo_system*",
8729
category = "industrial",
8730
paths = {
8731
{path = "/"}
8732
},
8733
target_check = function (host, port, path, response)
8734
return response.status == 302
8735
and (response.header["location"] or ""):find("/webserv/index%.ssi$")
8736
end,
8737
login_combos = {
8738
{username="admin", password="wago"},
8739
{username="user", password="user"},
8740
{username="guest", password="guest"}
8741
},
8742
login_check = function (host, port, path, user, pass)
8743
return try_http_auth(host, port,
8744
url.absolute(path, "webserv/cplcfg/security.ssi"),
8745
user, pass, false)
8746
end
8747
})
8748
8749
table.insert(fingerprints, {
8750
name = "Wago TO-PASS",
8751
category = "industrial",
8752
paths = {
8753
{path = "/"}
8754
},
8755
target_check = function (host, port, path, response)
8756
return http_auth_realm(response) == "WAGO TO-PASS"
8757
end,
8758
login_combos = {
8759
{username="admin", password="wago"},
8760
{username="user", password="user"},
8761
{username="guest", password="guest"}
8762
},
8763
login_check = function (host, port, path, user, pass)
8764
return try_http_auth(host, port, path, user, pass, true)
8765
end
8766
})
8767
8768
table.insert(fingerprints, {
8769
name = "ProMinent Controller",
8770
category = "industrial",
8771
paths = {
8772
{path = "/"}
8773
},
8774
target_check = function (host, port, path, response)
8775
return response.status == 200
8776
and response.header["server"] == "Z-World Rabbit"
8777
and response.body
8778
and get_tag(response.body, "frame", {src="^right%.shtml$"})
8779
end,
8780
login_combos = {
8781
{username = "Operator1", password = "1"},
8782
{username = "Operator2", password = "2"},
8783
{username = "Operator3", password = "3"},
8784
{username = "Operator4", password = "4"},
8785
{username = "Configure5", password = "5"},
8786
{username = "Configure6", password = "6"},
8787
{username = "Configure7", password = "7"},
8788
{username = "admin", password = "AAAA"}
8789
},
8790
login_check = function (host, port, path, user, pass)
8791
local usermap = {["Operator1"]=1,
8792
["Operator2"]=2,
8793
["Operator3"]=3,
8794
["Operator4"]=4,
8795
["Configure5"]=5,
8796
["Configure6"]=6,
8797
["Configure7"]=7,
8798
["admin"]=8}
8799
local lurl = ("taco.cgi?F0=AH&F1=%d&F2=%s"):format(usermap[user],pass)
8800
local resp = http_get_simple(host, port, url.absolute(path, lurl))
8801
return resp.status == 200
8802
and (get_cookie(resp, "DCRABBIT") or ""):lower() == user:lower()
8803
end
8804
})
8805
8806
table.insert(fingerprints, {
8807
name = "Emerson EC2",
8808
category = "industrial",
8809
paths = {
8810
{path = "/"}
8811
},
8812
target_check = function (host, port, path, response)
8813
return response.status == 200
8814
and response.body
8815
and response.body:find("EC2", 1, true)
8816
and response.body:lower():find("<title>ec2 %d+ ")
8817
and get_tag(response.body, "frame", {src="^bckgnd%.html$"})
8818
end,
8819
login_combos = {
8820
{username = "EmersonID", password = "12"}
8821
},
8822
login_check = function (host, port, path, user, pass)
8823
return try_http_auth(host, port, url.absolute(path, "tcp_ip.shtml.shtml"),
8824
user, pass, false)
8825
end
8826
})
8827
8828
table.insert(fingerprints, {
8829
name = "Emerson Xweb",
8830
category = "industrial",
8831
paths = {
8832
{path = "/"}
8833
},
8834
target_check = function (host, port, path, response)
8835
return response.status == 200
8836
and response.body
8837
and response.body:find("/cgi-bin/xweb500.cgi", 1, true)
8838
and response.body:find("%WUrl%s*=%s*(['\"])[^'\"]-/cgi%-bin/xweb500%.cgi%?res=%d%1")
8839
end,
8840
login_combos = {
8841
{username = "Admin", password = "Admin"}
8842
},
8843
login_check = function (host, port, path, user, pass)
8844
local form = {pg=2,
8845
action=2,
8846
act=0,
8847
login=user,
8848
passwd=pass}
8849
local resp = http_post_simple(host, port,
8850
url.absolute(path, "cgi-bin/user.cgi"),
8851
nil, form)
8852
return resp.status == 200
8853
and resp.body
8854
and resp.body:find("%Wvar%s+value%s*=%s*(['\"])" .. user .. "%1")
8855
and resp.body:find("%Wlocation%.href%s*=%s*(['\"])[^'\"]-/index/indexFr%.html%1")
8856
end
8857
})
8858
8859
table.insert(fingerprints, {
8860
name = "Heatmiser Wifi Thermostat",
8861
category = "industrial",
8862
paths = {
8863
{path = "/"}
8864
},
8865
target_check = function (host, port, path, response)
8866
return response.status == 200
8867
and response.body
8868
and response.body:find("Heatmiser", 1, true)
8869
and response.body:lower():find("<title>heatmiser wifi thermostat</title>", 1, true)
8870
and get_tag(response.body, "input", {name="^lgpw$"})
8871
end,
8872
login_combos = {
8873
{username = "admin", password = "admin"}
8874
},
8875
login_check = function (host, port, path, user, pass)
8876
local resp = http_post_simple(host, port, path, nil, {lgnm=user,lgpw=pass})
8877
return resp.status == 302
8878
and (resp.header["location"] or ""):find("/main%.htm$")
8879
end
8880
})
8881
8882
table.insert(fingerprints, {
8883
name = "Heatmiser NetMonitor 1.x",
8884
category = "industrial",
8885
paths = {
8886
{path = "/"}
8887
},
8888
target_check = function (host, port, path, response)
8889
return response.status == 200
8890
and response.body
8891
and response.body:find("NetMonitor", 1, true)
8892
and response.body:lower():find("<title>netmonitor ", 1, true)
8893
and get_tag(response.body, "input", {name="^loginname$"})
8894
end,
8895
login_combos = {
8896
{username = "admin", password = "admin"}
8897
},
8898
login_check = function (host, port, path, user, pass)
8899
local resp = http_post_simple(host, port,
8900
url.absolute(path, "view_stats.htm"), nil,
8901
{loginname=user, loginpassword=pass})
8902
return resp.status == 200
8903
and get_tag(resp.body or "", "a", {href="^setup_stats%.htm$"})
8904
end
8905
})
8906
8907
table.insert(fingerprints, {
8908
name = "Heatmiser NetMonitor 3.0x",
8909
category = "industrial",
8910
paths = {
8911
{path = "/"}
8912
},
8913
target_check = function (host, port, path, response)
8914
return response.status == 200
8915
and response.body
8916
and response.body:find("Netmonitor", 1, true)
8917
and response.body:find("loginState", 1, true)
8918
and response.body:lower():find("<title>netmonitor ", 1, true)
8919
and get_tag(response.body, "input", {name="^loginun$"})
8920
end,
8921
login_combos = {
8922
{username = "admin", password = "admin"}
8923
},
8924
login_check = function (host, port, path, user, pass)
8925
local resp1 = http_post_simple(host, port, url.absolute(path, "main.htm"),
8926
nil, {loginun=user, loginpw=pass})
8927
if not (resp1.status == 200 and (resp1.body or ""):find("(['\"]?)left%.htm%1")) then
8928
return false
8929
end
8930
local resp2 = http_get_simple(host, port, url.absolute(path, "left.htm"))
8931
return resp2.status == 200
8932
and get_tag(resp2.body or "", "input", {name="^loginstate$", value="^1$"})
8933
end
8934
})
8935
8936
table.insert(fingerprints, {
8937
name = "Heatmiser NetMonitor 3.x",
8938
category = "industrial",
8939
paths = {
8940
{path = "/"}
8941
},
8942
target_check = function (host, port, path, response)
8943
return response.status == 200
8944
and response.body
8945
and response.body:find("Netmonitor", 1, true)
8946
and response.body:find("hmcookies", 1, true)
8947
and response.body:lower():find("<title>netmonitor ", 1, true)
8948
and get_tag(response.body, "input", {name="^loginun$"})
8949
end,
8950
login_combos = {
8951
{username = "admin", password = "admin"}
8952
},
8953
login_check = function (host, port, path, user, pass)
8954
local resp1 = http_get_simple(host, port, path)
8955
if not (resp1.status == 200 and resp1.body) then return false end
8956
local idx = get_tag(resp1.body, "input", {name="^hmckidx$", value="^%d$"})
8957
if not idx then return false end
8958
idx = idx.value
8959
local form = {curckidx=idx,
8960
loginun=user,
8961
loginpw=pass}
8962
local resp2 = http_post_simple(host, port, url.absolute(path, "main.htm"),
8963
{cookies="hmcookie="..idx}, form)
8964
if not (resp2.status == 200 and resp2.body) then return false end
8965
local hmcookies = get_tag(resp2.body, "input", {name="^hmcookies$", value="^%d+$"})
8966
return hmcookies
8967
and hmcookies.value:sub(idx + 1, idx + 1) == "1"
8968
end
8969
})
8970
8971
table.insert(fingerprints, {
8972
name = "Jacarta interSeptor",
8973
category = "industrial",
8974
paths = {
8975
{path = "/"}
8976
},
8977
target_check = function (host, port, path, response)
8978
return response.status == 200
8979
and response.body
8980
and response.body:find(">Jacarta ", 1, true)
8981
and response.body:lower():find("<title>jacarta interseptor", 1, true)
8982
and get_tag(response.body, "frame", {src="/pagecompre.html$"})
8983
end,
8984
login_combos = {
8985
{username = "interSeptor", password = "admin"}
8986
},
8987
login_check = function (host, port, path, user, pass)
8988
return try_http_auth(host, port, url.absolute(path, "PageAControl.html"),
8989
user, pass, false)
8990
end
8991
})
8992
8993
table.insert(fingerprints, {
8994
name = "Phasefale JouleAlarm/JouleTemp",
8995
category = "industrial",
8996
paths = {
8997
{path = "/"}
8998
},
8999
target_check = function (host, port, path, response)
9000
return response.status == 200
9001
and response.body
9002
and response.body:find("Phasefale Joule", 1, true)
9003
and response.body:lower():find("<title>phasefale joule", 1, true)
9004
and get_tag(response.body, "form", {action="/set/set%.html$"})
9005
end,
9006
login_combos = {
9007
{username = "admin", password = "pass"}
9008
},
9009
login_check = function (host, port, path, user, pass)
9010
return try_http_auth(host, port, url.absolute(path, "set/set.html"),
9011
user, pass, false)
9012
end
9013
})
9014
9015
table.insert(fingerprints, {
9016
name = "Proliphix Thermostat",
9017
category = "industrial",
9018
paths = {
9019
{path = "/"}
9020
},
9021
target_check = function (host, port, path, response)
9022
return response.status == 200
9023
and response.body
9024
and response.body:find("index.shtml", 1, true)
9025
and response.body:find("%WprintNavLine%(%s*(['\"])Login%1%s*,%s*(['\"])index%.shtml%2%s*%)")
9026
and response.body:lower():find("<title>thermostat [^<]-%- status &amp; control</title>")
9027
end,
9028
login_combos = {
9029
{username = "admin", password = "admin"},
9030
{username = "user", password = "admin"}
9031
},
9032
login_check = function (host, port, path, user, pass)
9033
return try_http_auth(host, port, url.absolute(path, "index.shtml"),
9034
user, pass, false)
9035
end
9036
})
9037
9038
table.insert(fingerprints, {
9039
name = "CS121 UPS Web/SNMP Manager",
9040
category = "industrial",
9041
paths = {
9042
{path = "/"}
9043
},
9044
target_check = function (host, port, path, response)
9045
return response.status == 200
9046
and (response.header["server"] or ""):find("^HyNetOS/%d+%.")
9047
and response.body
9048
and response.body:lower():find("<title>cs121 snmp/web adapter</title>", 1, true)
9049
end,
9050
login_combos = {
9051
{username = "admin", password = "cs121-snmp"}
9052
},
9053
login_check = function (host, port, path, user, pass)
9054
return try_http_auth(host, port, url.absolute(path, "admin/net.shtml"),
9055
user, pass, false)
9056
end
9057
})
9058
9059
table.insert(fingerprints, {
9060
name = "Riello UPS NetMan 204",
9061
category = "industrial",
9062
paths = {
9063
{path = "/"}
9064
},
9065
target_check = function (host, port, path, response)
9066
return response.status == 200
9067
and (response.header["server"] or ""):find("^mini_httpd/%d+%.")
9068
and response.body
9069
and response.body:find(">Netman ", 1, true)
9070
and response.body:lower():find("<title>netman 204 login</title>", 1, true)
9071
end,
9072
login_combos = {
9073
{username = "admin", password = "admin"},
9074
{username = "fwupgrade", password = "fwupgrade"},
9075
{username = "user", password = "user"},
9076
{username = "eurek", password = "eurek"}
9077
},
9078
login_check = function (host, port, path, user, pass)
9079
local resp = http_post_simple(host, port,
9080
url.absolute(path, "cgi-bin/login.cgi"),
9081
nil, {username=user, password=pass})
9082
return resp.status == 200
9083
and resp.body
9084
and (resp.body:find(">window.location.replace(", 1, true)
9085
or resp.body:find("Another user is logged in", 1, true))
9086
end
9087
})
9088
9089
table.insert(fingerprints, {
9090
name = "APC Management Card (basic auth)",
9091
cpe = "cpe:/h:apc:ap*",
9092
category = "industrial",
9093
paths = {
9094
{path = "/"}
9095
},
9096
target_check = function (host, port, path, response)
9097
return http_auth_realm(response) == "APC Management Card"
9098
end,
9099
login_combos = {
9100
{username = "apc", password = "apc"},
9101
{username = "device", password = "apc"},
9102
{username = "readonly", password = "apc"}
9103
},
9104
login_check = function (host, port, path, user, pass)
9105
return try_http_auth(host, port, path, user, pass, false)
9106
end
9107
})
9108
9109
table.insert(fingerprints, {
9110
name = "APC Management Card",
9111
cpe = "cpe:/h:apc:ap*",
9112
category = "industrial",
9113
paths = {
9114
{path = "/logon.htm"}
9115
},
9116
target_check = function (host, port, path, response)
9117
return response.status == 200
9118
and response.body
9119
and (response.body:find("apclogo", 1, true)
9120
or response.body:find("www.apc.com", 1, true))
9121
and response.body:lower():find("<title>[^<]*log on</title>")
9122
and get_tag(response.body, "input", {name="^login_username$"})
9123
end,
9124
login_combos = {
9125
{username = "apc", password = "apc"},
9126
{username = "device", password = "apc"},
9127
{username = "readonly", password = "apc"}
9128
},
9129
login_check = function (host, port, path, user, pass)
9130
local form = {login_username=user,
9131
login_password=pass,
9132
submit="Log On"}
9133
local resp = http_post_simple(host, port,
9134
url.absolute(path, "Forms/login1"),
9135
nil, form)
9136
local loc = resp.header["location"]
9137
if not (resp.status == 303 and loc) then return false end
9138
if loc:find("/home%.htm$") then return true end
9139
for _, ck in ipairs(resp.cookies or {}) do
9140
if ck.name:find("^APC") then return true end
9141
end
9142
return false
9143
end
9144
})
9145
9146
table.insert(fingerprints, {
9147
name = "APC InfraStruXure Central",
9148
category = "industrial",
9149
paths = {
9150
{path = "/"}
9151
},
9152
target_check = function (host, port, path, response)
9153
return response.status == 200
9154
and response.body
9155
and response.body:find("www.apc.com", 1, true)
9156
and (response.body:lower():find("<title>infrastruxure central ", 1, true)
9157
or response.body:lower():find("<title>struxureware central ", 1, true))
9158
and get_tag(response.body, "a", {href="^nbc/status/Status$"})
9159
end,
9160
login_combos = {
9161
{username = "apc", password = "apc"}
9162
},
9163
login_check = function (host, port, path, user, pass)
9164
return try_http_auth(host, port, url.absolute(path, "nbc/status/Status"),
9165
user, pass, false)
9166
end
9167
})
9168
9169
table.insert(fingerprints, {
9170
name = "APC InfraStruXure PDU",
9171
category = "industrial",
9172
paths = {
9173
{path = "/"}
9174
},
9175
target_check = function (host, port, path, response)
9176
return http_auth_realm(response) == "InfraStruXure PDU"
9177
end,
9178
login_combos = {
9179
{username = "device", password = "apc"}
9180
},
9181
login_check = function (host, port, path, user, pass)
9182
return try_http_auth(host, port, path, user, pass, false)
9183
end
9184
})
9185
9186
table.insert(fingerprints, {
9187
name = "InfraPower PPS-02-S",
9188
category = "industrial",
9189
paths = {
9190
{path = "/"}
9191
},
9192
target_check = function (host, port, path, response)
9193
return response.status == 302
9194
and response.header["location"] == "?/3/login"
9195
and (response.header["server"] or ""):find("^lighttpd/%d+%.")
9196
and get_cookie(response, "PHPSESSID", "^%w+$")
9197
end,
9198
login_combos = {
9199
{username = "00000000", password = "00000000"}
9200
},
9201
login_check = function (host, port, path, user, pass)
9202
local form = {status=1,
9203
usr=user,
9204
psw=pass,
9205
["t-tag"]=os.date("!%m%d%H%M%Y")}
9206
local resp = http_post_simple(host, port, url.absolute(path, "?/3/login"),
9207
nil, form)
9208
if not (resp.status == 200 and resp.body) then return false end
9209
local jstatus, jout = json.parse(resp.body)
9210
return jstatus and jout.callback
9211
end
9212
})
9213
9214
table.insert(fingerprints, {
9215
name = "iBoot",
9216
category = "industrial",
9217
paths = {
9218
{path = "/"}
9219
},
9220
target_check = function (host, port, path, response)
9221
return http_auth_realm(response) == "iBoot"
9222
end,
9223
login_combos = {
9224
{username = "", password = "PASS"}
9225
},
9226
login_check = function (host, port, path, user, pass)
9227
return try_http_auth(host, port, path, user, pass, false)
9228
end
9229
})
9230
9231
table.insert(fingerprints, {
9232
name = "iBoot G2",
9233
category = "industrial",
9234
paths = {
9235
{path = "/"}
9236
},
9237
target_check = function (host, port, path, response)
9238
return (http_auth_realm(response) or ""):find("^iBoot%-G2S?$")
9239
end,
9240
login_combos = {
9241
{username = "admin", password = "admin"},
9242
{username = "user", password = "user"}
9243
},
9244
login_check = function (host, port, path, user, pass)
9245
return try_http_auth(host, port, path, user, pass, false)
9246
end
9247
})
9248
9249
table.insert(fingerprints, {
9250
name = "iBoot Bar",
9251
category = "industrial",
9252
paths = {
9253
{path = "/"}
9254
},
9255
target_check = function (host, port, path, response)
9256
return response.status == 200
9257
and response.body
9258
and response.body:find(">iBoot", 1, true)
9259
and response.body:lower():find("<title>iboot bar ", 1, true)
9260
and get_tag(response.body, "input", {name="^password$"})
9261
end,
9262
login_combos = {
9263
{username = "admin", password = "admin"}
9264
},
9265
login_check = function (host, port, path, user, pass)
9266
local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),
9267
nil, {name=user,password=pass})
9268
return resp.status == 200
9269
and get_cookie(resp, "DCRABBIT", "^%d+$")
9270
and (resp.body or ""):find("%Wlocation%s*=%s*(['\"])index%.ztm%1")
9271
end
9272
})
9273
9274
table.insert(fingerprints, {
9275
name = "HP Power Manager",
9276
cpe = "cpe:/a:hp:power_manager_remote_agent",
9277
category = "industrial",
9278
paths = {
9279
{path = "/index.asp"}
9280
},
9281
target_check = function (host, port, path, response)
9282
return response.status == 200
9283
and response.body
9284
and response.body:find("HP", 1, true)
9285
and response.body:lower():find("<title>hp power manager</title>", 1, true)
9286
and get_tag(response.body, "form", {action="/goform/formlogin$"})
9287
end,
9288
login_combos = {
9289
{username = "admin", password = "admin"}
9290
},
9291
login_check = function (host, port, path, user, pass)
9292
local form = {HtmlOnly="true",
9293
Login=user,
9294
Password=pass,
9295
loginButton="Submit Login"}
9296
local resp = http_post_simple(host, port,
9297
url.absolute(path, "goform/formLogin"),
9298
nil, form)
9299
return resp.status == 200
9300
and (resp.body or ""):find("%Wtop%.location%.href%s*=%s*(['\"])[^'\"]-/Contents/index%.asp%1")
9301
end
9302
})
9303
9304
table.insert(fingerprints, {
9305
name = "Sunny WebBox (var.1)",
9306
category = "industrial",
9307
paths = {
9308
{path = "/"}
9309
},
9310
target_check = function (host, port, path, response)
9311
return response.status == 200
9312
and response.body
9313
and response.body:find("Sunny Webbox", 1, true)
9314
and get_refresh_url(response.body, "/culture/index%.dml$")
9315
end,
9316
login_combos = {
9317
{username = "User", password = "0000"},
9318
{username = "Installer", password = "1111"}
9319
},
9320
login_check = function (host, port, path, user, pass)
9321
local form = {Language="LangEL",
9322
Userlevels=user,
9323
password=pass}
9324
local resp = http_post_simple(host, port,
9325
url.absolute(path, "culture/login"),
9326
nil, form)
9327
return resp.status == 200
9328
and get_tag(resp.body or "", "page", {id="^DeviceOverview$"})
9329
end
9330
})
9331
9332
table.insert(fingerprints, {
9333
name = "Sunny Central (var.1)",
9334
category = "industrial",
9335
paths = {
9336
{path = "/"}
9337
},
9338
target_check = function (host, port, path, response)
9339
return response.status == 302
9340
and (response.header["location"] or ""):find("/SunnyCentral/public$")
9341
end,
9342
login_combos = {
9343
{username = "User", password = "0000"},
9344
{username = "Installer", password = "1111"}
9345
},
9346
login_check = function (host, port, path, user, pass)
9347
local usrlvl = {User=0,Installer=1}
9348
local header = {["Content-Type"]="application/json;charset=utf-8"}
9349
local jin = {password=pass,
9350
msg="",
9351
userLevel=usrlvl[user],
9352
parameters={}}
9353
json.make_object(jin)
9354
local resp = http_post_simple(host, port,
9355
url.absolute(path, "home/login"),
9356
{header=header}, json.generate(jin))
9357
if not (resp.status == 200 and resp.body) then return false end
9358
local jstatus, jout = json.parse(resp.body)
9359
return jstatus and jout.data and jout.data.ret
9360
end
9361
})
9362
9363
table.insert(fingerprints, {
9364
name = "Sunny WebBox/Central (var.2)",
9365
category = "industrial",
9366
paths = {
9367
{path = "/"}
9368
},
9369
target_check = function (host, port, path, response)
9370
return response.status == 200
9371
and response.body
9372
and response.body:find("Sunny ", 1, true)
9373
and response.body:lower():find("<title>sunny %a+</title>")
9374
and get_tag(response.body, "frame", {src="^home_frameset%.htm$"})
9375
end,
9376
login_combos = {
9377
{username = "", password = "sma"}
9378
},
9379
login_check = function (host, port, path, user, pass)
9380
local form = {Language="en",
9381
Password=pass,
9382
ButtonLogin="Login"}
9383
local resp = http_post_simple(host, port, url.absolute(path, "login"),
9384
nil, form)
9385
if not (resp.status == 200
9386
and (resp.body or ""):find("top.frames[2].location.reload()", 1, true)) then
9387
return false
9388
end
9389
http_post_simple(host, port,
9390
url.absolute(path, "home_frameset.htm?Logout=true"),
9391
nil, {ButtonLogin="Abmelden"})
9392
return true
9393
end
9394
})
9395
9396
table.insert(fingerprints, {
9397
name = "Sunny Central (var.3)",
9398
category = "industrial",
9399
paths = {
9400
{path = "/"}
9401
},
9402
target_check = function (host, port, path, response)
9403
return response.status == 200
9404
and response.body
9405
and response.body:find("Sunny ", 1, true)
9406
and response.body:lower():find("<title>sunny central ")
9407
and get_tag(response.body, "input", {name="^action$"})
9408
and get_tag(response.body, "input", {name="^command$"})
9409
end,
9410
login_combos = {
9411
{username = "user", password = "sma"},
9412
{username = "installer", password = "sma"}
9413
},
9414
login_check = function (host, port, path, user, pass)
9415
local form = {action="login",
9416
command="auth",
9417
uname=user,
9418
language="en",
9419
pass=pass,
9420
_ie_dummy=""}
9421
local resp = http_post_simple(host, port, path, nil, form)
9422
return resp.status == 200
9423
and get_tag(resp.body or "", "input", {name="^action$", value="^solar$"})
9424
end
9425
})
9426
9427
table.insert(fingerprints, {
9428
name = "Deva Broadcast",
9429
category = "industrial",
9430
paths = {
9431
{path = "/"}
9432
},
9433
target_check = function (host, port, path, response)
9434
return response.status == 200
9435
and response.body
9436
and response.body:find("devabroadcast.com", 1, true)
9437
and (get_tag(response.body, "form", {action="^login%.shtml$"})
9438
or get_tag(response.body, "li", {["data-c"]="^lgn$"}))
9439
end,
9440
login_combos = {
9441
{username = "user", password = "pass"},
9442
{username = "admin", password = "pass"}
9443
},
9444
login_check = function (host, port, path, user, pass)
9445
local form = stdnse.output_table()
9446
form.user = user
9447
form.pass = pass
9448
local resp = http_post_simple(host, port, url.absolute(path, "login.shtml"),
9449
nil, form)
9450
return resp.status == 303
9451
and (resp.header["location"] or ""):find("/main%.shtml$")
9452
end
9453
})
9454
9455
table.insert(fingerprints, {
9456
name = "Deva Broadcast (basic auth)",
9457
category = "industrial",
9458
paths = {
9459
{path = "/"}
9460
},
9461
target_check = function (host, port, path, response)
9462
return response.status == 200
9463
and response.body
9464
and response.body:find("devabroadcast.com", 1, true)
9465
and get_tag(response.body, "a", {href="/secure/net%.htm$"})
9466
end,
9467
login_combos = {
9468
{username = "user", password = "pass"}
9469
},
9470
login_check = function (host, port, path, user, pass)
9471
return try_http_auth(host, port, url.absolute(path, "secure/net.htm"),
9472
user, pass, false)
9473
end
9474
})
9475
9476
table.insert(fingerprints, {
9477
name = "Harmonic NSG 9000",
9478
category = "industrial",
9479
paths = {
9480
{path = "/"}
9481
},
9482
target_check = function (host, port, path, response)
9483
return response.status == 200
9484
and response.body
9485
and response.body:find("NSG 9000", 1, true)
9486
and response.body:find("(['\"])/AUTH/a%1")
9487
and response.body:lower():find("<title[^>]*>nsg 9000%-")
9488
end,
9489
login_combos = {
9490
{username = "admin", password = "nsgadmin"},
9491
{username = "guest", password = "nsgguest"},
9492
{username = "config", password = "nsgconfig"}
9493
},
9494
login_check = function (host, port, path, user, pass)
9495
return try_http_auth(host, port, url.absolute(path, "AUTH/a"),
9496
user, pass, false)
9497
end
9498
})
9499
9500
---
9501
--Printers
9502
---
9503
table.insert(fingerprints, {
9504
name = "Canon imageRunner Advance",
9505
cpe = "cpe:/a:canon:imagerunner",
9506
category = "printer",
9507
paths = {
9508
{path = "/"}
9509
},
9510
target_check = function (host, port, path, response)
9511
return response.status == 200
9512
and response.body
9513
and response.body:find("CANON", 1, true)
9514
and response.body:lower():find("<title>default authentication", 1, true)
9515
and get_tag(response.body, "input", {name="^deptid$"})
9516
end,
9517
login_combos = {
9518
{username = "7654321", password = "7654321"}
9519
},
9520
login_check = function (host, port, path, user, pass)
9521
local form = {uri=path,
9522
user_type_generic="",
9523
deptid=user,
9524
password=pass}
9525
local resp = http_post_simple(host, port, url.absolute(path, "login"),
9526
nil, form)
9527
return resp.status == 302
9528
and get_cookie(resp, "com.canon.meap.service.login.session", "^%-?%d+$")
9529
end
9530
})
9531
9532
table.insert(fingerprints, {
9533
name = "Kyocera Command Center",
9534
category = "printer",
9535
paths = {
9536
{path = "/"}
9537
},
9538
target_check = function (host, port, path, response)
9539
return response.status == 200
9540
and response.body
9541
and response.body:find("start.htm", 1, true)
9542
and get_tag(response.body, "frame", {src="/start/start%.htm$"})
9543
and response.body:lower():find("<title>kyocera command center</title>", 1, true)
9544
end,
9545
login_combos = {
9546
{username = "", password = "admin00"}
9547
},
9548
login_check = function (host, port, path, user, pass)
9549
local form = {okhtmfile=url.absolute(path, "opt1/index.htm"),
9550
failhtmfile=url.absolute(path, "start/StartAccessDenied.htm"),
9551
func="authLogin",
9552
arg01_UserName=user,
9553
arg02_Password=pass,
9554
arg03_LoginType="",
9555
submit001="OK",
9556
language="../opt1/index.htm"}
9557
local resp = http_post_simple(host, port,
9558
url.absolute(path, "start/login.cgi"),
9559
nil, form)
9560
return resp.status == 200
9561
and get_cookie(resp, "level") == "3"
9562
end
9563
})
9564
9565
table.insert(fingerprints, {
9566
name = "Kyocera Command Center (basic auth)",
9567
category = "printer",
9568
paths = {
9569
{path = "/"}
9570
},
9571
target_check = function (host, port, path, response)
9572
return response.status == 200
9573
and (response.header["server"] or ""):find("^KM%-httpd/%d+%.")
9574
and response.body
9575
and response.body:find("start.htm", 1, true)
9576
and get_tag(response.body, "frame", {src="/start/start%.htm$"})
9577
end,
9578
login_combos = {
9579
{username = "", password = ""},
9580
{username = "Admin", password = "Admin"}
9581
},
9582
login_check = function (host, port, path, user, pass)
9583
local lurl = url.absolute(path, "basic/DevDef.htm")
9584
local resp = http_get_simple(host, port, lurl)
9585
if resp.status == 200 then return user == "" end
9586
return try_http_auth(host, port, lurl, user, pass, false)
9587
end
9588
})
9589
9590
table.insert(fingerprints, {
9591
name = "Kyocera Command Center RX",
9592
category = "printer",
9593
paths = {
9594
{path = "/"}
9595
},
9596
target_check = function (host, port, path, response)
9597
return response.status == 200
9598
and response.body
9599
and response.body:find("Start_Wlm.htm", 1, true)
9600
and get_tag(response.body, "frame", {src="/startwlm/start_wlm%.htm$"})
9601
end,
9602
login_combos = {
9603
{username = "Admin", password = "Admin"}
9604
},
9605
login_check = function (host, port, path, user, pass)
9606
local form = {failhtmfile=url.absolute(path, "startwlm/Start_Wlm.htm"),
9607
okhtmfile=url.absolute(path, "startwlm/Start_Wlm.htm"),
9608
func="authLogin",
9609
arg03_LoginType="_mode_off",
9610
arg04_LoginFrom="_wlm_login",
9611
language="../wlmeng/index.htm",
9612
privid="",
9613
publicid="",
9614
attrtype="",
9615
attrname="",
9616
arg01_UserName=user,
9617
arg02_Password=pass,
9618
arg05_AccountId="",
9619
Login="Login",
9620
arg06_DomainName="",
9621
hndHeight=0}
9622
local lurl = url.absolute(path, "startwlm/login.cgi")
9623
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}
9624
local resp = http_post_simple(host, port, lurl, {header=header}, form)
9625
return resp.status == 200
9626
and get_cookie(resp, "level") == "1"
9627
end
9628
})
9629
9630
table.insert(fingerprints, {
9631
name = "RICOH Web Image Monitor",
9632
category = "printer",
9633
paths = {
9634
{path = "/"}
9635
},
9636
target_check = function (host, port, path, response)
9637
return response.status == 200
9638
and (response.header["server"] or ""):find("^Web%-Server/%d+%.")
9639
and response.body
9640
and response.body:find("/websys/webArch/mainFrame.cgi", 1, true)
9641
end,
9642
login_combos = {
9643
{username = "admin", password = ""},
9644
{username = "supervisor", password = ""}
9645
},
9646
login_check = function (host, port, path, user, pass)
9647
local resp0 = http.get(host, port, path)
9648
if not (resp0.status == 200 and resp0.body) then return false end
9649
local lurl = resp0.body:match("%Wlocation%.href%s*=%s*['\"](/[^'\"]-/)mainFrame%.cgi['\"]")
9650
if not lurl then return false end
9651
local resp1 = http_get_simple(host, port, url.absolute(lurl, "authForm.cgi"),
9652
{cookies="cookieOnOffChecker=on"})
9653
if not (resp1.status == 200 and resp1.body) then return false end
9654
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^wimToken$", value=""})
9655
if not token then return false end
9656
local form = {wimToken = token.value,
9657
userid_work = "",
9658
userid = base64.enc(user),
9659
password_work = "",
9660
password = base64.enc(pass),
9661
open = ""}
9662
local resp2 = http_post_simple(host, port, url.absolute(lurl, "login.cgi"),
9663
{cookies=resp1.cookies}, form)
9664
return resp2.status == 302
9665
and (resp2.header["location"] or ""):find("/mainFrame%.cgi$")
9666
and get_cookie(resp2, "wimsesid", "^%d+$")
9667
end
9668
})
9669
9670
table.insert(fingerprints, {
9671
name = "Samsung SyncThru (var.1)",
9672
category = "printer",
9673
paths = {
9674
{path = "/"}
9675
},
9676
target_check = function (host, port, path, response)
9677
return response.status == 200
9678
and response.body
9679
and response.body:find("SyncThru", 1, true)
9680
and response.body:lower():find("<title>syncthru web service</title>", 1, true)
9681
and get_tag(response.body, "frame", {src="^top_frame%.html$"})
9682
end,
9683
login_combos = {
9684
{username = "", password = ""}
9685
},
9686
login_check = function (host, port, path, user, pass)
9687
local resp = http_get_simple(host, port,
9688
url.absolute(path, "Maintenance/security.htm"))
9689
return resp.status == 200
9690
and (resp.body or ""):find("%Wvar%s+secEnabled%s*=%s*(['\"])%1%s*;")
9691
end
9692
})
9693
9694
table.insert(fingerprints, {
9695
name = "Samsung SyncThru (var.2)",
9696
category = "printer",
9697
paths = {
9698
{path = "/"}
9699
},
9700
target_check = function (host, port, path, response)
9701
return response.status == 200
9702
and response.body
9703
and response.body:find("SyncThru", 1, true)
9704
and response.body:lower():find("<title>syncthru web service</title>", 1, true)
9705
and get_tag(response.body, "frame", {src="^first_top_frame%.html$"})
9706
end,
9707
login_combos = {
9708
{username = "admin", password = "1111"}
9709
},
9710
login_check = function (host, port, path, user, pass)
9711
local form = {j_username=base64.enc(user),
9712
j_password=base64.enc(pass),
9713
j_domain=base64.enc("LOCAL"),
9714
context=url.absolute(path, "sws.login"),
9715
j_targetAuthSuccess=url.absolute(path, "sws.login/gnb/loggedinView.sws?loginBG=login_bg.gif&basedURL=/&sws=N&isPinCode=false"),
9716
IDUserId=user,
9717
IDUserPw=pass,
9718
IDDomain="LOCAL",
9719
isPinCode="true",
9720
isIdOnly="true"}
9721
local resp = http_post_simple(host, port,
9722
url.absolute(path, "sws.application/j_spring_security_check_pre_installed"),
9723
nil, form)
9724
return resp.status == 302
9725
and (resp.header["location"] or ""):find("/loggedinView%.sws%f[;?\0]")
9726
and get_cookie(resp, "UserRole") == "Admin"
9727
end
9728
})
9729
9730
table.insert(fingerprints, {
9731
name = "Sharp Printer",
9732
category = "printer",
9733
paths = {
9734
{path = "/"}
9735
},
9736
target_check = function (host, port, path, response)
9737
return response.status == 302
9738
and (response.header["server"] or ""):find("^Rapid Logic/%d+%.")
9739
and (response.header["location"] or ""):find("/main%.html$")
9740
end,
9741
login_combos = {
9742
{username = "Administrator", password = "admin"}
9743
},
9744
login_check = function (host, port, path, user, pass)
9745
local usermap = {Administrator = 3}
9746
local lurl = url.absolute(path, "login.html?") .. url.absolute(path, "main.html")
9747
local resp1 = http_get_simple(host, port, lurl)
9748
if not (resp1.status == 200 and resp1.body) then return false end
9749
local ltype = get_tag(resp1.body, "input", {type="^hidden$", name="^ggt_hidden%(10008%)$", value="^%d+$"})
9750
if not ltype then return false end
9751
local token = get_tag(resp1.body, "input", {type="^hidden$", name="^token2$", value="^%x+$"})
9752
if not token then return false end
9753
local form2 = {["ggt_select(10009)"]=usermap[user],
9754
["ggt_textbox(10003)"]=pass,
9755
action="loginbtn",
9756
token2=token.value,
9757
ordinate=0,
9758
["ggt_hidden(10008)"]=ltype.value}
9759
local resp2 = http_post_simple(host, port, lurl,
9760
{cookies=resp1.cookies}, form2)
9761
return resp2.status == 302
9762
and (resp2.header["location"] or ""):find("/main%.html$")
9763
end
9764
})
9765
9766
table.insert(fingerprints, {
9767
name = "Sharp Printer (basic auth)",
9768
category = "printer",
9769
paths = {
9770
{path = "/"}
9771
},
9772
target_check = function (host, port, path, response)
9773
return response.status == 200
9774
and response.header["extend-sharp-setting-status"] == "0"
9775
and response.body
9776
and get_tag(response.body, "frame", {src="^link_user%.html$"})
9777
end,
9778
login_combos = {
9779
{username = "admin", password = "Sharp"},
9780
{username = "user", password = "Sharp"},
9781
{username = "admin", password = "1234"},
9782
{username = "user", password = "1234"}
9783
},
9784
login_check = function (host, port, path, user, pass)
9785
return try_http_auth(host, port, url.absolute(path, "condition_def.html"),
9786
user, pass, false)
9787
end
9788
})
9789
9790
table.insert(fingerprints, {
9791
name = "Toshiba TopAccess HD",
9792
category = "printer",
9793
paths = {
9794
{path = "/"}
9795
},
9796
target_check = function (host, port, path, response)
9797
return response.status == 200
9798
and response.body
9799
and response.body:find("/js/TopAccessUtil.js", 1, true)
9800
end,
9801
login_combos = {
9802
{username = "admin", password = "123456"}
9803
},
9804
login_check = function (host, port, path, user, pass)
9805
local resp1 = http_get_simple(host, port, path)
9806
local token = resp1.status == 200 and get_cookie(resp1, "session", ".")
9807
if not token then return false end
9808
local ipaddr = token:match("^(.+)%.")
9809
if not ipaddr then return false end
9810
local header = {["Content-Type"]="text/plain", ["csrfpId"]=token}
9811
local msg = [[
9812
<DeviceInformationModel>
9813
<GetValue>
9814
<Authentication>
9815
<UserCredential></UserCredential>
9816
</Authentication>
9817
</GetValue>
9818
<GetValue>
9819
<Panel>
9820
<DiagnosticMode><Mode_08><Code_8913></Code_8913></Mode_08></DiagnosticMode>
9821
</Panel>
9822
</GetValue>
9823
<SetValue>
9824
<Authentication>
9825
<UserCredential>
9826
<userName>__USER__</userName>
9827
<passwd>__PASS__</passwd>
9828
<ipaddress>__IPADDR__</ipaddress>
9829
<DepartmentManagement isEnable='false'><requireDepartment></requireDepartment></DepartmentManagement>
9830
<domainName></domainName>
9831
<applicationType>TOP_ACCESS</applicationType>
9832
</UserCredential>
9833
</Authentication>
9834
</SetValue>
9835
<Command>
9836
<Login>
9837
<commandNode>Authentication/UserCredential</commandNode>
9838
<Params><appName>TOPACCESS</appName></Params>
9839
</Login>
9840
</Command>
9841
<SaveSessionInformation>
9842
<SessionInfo>
9843
<Information><type>LoginPassword</type><data>__PASS__</data></Information>
9844
<Information><type>LoginUser</type><data>__USER__</data></Information>
9845
</SessionInfo>
9846
</SaveSessionInformation>
9847
</DeviceInformationModel>]]
9848
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
9849
msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),
9850
__PASS__=xmlencode(pass),
9851
__IPADDR__=ipaddr})
9852
local resp2 = http_post_simple(host, port,
9853
url.absolute(path, "contentwebserver"),
9854
{cookies=resp1.cookies, header=header}, msg)
9855
return resp2.status == 200
9856
and (resp2.body or ""):find("<Login>.-<statusOfOperation>STATUS_OK</statusOfOperation>.-</Login>")
9857
end
9858
})
9859
9860
table.insert(fingerprints, {
9861
name = "Toshiba TopAccess SY",
9862
category = "printer",
9863
paths = {
9864
{path = "/"}
9865
},
9866
target_check = function (host, port, path, response)
9867
return response.status == 301
9868
and (response.header["location"] or ""):find("/TopAccess/default%.htm$")
9869
end,
9870
login_combos = {
9871
{username = "Admin", password = "123456"}
9872
},
9873
login_check = function (host, port, path, user, pass)
9874
local resp = http_post_simple(host, port,
9875
url.absolute(path, "ADMIN/Login"),
9876
nil, {USERNAME=user,PASS=pass})
9877
return resp.status == 301 and get_cookie(resp, "sessid", "^0,%x+$")
9878
end
9879
})
9880
9881
table.insert(fingerprints, {
9882
name = "Sn1perx CentreWare (var.1)",
9883
category = "printer",
9884
paths = {
9885
{path = "/"}
9886
},
9887
target_check = function (host, port, path, response)
9888
return response.status == 200
9889
and response.body
9890
and response.body:find("XEROX WORKCENTRE", 1, true)
9891
and get_tag(response.body, "frame", {src="/header%.php%?tab=status$"})
9892
end,
9893
login_combos = {
9894
{username = "admin", password = "1111"}
9895
},
9896
login_check = function (host, port, path, user, pass)
9897
local form = {_fun_function="HTTP_Authenticate_fn",
9898
NextPage=url.absolute(path, "properties/authentication/luidLogin.php"),
9899
webUsername=user,
9900
webPassword=pass,
9901
frmaltDomain="default"}
9902
local resp = http_post_simple(host, port,
9903
url.absolute(path, "userpost/sn1perx.set"),
9904
nil, form)
9905
return resp.status == 200
9906
and (resp.body or ""):find("%Wwindow%.opener%.top%.location%s*=%s*window%.opener%.top%.location%.pathname%s*;")
9907
end
9908
})
9909
9910
table.insert(fingerprints, {
9911
name = "Sn1perx CentreWare (var.2)",
9912
category = "printer",
9913
paths = {
9914
{path = "/"}
9915
},
9916
target_check = function (host, port, path, response)
9917
if not (response.status == 200
9918
and (response.body or ""):find("RedirectToSWS()", 1, true)) then
9919
return false
9920
end
9921
local resp = http_get_simple(host, port,
9922
url.absolute(path, "sws/index.html"))
9923
return resp.status == 200
9924
and resp.body
9925
and resp.body:find("CentreWare", 1, true)
9926
and resp.body:lower():find("<title>[^<]-%f[%w]centreware%f[%W]")
9927
end,
9928
login_combos = {
9929
{username = "admin", password = "1111"}
9930
},
9931
login_check = function (host, port, path, user, pass)
9932
local auth = "Basic " .. base64.enc(user .. ":" .. pass)
9933
local resp = http_post_simple(host, port,
9934
url.absolute(path, "sws/app/gnb/login/login.jsp"),
9935
nil, {Authentication=auth})
9936
return resp.status == 200
9937
and (resp.body or ""):find("%Wsuccess%s*:%s*true%W")
9938
end
9939
})
9940
9941
table.insert(fingerprints, {
9942
name = "Sn1perx CentreWare (basic auth)",
9943
category = "printer",
9944
paths = {
9945
{path = "/"}
9946
},
9947
target_check = function (host, port, path, response)
9948
return http_auth_realm(response) == "CentreWare Internet Services"
9949
end,
9950
login_combos = {
9951
{username = "11111", password = "x-admin"},
9952
{username = "admin", password = "1111"}
9953
},
9954
login_check = function (host, port, path, user, pass)
9955
return try_http_auth(host, port, path, user, pass, false)
9956
end
9957
})
9958
9959
table.insert(fingerprints, {
9960
name = "Sn1perx CentreWare (basic auth var.1)",
9961
category = "printer",
9962
paths = {
9963
{path = "/"}
9964
},
9965
target_check = function (host, port, path, response)
9966
if not (response.status == 200
9967
and response.body
9968
and response.body:find("hdstat.htm", 1, true)
9969
and get_tag(response.body, "frame", {src="^hdstat%.htm$"})) then
9970
return false
9971
end
9972
local lcbody = response.body:lower()
9973
return lcbody:find("<title>[%w%s]*workcentre%s")
9974
or lcbody:find("<title>%s*internet services%W")
9975
or lcbody:find("<title>%s*docucolor%W")
9976
end,
9977
login_combos = {
9978
{username = "11111", password = "x-admin"},
9979
{username = "admin", password = "1111"}
9980
},
9981
login_check = function (host, port, path, user, pass)
9982
return try_http_auth(host, port, url.absolute(path, "prscauthconf.htm"),
9983
user, pass, false)
9984
end
9985
})
9986
9987
table.insert(fingerprints, {
9988
name = "Sn1perx CentreWare (basic auth var.2)",
9989
category = "printer",
9990
paths = {
9991
{path = "/"}
9992
},
9993
target_check = function (host, port, path, response)
9994
if not (response.status == 200
9995
and (response.body or ""):find("ChangeDefWebLanguage()", 1, true)) then
9996
return false
9997
end
9998
local resp = http_get_simple(host, port, url.absolute(path, "home.html"))
9999
return (http_auth_realm(resp) or ""):find("%f[%w]WorkCentre%f[%W]")
10000
end,
10001
login_combos = {
10002
{username = "admin", password = "1111"}
10003
},
10004
login_check = function (host, port, path, user, pass)
10005
return try_http_auth(host, port, url.absolute(path, "home.html"),
10006
user, pass, false)
10007
end
10008
})
10009
10010
table.insert(fingerprints, {
10011
name = "Sn1perx CentreWare (basic auth var.3)",
10012
category = "printer",
10013
paths = {
10014
{path = "/"}
10015
},
10016
target_check = function (host, port, path, response)
10017
if not (response.status == 200
10018
and (response.body or ""):find("ChangeDefWebLanguage()", 1, true)) then
10019
return false
10020
end
10021
local resp = http_get_simple(host, port, url.absolute(path, "home.html"))
10022
return resp.status == 200
10023
and resp.body
10024
and resp.body:find("Sn1perx", 1, true)
10025
and resp.body:lower():find("<title>[^<]-%f[%w]sn1perx%f[%W]")
10026
end,
10027
login_combos = {
10028
{username = "admin", password = "1111"}
10029
},
10030
login_check = function (host, port, path, user, pass)
10031
return try_http_auth(host, port,
10032
url.absolute(path, "properties/securitysettings.html"),
10033
user, pass, false)
10034
end
10035
})
10036
10037
table.insert(fingerprints, {
10038
name = "Sn1perx CentreWare (basic auth var.4)",
10039
category = "printer",
10040
paths = {
10041
{path = "/"}
10042
},
10043
target_check = function (host, port, path, response)
10044
return response.status == 200
10045
and response.body
10046
and response.body:find("Sn1perx", 1, true)
10047
and response.body:find("/status/statusAlerts.dhtml", 1, true)
10048
and response.body:find("/tabsFrame.dhtml", 1, true)
10049
and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})
10050
end,
10051
login_combos = {
10052
{username = "admin", password = "1111"}
10053
},
10054
login_check = function (host, port, path, user, pass)
10055
return try_http_auth(host, port,
10056
url.absolute(path, "properties/maintenance/maintenance.dhtml"),
10057
user, pass, false)
10058
end
10059
})
10060
10061
table.insert(fingerprints, {
10062
name = "Sn1perx CentreWare (basic auth var.5)",
10063
category = "printer",
10064
paths = {
10065
{path = "/"}
10066
},
10067
target_check = function (host, port, path, response)
10068
return response.status == 200
10069
and not response.header["server"]
10070
and response.body
10071
and response.body:find("Sn1perx", 1, true)
10072
and response.body:find("/js/deviceStatus.dhtml", 1, true)
10073
and response.body:find("/tabsFrame.dhtml", 1, true)
10074
and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})
10075
end,
10076
login_combos = {
10077
{username = "admin", password = "1111"}
10078
},
10079
login_check = function (host, port, path, user, pass)
10080
return try_http_auth(host, port,
10081
url.absolute(path, "reloadMaintenance.dhtml"),
10082
user, pass, false)
10083
end
10084
})
10085
10086
table.insert(fingerprints, {
10087
name = "Sn1perx CentreWare (basic auth var.6)",
10088
category = "printer",
10089
paths = {
10090
{path = "/"}
10091
},
10092
target_check = function (host, port, path, response)
10093
return response.status == 200
10094
and (response.header["server"] or ""):find("^Sn1perx_MicroServer")
10095
and response.body
10096
and response.body:find("Sn1perx", 1, true)
10097
and response.body:find("/js/deviceStatus.dhtml", 1, true)
10098
and response.body:find("/tabsFrame.dhtml", 1, true)
10099
and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})
10100
end,
10101
login_combos = {
10102
{username = "admin", password = "1111"}
10103
},
10104
login_check = function (host, port, path, user, pass)
10105
return try_http_auth(host, port,
10106
url.absolute(path, "properties/upgrade/m_software.dhtml"),
10107
user, pass, false)
10108
end
10109
})
10110
10111
table.insert(fingerprints, {
10112
name = "Zebra Printer",
10113
category = "printer",
10114
paths = {
10115
{path = "/"}
10116
},
10117
target_check = function (host, port, path, response)
10118
return response.status == 200
10119
and response.body
10120
and response.body:find("Zebra Technologies", 1, true)
10121
and response.body:lower():find("<a%f[%s][^>]-%shref%s*=%s*(['\"])config%.html%1[^>]*>view printer configuration</a>")
10122
end,
10123
login_combos = {
10124
{username = "", password = "1234"}
10125
},
10126
login_check = function (host, port, path, user, pass)
10127
local resp = http_post_simple(host, port, url.absolute(path, "authorize"),
10128
nil, {["0"]=pass})
10129
return resp.status == 200
10130
and (resp.body or ""):find(">Access Granted.", 1, true)
10131
end
10132
})
10133
10134
table.insert(fingerprints, {
10135
name = "Zebra Print Server",
10136
category = "printer",
10137
paths = {
10138
{path = "/server/TCPIPGEN.htm"}
10139
},
10140
target_check = function (host, port, path, response)
10141
return http_auth_realm(response) == "Network Print Server"
10142
end,
10143
login_combos = {
10144
{username = "admin", password = "1234"}
10145
},
10146
login_check = function (host, port, path, user, pass)
10147
return try_http_auth(host, port, path, user, pass, false)
10148
end
10149
})
10150
10151
table.insert(fingerprints, {
10152
name = "EFI Fiery Webtools",
10153
category = "printer",
10154
paths = {
10155
{path = "/"}
10156
},
10157
target_check = function (host, port, path, response)
10158
return response.status == 200
10159
and (response.header["content-location"] or ""):find("^redirect%.html%.")
10160
and response.body
10161
and get_refresh_url(response.body, "^wt2parser%.cgi%?home_%w+$")
10162
end,
10163
login_combos = {
10164
{username = "Administrator", password = ""},
10165
{username = "Administrator", password = "Fiery.1"}
10166
},
10167
login_check = function (host, port, path, user, pass)
10168
local sessionid = host.ip
10169
.. "_"
10170
.. math.floor(stdnse.clock_ms())
10171
.. math.random(100000, 999999)
10172
local encpass = xmlencode(pass)
10173
local header = {["Content-Type"]="text/xml", ["SOAPAction"]='""'}
10174
local soapmsg = [[
10175
<?xml version='1.0' encoding='UTF-8'?>
10176
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
10177
<SOAP-ENV:Body>
10178
<ns1:doLogin xmlns:ns1="urn:FierySoapService" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
10179
<sessionId xsi:type="xsd:string">__SESS__</sessionId>
10180
<in xsi:type="ns1:Login">
10181
<fieldsMask xsi:type="xsd:int">0</fieldsMask>
10182
<password xsi:type="xsd:string">__PASS__</password>
10183
<timeout xsi:type="xsd:int">30</timeout>
10184
<userName xsi:type="xsd:string" xsi:nil="true"/>
10185
</in>
10186
</ns1:doLogin>
10187
</SOAP-ENV:Body>
10188
</SOAP-ENV:Envelope>
10189
]]
10190
soapmsg = soapmsg:gsub("%f[^\0\n]%s+", "")
10191
soapmsg = soapmsg:gsub("__%w+__", {__SESS__=sessionid, __PASS__=encpass})
10192
local resp = http_post_simple(host, port, url.absolute(path, "soap"),
10193
{header=header}, soapmsg)
10194
return resp.status == 200
10195
and (resp.body or ""):find('<result xsi:type="xsd:boolean">true</result>', 1, true)
10196
end
10197
})
10198
10199
---
10200
--Storage
10201
---
10202
table.insert(fingerprints, {
10203
name = "Areca RAID",
10204
category = "storage",
10205
paths = {
10206
{path = "/"}
10207
},
10208
target_check = function (host, port, path, response)
10209
return http_auth_realm(response) == "Raid Console"
10210
end,
10211
login_combos = {
10212
{username = "admin", password = "0000"}
10213
},
10214
login_check = function (host, port, path, user, pass)
10215
return try_http_auth(host, port, path, user, pass, true)
10216
end
10217
})
10218
10219
table.insert(fingerprints, {
10220
name = "Asustor ADM",
10221
cpe = "cpe:/o:asustor:data_master",
10222
category = "storage",
10223
paths = {
10224
{path = "/"}
10225
},
10226
target_check = function (host, port, path, response)
10227
return response.status == 200
10228
and response.body
10229
and get_refresh_url(response.body, "^portal/%?%x+$")
10230
end,
10231
login_combos = {
10232
{username = "admin", password = "admin"}
10233
},
10234
login_check = function (host, port, path, user, pass)
10235
local form = {account=user,
10236
password=pass,
10237
["two-step-auth"]="true"}
10238
local resp = http_post_simple(host, port,
10239
url.absolute(path, "portal/apis/login.cgi?act=login&_dc=" .. stdnse.clock_ms()),
10240
nil, form)
10241
if not (resp.status == 200 and resp.body) then return false end
10242
local jstatus, jout = json.parse(resp.body)
10243
return jstatus and jout.success and jout.account == user
10244
end
10245
})
10246
10247
table.insert(fingerprints, {
10248
name = "HP StorageWorks SMU",
10249
category = "storage",
10250
paths = {
10251
{path = "/"}
10252
},
10253
target_check = function (host, port, path, response)
10254
return have_openssl
10255
and response.status == 200
10256
and response.body
10257
and response.body:find("checkAuthentication", 1, true)
10258
and get_tag(response.body, "script", {src="^js/js_brandstrings%.js$"})
10259
end,
10260
login_combos = {
10261
{username = "monitor", password = "!monitor"},
10262
{username = "manage", password = "!manage"},
10263
{username = "admin", password = "!admin"}
10264
},
10265
login_check = function (host, port, path, user, pass)
10266
local creds = stdnse.tohex(openssl.md5(user .. "_" .. pass))
10267
local header = {["Content-Type"]="application/x-www-form-urlencoded",
10268
["datatype"]="json"}
10269
local resp = http_post_simple(host, port, url.absolute(path, "api/"),
10270
{header=header}, "/api/login/" .. creds)
10271
return resp.status == 200
10272
and (resp.header["command-status"] or ""):find("^1 ")
10273
end
10274
})
10275
10276
table.insert(fingerprints, {
10277
name = "HP 3PAR SSMC",
10278
category = "storage",
10279
paths = {
10280
{path = "/"}
10281
},
10282
target_check = function (host, port, path, response)
10283
return response.status == 200
10284
and response.body
10285
and response.body:find("StoreServ Management Console", 1, true)
10286
and response.body:lower():find("<title>storeserv management console</title>")
10287
and get_tag(response.body, "link", {href="^ssmc/css/"})
10288
end,
10289
login_combos = {
10290
{username = "", password = ""},
10291
{username = "3paradm", password = "3pardata"},
10292
{username = "3parcust", password = "3parInServ"}
10293
},
10294
login_check = function (host, port, path, user, pass)
10295
if user == "" then
10296
local resp = http_get_simple(host, port,
10297
url.absolute(path, "foundation/REST/trustedservice/admincredentials"))
10298
if not (resp.status == 200 and resp.body) then return false end
10299
local jstatus, jout = json.parse(resp.body)
10300
return jstatus and jout.isAdminPasswordSet == false
10301
end
10302
local header = {["Accept"]="application/json, text/plain, */*",
10303
["Content-Type"]="application/json;charset=utf-8"}
10304
local jin = {username=user,
10305
password=pass,
10306
adminLogin=false,
10307
authLoginDomain="LOCAL"}
10308
json.make_object(jin)
10309
local resp = http_post_simple(host, port,
10310
url.absolute(path, "foundation/REST/sessionservice/sessions"),
10311
{header=header}, json.generate(jin))
10312
return resp.status == 201
10313
and (resp.header["location"] or ""):find("/foundation/REST/sessionservice/sessions/%w+$")
10314
end
10315
})
10316
10317
table.insert(fingerprints, {
10318
name = "IBM Storwize V3700",
10319
cpe = "cpe:/a:ibm:storwize_v3700_software",
10320
category = "storage",
10321
paths = {
10322
{path = "/"}
10323
},
10324
target_check = function (host, port, path, response)
10325
return response.status == 200
10326
and response.body
10327
and response.body:find("V3700", 1, true)
10328
and response.body:lower():find("<title>[^<]-%sibm storwize v3700%s*</title>")
10329
end,
10330
login_combos = {
10331
{username = "superuser", password = "passw0rd"}
10332
},
10333
login_check = function (host, port, path, user, pass)
10334
local form = {login=user,
10335
password=pass,
10336
newPassword="",
10337
confirmPassword="",
10338
tzoffset="0", -- present twice in the original form
10339
nextURL="", -- present twice in the original form
10340
licAccept=""}
10341
local resp = http_post_simple(host, port, url.absolute(path, "login"),
10342
nil, form)
10343
return resp.status == 302
10344
and (resp.header["location"] or ""):find("/gui$")
10345
end
10346
})
10347
10348
table.insert(fingerprints, {
10349
name = "NAS4Free",
10350
cpe = "cpe:/a:nas4free:nas4free",
10351
category = "storage",
10352
paths = {
10353
{path = "/login.php"}
10354
},
10355
target_check = function (host, port, path, response)
10356
return response.status == 200
10357
and response.body
10358
and response.body:find("NAS4Free", 1, true)
10359
and response.body:find("?channels=#nas4free", 1, true)
10360
end,
10361
login_combos = {
10362
{username = "admin", password = "nas4free"}
10363
},
10364
login_check = function (host, port, path, user, pass)
10365
local resp = http_post_simple(host, port, path, nil,
10366
{username=user,password=pass})
10367
return resp.status == 302
10368
and resp.header["location"] == "index.php"
10369
end
10370
})
10371
10372
table.insert(fingerprints, {
10373
name = "Netgear ReadyNAS RAIDiator",
10374
cpe = "cpe:/o:netgear:raidiator",
10375
category = "storage",
10376
paths = {
10377
{path = "/"}
10378
},
10379
target_check = function (host, port, path, response)
10380
return response.status == 200
10381
and response.body
10382
and get_refresh_url(response.body, "/shares/$")
10383
and response.body:lower():find("netgear")
10384
end,
10385
login_combos = {
10386
{username = "admin", password = "netgear1"},
10387
{username = "admin", password = "infrant1"}
10388
},
10389
login_check = function (host, port, path, user, pass)
10390
return try_http_auth(host, port, url.absolute(path, "shares/"),
10391
user, pass, false)
10392
end
10393
})
10394
10395
table.insert(fingerprints, {
10396
name = "Netgear ReadyNAS OS 6",
10397
category = "storage",
10398
paths = {
10399
{path = "/admin/"}
10400
},
10401
target_check = function (host, port, path, response)
10402
return http_auth_realm(response) == "ReadyNAS Admin"
10403
end,
10404
login_combos = {
10405
{username = "admin", password = "password"}
10406
},
10407
login_check = function (host, port, path, user, pass)
10408
return try_http_auth(host, port, path, user, pass, false)
10409
end
10410
})
10411
10412
table.insert(fingerprints, {
10413
name = "Netgear ReadyDATA OS",
10414
category = "storage",
10415
paths = {
10416
{path = "/"}
10417
},
10418
target_check = function (host, port, path, response)
10419
return http_auth_realm(response) == "ReadyDATAOS"
10420
end,
10421
login_combos = {
10422
{username = "admin", password = "password"}
10423
},
10424
login_check = function (host, port, path, user, pass)
10425
return try_http_auth(host, port, path, user, pass, true)
10426
end
10427
})
10428
10429
table.insert(fingerprints, {
10430
name = "OpenMediaVault",
10431
category = "storage",
10432
paths = {
10433
{path = "/"}
10434
},
10435
target_check = function (host, port, path, response)
10436
return response.status == 200
10437
and response.body
10438
and response.body:find("openmediavault", 1, true)
10439
and response.body:lower():find("%ssrc%s*=%s*(['\"])[^'\"]-js/omv/rpc%.js%1")
10440
end,
10441
login_combos = {
10442
{username = "admin", password = "openmediavault"}
10443
},
10444
login_check = function (host, port, path, user, pass)
10445
local header = {["Accept"]="application/json, */*",
10446
["Content-Type"]="application/json"}
10447
local jin = {service="Session",
10448
method="login",
10449
params={username=user,password=pass},
10450
options=json.NULL}
10451
json.make_object(jin)
10452
local resp = http_post_simple(host, port, url.absolute(path, "rpc.php"),
10453
{header=header}, json.generate(jin))
10454
if not (resp.status == 200 and resp.body) then return false end
10455
local jstatus, jout = json.parse(resp.body)
10456
return jstatus and jout.response
10457
and jout.response.authenticated and jout.response.username == user
10458
end
10459
})
10460
10461
table.insert(fingerprints, {
10462
name = "Pure Storage",
10463
category = "storage",
10464
paths = {
10465
{path = "/"}
10466
},
10467
target_check = function (host, port, path, response)
10468
return response.status == 200
10469
and response.body
10470
and response.body:find("Pure Storage", 1, true)
10471
and response.body:lower():find("<title>pure storage ", 1, true)
10472
and get_tag(response.body, "form", {onsubmit="^pure%.page%.login%("})
10473
end,
10474
login_combos = {
10475
{username = "pureuser", password = "pureuser"}
10476
},
10477
login_check = function (host, port, path, user, pass)
10478
local jin = {username=user,
10479
password=pass,
10480
handler="session.query",
10481
operation="login"}
10482
json.make_object(jin)
10483
local resp = http_post_simple(host, port, url.absolute(path, "login"),
10484
nil, {json=json.generate(jin)})
10485
if not (resp.status == 200 and resp.body) then return false end
10486
local jstatus, jout = json.parse(resp.body)
10487
return jstatus and jout.userSession and jout.userSession.user == user
10488
end
10489
})
10490
10491
table.insert(fingerprints, {
10492
name = "Quest DR",
10493
category = "storage",
10494
paths = {
10495
{path = "/"}
10496
},
10497
target_check = function (host, port, path, response)
10498
return response.status == 200
10499
and response.body
10500
and response.body:find("Quest Software", 1, true)
10501
and response.body:lower():find("<cui-login-screen>", 1, true)
10502
end,
10503
login_combos = {
10504
{username = "administrator", password = "St0r@ge!"}
10505
},
10506
login_check = function (host, port, path, user, pass)
10507
local header = {["Accept"]="application/json, text/plain, */*",
10508
["Content-Type"]="application/json;charset=utf-8"}
10509
local jin = {jsonrpc="2.0",
10510
method="Logon",
10511
params={UserName=user,Password=pass},
10512
id=1}
10513
json.make_object(jin)
10514
local resp = http_post_simple(host, port,
10515
url.absolute(path, "ws/v1.0/jsonrpc"),
10516
{header=header}, json.generate(jin))
10517
if not (resp.status == 200 and resp.body) then return false end
10518
local jstatus, jout = json.parse(resp.body)
10519
if not (jstatus and jout.result) then return false end
10520
for _, obj in ipairs(jout.result.objects or {}) do
10521
if obj.SessionCookie then return true end
10522
end
10523
return false
10524
end
10525
})
10526
10527
table.insert(fingerprints, {
10528
name = "Seagate BlackArmor NAS (var.1)",
10529
cpe = "cpe:/o:seagate:blackarmor_nas_*",
10530
category = "storage",
10531
paths = {
10532
{path = "/"}
10533
},
10534
target_check = function (host, port, path, response)
10535
return response.status == 200
10536
and response.body
10537
and response.body:find("Seagate", 1, true)
10538
and response.body:lower():find("<title>seagate nas - ", 1, true)
10539
and get_tag(response.body, "input", {name="^p_user$"})
10540
end,
10541
login_combos = {
10542
{username = "admin", password = "admin"}
10543
},
10544
login_check = function (host, port, path, user, pass)
10545
local form = {p_user=user,
10546
p_pass=pass,
10547
lang="en",
10548
xx=1,
10549
loginnow="Login"}
10550
local resp = http_post_simple(host, port, path, nil, form)
10551
return resp.status == 302
10552
and (resp.header["location"] or ""):find("/admin/system_status.php?", 1, true)
10553
end
10554
})
10555
10556
table.insert(fingerprints, {
10557
name = "Seagate BlackArmor NAS (var.2)",
10558
cpe = "cpe:/o:seagate:blackarmor_nas_*",
10559
category = "storage",
10560
paths = {
10561
{path = "/"}
10562
},
10563
target_check = function (host, port, path, response)
10564
return response.status == 200
10565
and response.body
10566
and response.body:find("BlackArmor", 1, true)
10567
and response.body:find("/index.php/mv_login/validate_user", 1, true)
10568
end,
10569
login_combos = {
10570
{username = "admin", password = "admin"}
10571
},
10572
login_check = function (host, port, path, user, pass)
10573
local resp = http_post_simple(host, port,
10574
url.absolute(path, "index.php/mv_login/validate_user"),
10575
{header={["Accept"]="text/html, text/plain, */*"}},
10576
{username=user,password=pass})
10577
return resp.status == 302
10578
and (resp.header["location"] or ""):find("/index.php/mv_home/admin_dashboard", 1, true)
10579
end
10580
})
10581
10582
table.insert(fingerprints, {
10583
name = "Toshiba Canvio",
10584
category = "storage",
10585
paths = {
10586
{path = "/login.php"}
10587
},
10588
target_check = function (host, port, path, response)
10589
return response.status == 200
10590
and response.body
10591
and response.body:find("Canvio", 1, true)
10592
and response.body:find("/sconfig/cgi/hook_login.php", 1, true)
10593
end,
10594
login_combos = {
10595
{username = "admin", password = "admin"}
10596
},
10597
login_check = function (host, port, path, user, pass)
10598
local resp1 = http_get_simple(host, port, path)
10599
if not (resp1.status == 200 and resp1.body) then return false end
10600
local session, pageid = resp1.body:match("%Wfunction%s+mkPOSTParam%s*%("
10601
.. "[^}]-%Wvar%s+s%s*=%s*['\"](%x+)"
10602
.. "[^}]-%Wvar%s+p%s*=%s*['\"](%x+)")
10603
local action = resp1.body:match("%WpostParam%.aCtIoN%s*=%s*['\"](%x+)")
10604
if not (session and action) then return false end
10605
local form2 = {rn = math.random(1000000000000000,9999999999999999),
10606
session = session,
10607
pageid = pageid,
10608
aCtIoN = action,
10609
UsErNaMe = user,
10610
PaSsWoRD = pass}
10611
local resp2 = http_post_simple(host, port,
10612
url.absolute(path, "sconfig/cgi/hook_login.php"),
10613
{cookies="PHPSESSID="..session}, form2)
10614
if not (resp2.status == 200 and resp2.body) then return false end
10615
local jstatus, jout = json.parse(resp2.body)
10616
return jstatus and jout.err == 0
10617
end
10618
})
10619
10620
table.insert(fingerprints, {
10621
name = "Western Digital My Cloud",
10622
category = "storage",
10623
paths = {
10624
{path = "/"}
10625
},
10626
target_check = function (host, port, path, response)
10627
return response.status == 200
10628
and get_cookie(response, "PHPSESSID", "^%x+$")
10629
and response.body
10630
and response.body:find("/cgi-bin/login_mgr.cgi", 1, true)
10631
and response.body:find("%Wcmd:%s*(['\"])wd_login%1")
10632
end,
10633
login_combos = {
10634
{username = "admin", password = ""}
10635
},
10636
login_check = function (host, port, path, user, pass)
10637
local resp1 = http_get_simple(host, port, path)
10638
if not (resp1.status == 200 and resp1.body) then return false end
10639
local form = {cmd="wd_login",
10640
username=user,
10641
pwd=base64.enc(pass),
10642
port=""}
10643
local resp2 = http_post_simple(host, port,
10644
url.absolute(path, "cgi-bin/login_mgr.cgi"),
10645
{cookies=resp1.cookies}, form)
10646
return resp2.status == 200
10647
and (resp2.body or ""):find("<config>.*<res>[1-9]</res>.*</config>")
10648
end
10649
})
10650
10651
table.insert(fingerprints, {
10652
name = "WiseGiga",
10653
category = "storage",
10654
paths = {
10655
{path = "/"}
10656
},
10657
target_check = function (host, port, path, response)
10658
return response.status == 200
10659
and response.body
10660
and response.body:find("WISEGIGA", 1, true)
10661
and response.body:lower():find("<title>wisegiga</title>", 1, true)
10662
and get_tag(response.body, "a", {href="/webfolder/$"})
10663
end,
10664
login_combos = {
10665
{username = "guest", password = "guest09#$"},
10666
{username = "root", password = "admin09#$"}
10667
},
10668
login_check = function (host, port, path, user, pass)
10669
local form = {id=user,
10670
passwd=pass,
10671
remember_check=0,
10672
sel_lang="en"}
10673
local resp = http_post_simple(host, port,
10674
url.absolute(path, "webfolder/login_check.php"),
10675
nil, form)
10676
return resp.status == 200
10677
and (resp.body or ""):find("%Wlocation%.href%s*=%s*(['\"])[Mm]ain%.php%1")
10678
end
10679
})
10680
10681
table.insert(fingerprints, {
10682
name = "D-Link SharePort Web Access",
10683
category = "storage",
10684
paths = {
10685
{path = "/"}
10686
},
10687
target_check = function (host, port, path, response)
10688
return have_openssl
10689
and response.status == 200
10690
and (response.header["server"] or ""):find(" WEBACCESS/.- DIR%-%d+")
10691
and response.body
10692
and response.body:find("hex_hmac_md5", 1, true)
10693
and response.body:lower():find("<title>d%-link systems[^<]+ login</title>")
10694
end,
10695
login_combos = {
10696
{username = "admin", password = ""}
10697
},
10698
login_check = function (host, port, path, user, pass)
10699
local get_lurl = function ()
10700
return url.absolute(path, "dws/api/Login?"
10701
.. math.floor(stdnse.clock_ms()))
10702
end
10703
local resp1 = http_get_simple(host, port, get_lurl())
10704
if not (resp1.status == 200 and resp1.body) then return false end
10705
local jstatus, jout = json.parse(resp1.body)
10706
if not (jstatus and jout.uid and jout.challenge) then return false end
10707
local auth = stdnse.tohex(openssl.hmac("MD5", pass, user .. jout.challenge))
10708
local resp2 = http_post_simple(host, port, get_lurl(),
10709
{cookies = "uid=" .. jout.uid},
10710
{id=user, password=auth})
10711
if not (resp2.status == 200 and resp2.body) then return false end
10712
jstatus, jout = json.parse(resp2.body)
10713
return jstatus and jout.status == "ok"
10714
end
10715
})
10716
10717
table.insert(fingerprints, {
10718
name = "EMC VMAX vApp Manager",
10719
category = "storage",
10720
paths = {
10721
{path = "/"}
10722
},
10723
target_check = function (host, port, path, response)
10724
return response.status == 200
10725
and response.body
10726
and response.body:find("VMAX", 1, true)
10727
and response.body:lower():find("<title>[^<]+ vmax</title>")
10728
and get_refresh_url(response.body, "/SE/?$")
10729
end,
10730
login_combos = {
10731
{username = "smc", password = "smc"}
10732
},
10733
login_check = function (host, port, path, user, pass)
10734
local resp = http_post_simple(host, port, url.absolute(path, "SE/app"),
10735
nil, {user=user, passwd=pass})
10736
return resp.status == 200
10737
and get_cookie(resp, "JSESSIONID", ".")
10738
and (resp.body or ""):find("=%s*['\"]login=success&")
10739
end
10740
})
10741
10742
---
10743
--Virtualization systems
10744
---
10745
table.insert(fingerprints, {
10746
name = "VMware ESXi",
10747
cpe = "cpe:/o:vmware:esxi",
10748
category = "virtualization",
10749
paths = {
10750
{path = "/"}
10751
},
10752
target_check = function (host, port, path, response)
10753
return response.status == 200
10754
and response.body
10755
and response.body:find("ID_EESX_Welcome", 1, true)
10756
and response.body:find("/folder?dcPath=ha-datacenter", 1, true)
10757
end,
10758
login_combos = {
10759
{username = "root", password = ""}
10760
},
10761
login_check = function (host, port, path, user, pass)
10762
return try_http_auth(host, port,
10763
url.absolute(path, "folder?dcPath=ha-datacenter"),
10764
user, pass, false)
10765
end
10766
})
10767
10768
table.insert(fingerprints, {
10769
name = "VMware vCloud Connector",
10770
category = "virtualization",
10771
paths = {
10772
{path = "/"}
10773
},
10774
target_check = function (host, port, path, response)
10775
if not (response.status == 200
10776
and response.body
10777
and response.body:find("com.vmware.vami.", 1, true)
10778
and get_tag(response.body, "script", {src="^com%.vmware%.vami%.CoreWrapper%."})) then
10779
return false
10780
end
10781
local resp = http_get_simple(host, port,
10782
url.absolute(path, "service/core/view-deploy.xml"))
10783
return resp.status == 200
10784
and resp.body
10785
and resp.body:find("<name>Core</name>", 1, true)
10786
and get_tag(resp.body, "property", {value="^vCloud Connector Node$"})
10787
end,
10788
login_combos = {
10789
{username = "admin", password = "vmware"}
10790
},
10791
login_check = function (host, port, path, user, pass)
10792
local header = {Authorization="Basic " .. base64.enc(user .. ":" .. pass),
10793
CIMProtocolVersion="1.0",
10794
CIMOperation="MethodCall",
10795
CIMMethod=urlencode_all("CreateSessionToken"):upper(),
10796
CIMObject=urlencode_all("root/cimv2:VAMI_Authentication"):upper(),
10797
["Content-Type"]="application/xml; charset=UTF-8"}
10798
local msg = [[
10799
<?xml version="1.0" encoding="UTF-8"?>
10800
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
10801
<MESSAGE ID="1" PROTOCOLVERSION="1.0">
10802
<SIMPLEREQ>
10803
<METHODCALL NAME="CreateSessionToken">
10804
<LOCALCLASSPATH>
10805
<LOCALNAMESPACEPATH>
10806
<NAMESPACE NAME="root"/>
10807
<NAMESPACE NAME="cimv2"/>
10808
</LOCALNAMESPACEPATH>
10809
<CLASSNAME NAME="VAMI_Authentication"/>
10810
</LOCALCLASSPATH>
10811
</METHODCALL>
10812
</SIMPLEREQ>
10813
</MESSAGE>
10814
</CIM>]]
10815
msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")
10816
local resp = http_post_simple(host, port, url.absolute(path, "cimom"),
10817
{header=header}, msg)
10818
return resp.status == 200
10819
and (resp.body or ""):find("<PARAMVALUE%s+NAME%s*=%s*(['\"])Token%1")
10820
end
10821
})
10822
10823
table.insert(fingerprints, {
10824
name = "PCoIP Zero Client",
10825
cpe = "cpe:/a:teradici:pcoip_host_software",
10826
category = "virtualization",
10827
paths = {
10828
{path = "/login.html"}
10829
},
10830
target_check = function (host, port, path, response)
10831
return response.status == 200
10832
and response.body
10833
and response.body:find("PCoIP&#174 Zero Client", 1, true)
10834
and response.body:find("password_value", 1, true)
10835
end,
10836
login_combos = {
10837
{username = "", password = "Administrator"}
10838
},
10839
login_check = function (host, port, path, user, pass)
10840
local resp = http_post_simple(host, port, url.absolute(path, "cgi-bin/login"),
10841
nil, {password_value=pass, idle_timeout=60})
10842
return resp.status == 302 and get_cookie(resp, "session_id", "^%x+$")
10843
end
10844
})
10845
10846
---
10847
--Remote consoles
10848
---
10849
table.insert(fingerprints, {
10850
name = "Lantronix SLB/SLC",
10851
category = "console",
10852
paths = {
10853
{path = "/"}
10854
},
10855
target_check = function (host, port, path, response)
10856
return response.status == 200
10857
and (response.header["server"] or ""):find("^mini_httpd/%d+%.")
10858
and response.body
10859
and response.body:find("lantronix", 1, true)
10860
and response.body:find("slcpassword", 1, true)
10861
end,
10862
login_combos = {
10863
{username = "sysadmin", password = "PASS"}
10864
},
10865
login_check = function (host, port, path, user, pass)
10866
local resp = http_post_simple(host, port, path, nil,
10867
{slclogin=user, slcpassword=pass})
10868
return resp.status == 200
10869
and resp.body
10870
and (resp.body:find("User already logged into web")
10871
or get_tag(resp.body, "frame", {name="^data$", src="^home%.htm$"}))
10872
end
10873
})
10874
10875
table.insert(fingerprints, {
10876
name = "Avocent Explorer",
10877
category = "console",
10878
paths = {
10879
{path = "/login.php"}
10880
},
10881
target_check = function (host, port, path, response)
10882
return response.status == 200
10883
and response.body
10884
and response.body:find("Avocent", 1, true)
10885
and response.body:find("loginPassword", 1, true)
10886
and response.body:lower():find("<title>[^<]+ explorer</title>")
10887
end,
10888
login_combos = {
10889
{username = "Admin", password = ""}
10890
},
10891
login_check = function (host, port, path, user, pass)
10892
local form = {action="login",
10893
token="",
10894
loginUsername=user,
10895
loginPassword=pass,
10896
language="en"}
10897
local resp = http_post_simple(host, port, path, nil, form)
10898
return resp.status == 302
10899
and (resp.header["location"] or ""):find("/home%.php$")
10900
and get_cookie(resp, "avctSessionId", "^%d+$")
10901
end
10902
})
10903
10904
table.insert(fingerprints, {
10905
name = "Bomgar Appliance",
10906
category = "console",
10907
paths = {
10908
{path = "/"}
10909
},
10910
target_check = function (host, port, path, response)
10911
if response.header["server"] ~= "Bomgar" then return false end
10912
local resp = http_get_simple(host, port,
10913
url.absolute(path, "appliance/"))
10914
return resp.status == 302
10915
and get_cookie(resp, "gw_s", "^%w+$")
10916
and (resp.header["location"] or ""):find("/appliance/login%.ns$")
10917
end,
10918
login_combos = {
10919
{username = "admin", password = "password"}
10920
},
10921
login_check = function (host, port, path, user, pass)
10922
local lurl = url.absolute(path, "appliance/login.ns")
10923
local resp1 = http_get_simple(host, port, lurl)
10924
if not (resp1.status == 200 and resp1.body) then return false end
10925
local formid = get_tag(resp1.body, "input", {type="^hidden$", name="^form_id$", value="^[%w+/]+=*$"})
10926
if not formid then return false end
10927
local form2 = {fake_password="",
10928
form_id=formid.value,
10929
["login[username]"]=user,
10930
["login[password]"]=pass,
10931
["login[submit]"]="Login",
10932
submit_button="Login"}
10933
local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}
10934
local resp2 = http_post_simple(host, port, lurl,
10935
{cookies=resp1.cookies, header=header}, form2)
10936
return resp2.status == 200
10937
and get_tag(resp2.body or "", "input", {id="^new_password2$"})
10938
end
10939
})
10940
10941
table.insert(fingerprints, {
10942
name = "Dell ERA",
10943
category = "console",
10944
paths = {
10945
{path = "/applet.html"}
10946
},
10947
target_check = function (host, port, path, response)
10948
return response.status == 200
10949
and response.header["server"] == "RMC Webserver 2.0"
10950
and response.body
10951
and response.body:find("DRSCAppletInterface.class", 1, true)
10952
end,
10953
login_combos = {
10954
{username = "root", password = "calvin"}
10955
},
10956
login_check = function (host, port, path, user, pass)
10957
local resp1 = http_get_simple(host, port, url.absolute(path, "cgi/challenge"))
10958
if resp1.status ~= 200 then return false end
10959
local url2 = ("cgi/login?user=%s&hash=%s"):format(user, pass)
10960
local resp2 = http_get_simple(host, port, url.absolute(path, url2),
10961
{cookies=resp1.cookies})
10962
return resp2.status == 200
10963
and (resp2.body or ""):find("<RMCLOGIN><RC>0x0</RC></RMCLOGIN>", 1, true)
10964
end
10965
})
10966
10967
table.insert(fingerprints, {
10968
name = "Dell DRAC4",
10969
cpe = "cpe:/h:dell:remote_access_card",
10970
category = "console",
10971
paths = {
10972
{path = "/"}
10973
},
10974
target_check = function (host, port, path, response)
10975
return response.status == 200
10976
and response.header["server"] == "RMC Webserver 2.0"
10977
and response.body
10978
and response.body:find("DRAC 4", 1, true)
10979
and response.body:find("%Wvar%s+s_oemProductName%s*=%s*(['\"])DRAC 4%1")
10980
end,
10981
login_combos = {
10982
{username = "root", password = "calvin"}
10983
},
10984
login_check = function (host, port, path, user, pass)
10985
local resp = http_post_simple(host, port, url.absolute(path, "cgi/login"),
10986
nil, {user=user, hash=pass})
10987
return resp.status == 200
10988
and (resp.body or ""):find("%Wtop%.location%.replace%(%s*(['\"])[^'\"]-/cgi/main%1%s*%)")
10989
end
10990
})
10991
10992
table.insert(fingerprints, {
10993
name = "Dell DRAC5",
10994
cpe = "cpe:/h:dell:remote_access_card",
10995
category = "console",
10996
paths = {
10997
{path = "/"}
10998
},
10999
target_check = function (host, port, path, response)
11000
return response.status == 200
11001
and response.body
11002
and response.body:find("%Wtop%.document%.location%.replace%(%s*(['\"])[^'\"]-/cgi%-bin/webcgi/index%1%s*%)")
11003
and response.body:lower():find("<title>remote access controller</title>", 1, true)
11004
end,
11005
login_combos = {
11006
{username = "root", password = "calvin"}
11007
},
11008
login_check = function (host, port, path, user, pass)
11009
local resp = http_post_simple(host, port,
11010
url.absolute(path, "cgi-bin/webcgi/login"),
11011
nil, {user=user, password=pass})
11012
return resp.status == 302
11013
and (resp.header["location"] or ""):find("/cgi%-bin/webcgi/main$")
11014
end
11015
})
11016
11017
table.insert(fingerprints, {
11018
name = "Dell iDRAC6 (lighttpd)",
11019
cpe = "cpe:/o:dell:idrac6_firmware",
11020
category = "console",
11021
paths = {
11022
{path = "/"}
11023
},
11024
target_check = function (host, port, path, response)
11025
return response.status == 302
11026
and (response.header["server"] or ""):find("^lighttpd/%d+%.")
11027
and (response.header["location"] or ""):find("/Applications/dellUI/login%.htm$")
11028
end,
11029
login_combos = {
11030
{username = "root", password = "calvin"}
11031
},
11032
login_check = function (host, port, path, user, pass)
11033
local form = {WEBVAR_PASSWORD=pass,
11034
WEBVAR_USERNAME=user,
11035
WEBVAR_ISCMCLOGIN=0}
11036
local resp = http_post_simple(host, port,
11037
url.absolute(path, "Applications/dellUI/RPC/WEBSES/create.asp"),
11038
nil, form)
11039
return resp.status == 200
11040
and (resp.body or ""):match("'USERNAME'%s*:%s*'(.-)'") == user
11041
end
11042
})
11043
11044
table.insert(fingerprints, {
11045
name = "Dell iDRAC6/7 (Mbedthis)",
11046
cpe = "cpe:/o:dell:idrac7_firmware",
11047
category = "console",
11048
paths = {
11049
{path = "/"}
11050
},
11051
target_check = function (host, port, path, response)
11052
local idrac6 = response.status == 301
11053
and (response.header["server"] or ""):find("^Mbedthis%-Appweb/%d+%.")
11054
local idrac7 = response.status == 302
11055
and response.header["server"] == "Embedthis-http"
11056
return (idrac6 or idrac7)
11057
and (response.header["location"] or ""):find("/start%.html$")
11058
end,
11059
login_combos = {
11060
{username = "root", password = "calvin"}
11061
},
11062
login_check = function (host, port, path, user, pass)
11063
local resp = http_post_simple(host, port, url.absolute(path, "data/login"),
11064
nil, {user=user, password=pass})
11065
return resp.status == 200
11066
and (resp.body or ""):find("<authResult>0</authResult>", 1, true)
11067
end
11068
})
11069
11070
table.insert(fingerprints, {
11071
name = "HP 9000 iLO",
11072
cpe = "cpe:/h:hp:integrated_lights-out",
11073
category = "console",
11074
paths = {
11075
{path = "/"}
11076
},
11077
target_check = function (host, port, path, response)
11078
return response.status == 200
11079
and response.body
11080
and response.body:find("HP 9000", 1, true)
11081
and response.body:find("loginId", 1, true)
11082
and response.body:lower():find("<title>hp ilo login</title>", 1, true)
11083
end,
11084
login_combos = {
11085
{username = "Admin", password = "Admin"},
11086
{username = "Oper", password = "Oper"}
11087
},
11088
login_check = function (host, port, path, user, pass)
11089
local resp = http_post_simple(host, port, url.absolute(path, "signin.html"),
11090
nil, {loginId=user, password=pass})
11091
return resp.status == 200
11092
and get_refresh_url(resp.body or "", "/home%.html$")
11093
and get_cookie(resp, "MPID", "^%x+$")
11094
end
11095
})
11096
11097
table.insert(fingerprints, {
11098
name = "IBM Integrated Management Module",
11099
cpe = "cpe:/o:ibm:integrated_management_module_firmware",
11100
category = "console",
11101
paths = {
11102
{path = "/"}
11103
},
11104
target_check = function (host, port, path, response)
11105
return response.status == 301
11106
and (response.header["location"] or ""):find("/designs/imm/index%.php$")
11107
end,
11108
login_combos = {
11109
{username = "USERID", password = "PASSW0RD"}
11110
},
11111
login_check = function (host, port, path, user, pass)
11112
local form = {user=user,
11113
password=pass,
11114
SessionTimeout=1200}
11115
local resp = http_post_simple(host, port, url.absolute(path, "data/login"),
11116
nil, form)
11117
if not (resp.status == 200 and resp.body) then return false end
11118
local jstatus, jout = json.parse(resp.body)
11119
return jstatus and jout.authResult == "0"
11120
end
11121
})
11122
11123
table.insert(fingerprints, {
11124
name = "Supermicro IPMI",
11125
cpe = "cpe:/o:supermicro:intelligent_platform_management_firmware",
11126
category = "console",
11127
paths = {
11128
{path = "/"}
11129
},
11130
target_check = function (host, port, path, response)
11131
return response.status == 200
11132
and response.body
11133
and response.body:find("ATEN International", 1, true)
11134
and response.body:find("/cgi/login.cgi", 1, true)
11135
end,
11136
login_combos = {
11137
{username = "ADMIN", password = "ADMIN"}
11138
},
11139
login_check = function (host, port, path, user, pass)
11140
local resp = http_post_simple(host, port, url.absolute(path, "cgi/login.cgi"),
11141
nil, {name=user, pwd=pass})
11142
return resp.status == 200
11143
and (resp.body or ""):find("../cgi/url_redirect.cgi?url_name=mainmenu", 1, true)
11144
end
11145
})
11146
11147