Path: blob/master/bin/http-default-accounts-fingerprints-nndefaccts.lua
2960 views
--[[1This file is part of NNdefaccts, an alternate fingerprint dataset for2Nmap script http-default-accounts.34NNdefaccts is Copyright (c) 2012-2019 by nnposter5(nnposter /at/ users.sourceforge.net, <https://github.com/nnposter>)67NNdefaccts is free software: you can redistribute it and/or modify it8under the terms of the GNU General Public License as published by the Free9Software Foundation, either version 3 of the License, or (at your option)10any later version.1112NNdefaccts is distributed in the hope that it will be useful, but WITHOUT13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License15for more details.1617You should have received a copy of the GNU General Public License along18with this program. If not, see <http://www.gnu.org/licenses/>.1920Note that NNdefaccts is licensed separately from Nmap. By obtaining21a custom license for Nmap you are not automatically entitled to modify or22distribute the NNdefaccts dataset to the same extent as Nmap itself and,23conversely, licensing NNdefaccts does not cover Nmap. For details, see24<https://github.com/nnposter/nndefaccts/COPYING>.2526You can obtain the latest version of the dataset from its public repository27at <https://github.com/nnposter/nndefaccts/>.2829To report bugs and other problems, contribute patches, request a feature,30provide generic feedback, etc., please see instructions posted at31<https://github.com/nnposter/nndefaccts/README.md>.32]]333435local base64 = require "base64"36local http = require "http"37local json = require "json"38local math = require "math"39local os = require "os"40local shortport = require "shortport"41local stdnse = require "stdnse"42local table = require "table"43local url = require "url"44local have_openssl, openssl = pcall(require, "openssl")45local have_rand, rand = pcall(require, "rand")46local have_stringaux, stringaux = pcall(require, "stringaux")47local have_tableaux, tableaux = pcall(require, "tableaux")4849---50-- http-default-accounts-fingerprints-nndefaccts.lua51-- This file contains fingerprint data for http-default-accounts.nse52--53-- STRUCTURE:54-- * <code>name</code> - Descriptive name55-- * <code>cpe</code> - Official CPE Dictionary entry (optional)56-- * <code>category</code> - Category57-- * <code>login_combos</code> - Table of default credential pairs58---- * <code>username</code>59---- * <code>password</code>60-- * <code>paths</code> - Table of likely locations (paths) of the target61-- * <code>target_check</code> - Validation function of the target62-- (optional but highly recommended)63-- * <code>login_check</code> - Login function of the target64---6566---67-- Backwards compatibility provisions for library rand68---69if not have_rand then70rand = {}71end72if not rand.random_string then73rand.random_string = stdnse.generate_random_string74end7576---77-- Generates a random alphanumeric string.78--79-- @param len Length of the output string.80-- @return A random string consisting of letters and digits81---82local function random_alnum (len)83return rand.random_string(len, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")84end8586---87-- Generates a random hexadecimal string.88--89-- @param len Length of the output string.90-- @return A random string consisting of hexadecimal digits91---92local function random_hex (len)93return rand.random_string(len, "0123456789abcdef")94end9596---97-- Backwards compatibility provisions for library stringaux98---99if not have_stringaux then100stringaux = {}101end102if not stringaux.ipattern then103stringaux.ipattern = stdnse.generate_case_insensitive_pattern104end105106---107-- Backwards compatibility provisions for library tableaux108---109if not have_tableaux then110tableaux = {}111end112if not tableaux.tcopy then113tableaux.tcopy =114function (tbl)115local clone = {}116for k,v in pairs(tbl) do117clone[k] = type(v) == "table" and tableaux.tcopy(v) or v118end119return clone120end121end122if not tableaux.contains then123tableaux.contains = stdnse.contains124end125126---127-- Requests given path using http.get() but disabling cache and redirects.128-- @param host The host to connect to129-- @param port The port to connect to130-- @param path The path to retrieve131-- @param options [optional] A table of HTTP request options132-- @return A response table (see library http.lua for description)133---134local function http_get_simple (host, port, path, options)135local opts = tableaux.tcopy(options or {})136opts.bypass_cache = true137opts.no_cache = true138opts.redirect_ok = false139return http.get(host, port, path, opts)140end141142---143-- Requests given path using http.post() but disabling cache and redirects.144-- (The current implementation of http.post() does not use either; this is145-- a defensive wrapper to guard against future problems.)146-- @param host The host to connect to147-- @param port The port to connect to148-- @param path The path to retrieve149-- @param options [optional] A table of HTTP request options150-- @param postdata A string or a table of data to be posted151-- @return A response table (see library http.lua for description)152---153local function http_post_simple (host, port, path, options, postdata)154local opts = tableaux.tcopy(options or {})155opts.no_cache = true156opts.redirect_ok = false157return http.post(host, port, path, opts, nil, postdata)158end159160---161-- Requests given path using http_post_simple() with the body formatted as162-- Content-Type multipart/form-data.163-- @param host The host to connect to164-- @param port The port to connect to165-- @param path The path to retrieve166-- @param options [optional] A table of HTTP request options167-- @param postdata A table of data to be posted168-- @return A response table (see library http.lua for description)169---170local function http_post_multipart (host, port, path, options, postdata)171local boundary = ("-"):rep(20)172.. math.random(1000000, 9999999)173.. math.random(1000000, 9999999)174local opts = tableaux.tcopy(options or {})175opts.header = opts.header or {}176opts.header["Content-Type"] = "multipart/form-data; boundary=" .. boundary177if type(postdata) ~= "table" then178return {status = nil,179["status-line"] = "POST data must be a table",180header = {},181rawheader = {}}182end183boundary = "--" .. boundary184local body = {}185for k, v in pairs(postdata) do186table.insert(body, boundary)187table.insert(body, ('Content-Disposition: form-data; name="%s"'):format(k))188table.insert(body, "")189table.insert(body, v)190end191table.insert(body, boundary .. "--")192table.insert(body, "")193return http_post_simple (host, port, path, opts, table.concat(body, "\r\n"))194end195196---197-- Requests given path using native HTTP authentication.198-- @param host Host table199-- @param port Port table200-- @param path Path to request201-- @param user HTTP authentication username202-- @param pass HTTP authentication password203-- @param digest true: digest auth, false: basic auth, "any": try to detect204-- @return True if login in was successful205---206local function try_http_auth (host, port, path, user, pass, digest)207if digest == "any" then208local resp = http_get_simple(host, port, path)209local auth = (resp.header["www-authenticate"] or ""):lower():match("^%w+")210if not auth then return end211digest = auth == "digest"212end213local creds = {username = user, password = pass, digest = digest}214local resp = http_get_simple(host, port, path, {auth=creds})215return resp.status and not (resp.status >= 400 and resp.status <= 405)216end217218---219-- Returns authentication realm advertised in an HTTP response220-- @param response HTTP response object, such as a result from http.get()221-- @return realm found in response header WWW-Authenticate222-- (or nil if not present)223---224local function http_auth_realm (response)225local auth = response.header["www-authenticate"] or ""226-- NB: "OEM Netcam" devices lack the closing double quote227return auth:match('%srealm%s*=%s*"([^"]*)')228end229230---231-- Tests whether an HTTP response sets a named cookie with a given value232-- @param response a standard HTTP response object233-- @param name a case-insensitive cookie name that must be set234-- @param pattern to validate the cookie value235-- @return cookie value if such a cookie is found236---237local function get_cookie (response, name, pattern)238name = name:lower()239for _, ck in ipairs(response.cookies or {}) do240if ck.name:lower() == name and (not pattern or ck.value:find(pattern)) then241return ck.value242end243end244return false245end246247---248-- Parses an HTML tag and returns parsed attributes249-- @param html a string representing HTML tag. It is expected that the first250-- and last characters are angle brackets.251-- @return table of attributes with their names converted to lowercase252---253local function parse_tag (html)254local attrs = {}255local _, pos = html:find("^<%f[%w][%w-]+[^%w-]")256while true do257local attr, equal258_, pos, attr, equal = html:find("%f[%w]([%w-]+)%s*(=?)%s*", pos)259if not pos then break end260local oldpos = pos + 1261if equal == "=" then262local c = html:sub(oldpos, oldpos)263if c == "\"" or c == "'" then264oldpos = oldpos + 1265pos = html:find(c, oldpos, true)266else267pos = html:find("[%s>]", oldpos)268end269if not pos then break end270else271pos = oldpos272end273attrs[attr:lower()] = html:sub(oldpos, pos - 1)274end275return attrs276end277278---279-- Searches given HTML string for an element tag that meets given attribute280-- critera and returns its position and all its attributes281-- @param html a string representing HTML test282-- @param elem an element to search for (for example "img" or "div")283-- @param criteria a table of attribute names and corresponding patterns,284-- for example {id="^secret$"}. The patterns are treated as case-insensitive.285-- (optional)286-- @param init a string position from which to start searching (optional)287-- @return position of the opening angle bracket of the found tag or nil288-- @return position of the closing angle bracket of the found tag or nil289-- @return table of tag attributes with their names converted to lowercase290---291local function find_tag (html, elem, criteria, init)292local icrit = {}293for cnam, cptn in pairs(criteria or {}) do294icrit[cnam:lower()] = stringaux.ipattern(cptn)295end296local tptn = stringaux.ipattern("<" .. elem:gsub("%-", "%%-") .. "%f[%s/>].->")297local start298local stop = init299while true do300start, stop = html:find(tptn, stop)301if not start then break end302local attrs = parse_tag(html:sub(start, stop))303local found = true304for cnam, cptn in pairs(icrit) do305local cval = attrs[cnam]306if not (cval and cval:find(cptn)) then307found = false308break309end310end311if found then return start, stop, attrs end312end313return314end315316---317-- Searches given HTML string for an element tag that meets given attribute318-- critera and returns all its attributes319-- @param html a string representing HTML test320-- @param elem an element to search for (for example "img" or "div")321-- @param criteria a table of attribute names and corresponding patterns,322-- for example {id="^secret$"}. The patterns are treated as case-insensitive.323-- (optional)324-- @param init a string position from which to start searching (optional)325-- @return table of tag attributes with their names converted to lowercase326---327local function get_tag (html, elem, criteria, init)328local start, stop, attrs = find_tag(html, elem, criteria, init)329return attrs330end331332---333-- Builds an iterator function that searches given HTML string for element tags334-- that meets given attribute critera335-- @param html a string representing HTML test336-- @param elem an element to search for (for example "img" or "div")337-- @param criteria a table of attribute names and corresponding patterns,338-- for example {id="^secret$"}. The patterns are treated as case-insensitive.339-- (optional)340-- @param init a string position from which to start searching (optional)341-- @return iterator342---343local function get_tags (html, elem, criteria)344local init = 0345return function ()346local _, attrs347_, init, attrs = find_tag(html, elem, criteria, (init or #html) + 1)348return attrs349end350end351352---353-- Searches given HTML string for an element tag that meets given attribute354-- critera and returns inner HTML of the corresponding element355-- (Nested elements of the same type are not supported.)356-- @param html a string representing HTML test357-- @param elem an element to search for (for example "div" or "title")358-- @param criteria a table of attribute names and corresponding patterns,359-- for example {id="^secret$"}. The patterns are treated as case-insensitive.360-- (optional)361-- @param init a string position from which to start searching (optional)362-- @return inner HTML363---364local function get_tag_html (html, elem, criteria, init)365local _, start, attrs = find_tag(html, elem, criteria, init)366if not start then return end367start = start + 1368local stop = html:find(stringaux.ipattern("</" .. elem:gsub("%-", "%%-") .. "[%s>]"), start)369return stop and html:sub(start, stop - 1) or nil370end371372---373-- Searches given HTML string for a meta refresh tag and returns the target URL374-- @param html a string representing HTML test375-- @param criteria a pattern to validate the extracted target URL376-- for example {id="^secret$"}. The patterns are treated as case-insensitive.377-- (optional)378-- @param init a string position from which to start searching (optional)379-- @return table of tag attributes with their names converted to lowercase380---381local function get_refresh_url (html, criteria)382local refresh = get_tag(html, "meta", {["http-equiv"]="^refresh$", content="^0;%s*url="})383if not refresh then return end384local url = refresh.content:match("=(.*)")385return url:find(stringaux.ipattern(criteria)) and url or nil386end387388---389-- Generates default scheme, host, and port components for a parsed URL.390--391-- This filter function generates the scheme, host, and port components from392-- the standard <code>host</code> and <code>port</code> script objects. These393-- components can then be passed onto function <code>url.build</code>.394--395-- As an example, the following code generates a URL for path "/test/"396-- on the current host and port:397-- <code>398-- local testurl = url.build(url_build_defaults(host, port, {path = "/test/"}))399-- </code>400-- or, alternatively, when not used as a filter:401-- <code>402-- local parsed = url_build_defaults(host, port)403-- parsed.path = "/test/"404-- local testurl = url.build(parsed)405-- </code>406--407-- @param host The host the URL is intended for.408-- @param port The port the URL is intended for.409-- @param parsed Parsed URL, as typically returned by <code>url.parse</code>,410-- or nil. The table can be be missing the scheme, host, and port components.411-- @return A clone of the parsed URL, with any missing scheme, host, and port412-- components added.413-- @see url.parse414-- @see url.build415---416local function url_build_defaults (host, port, parsed)417local parts = tableaux.tcopy(parsed or {})418parts.host = parts.host or stdnse.get_hostname(host, port)419parts.scheme = parts.scheme or shortport.ssl(host, port) and "https" or "http"420if not parts.port and port.number ~= url.get_default_port(parts.scheme) then421parts.port = port.number422end423return parts424end425426---427-- Encodes a string to make it safe for embedding into XML/HTML.428--429-- @param s The string to be encoded.430-- @return A string with unsafe characters encoded431---432local function xmlencode (s)433return s:gsub("%W", function (c) return ("&#x%x;"):format(c:byte()) end)434end435436---437-- Decodes an XML-encoded string.438--439-- @param s The string to be decoded.440-- @return A string with XML encoding stripped off441---442local function xmldecode (s)443local refmap = {amp = "&", quot = "\"", apos = "'", lt ="<", gt = ">"}444return s:gsub("&.-;",445function (e)446local r = e:sub(2,-2)447if r:find("^#x%x%x$") then448return stdnse.fromhex(r:sub(3))449end450return refmap[r]451end)452end453454---455-- Performs URL encoding of all characters in a string.456--457-- @param s The string to be encoded.458-- @return A URL-encoded string459---460local function urlencode_all (s)461return s:gsub(".", function (c) return ("%%%02x"):format(c:byte()) end)462end463464---465-- Decodes a base64-encoded string safely, catching any decoding errors.466--467-- @param s The string to be decoded.468-- @return A decoded string or nil if the input is invalid469---470local function b64decode (s)471local status, out = pcall(base64.dec, s)472return status and out or nil473end474475476fingerprints = {}477478---479--WEB480---481table.insert(fingerprints, {482name = "Ansible AWX",483cpe = "cpe:/a:ansible:tower",484category = "web",485paths = {486{path = "/api/"}487},488target_check = function (host, port, path, response)489if not (response.status == 200490and get_cookie(response, "csrftoken", "^%w+$")491and response.body492and response.body:find("AWX REST API", 1, true)) then493return false494end495local jstatus, jout = json.parse(response.body)496return jstatus and jout.description == "AWX REST API"497end,498login_combos = {499{username = "admin", password = "password"}500},501login_check = function (host, port, path, user, pass)502local resp1 = http_get_simple(host, port, path)503if resp1.status ~= 200 then return false end504local token = get_cookie(resp1, "csrftoken")505if not token then return false end506local form = {username=user,507password=pass,508next=path}509local header = {["X-CSRFToken"]=token}510local resp2 = http_post_simple(host, port, url.absolute(path, "login/"),511{cookies=resp1.cookies, header=header}, form)512return resp2.status == 302513and resp2.header["location"] == path514and get_cookie(resp2, "userLoggedIn") == "true"515end516})517518table.insert(fingerprints, {519name = "Cacti",520cpe = "cpe:/a:cacti:cacti",521category = "web",522paths = {523{path = "/"},524{path = "/cacti/"}525},526target_check = function (host, port, path, response)527return response.status == 200528and (get_cookie(response, "Cacti") or get_cookie(response, "CactiEZ"))529end,530login_combos = {531{username = "admin", password = "admin"}532},533login_check = function (host, port, path, user, pass)534local form = {action="login",535login_username=user,536login_password=pass}537local resp = http_post_simple(host, port, url.absolute(path, "index.php"),538nil, form)539return resp.status == 302540and (resp.header["location"] or ""):find("/", 1, true)541end542})543544table.insert(fingerprints, {545name = "Zabbix",546cpe = "cpe:/a:zabbix:zabbix",547category = "web",548paths = {549{path = "/zabbix/"}550},551target_check = function (host, port, path, response)552return response.status == 200 and get_cookie(response, "zbx_sessionid")553end,554login_combos = {555{username = "admin", password = "zabbix"}556},557login_check = function (host, port, path, user, pass)558local form = {request="",559name=user,560password=pass,561enter="Sign in"}562local resp = http_post_simple(host, port, url.absolute(path, "index.php"),563nil, form)564return resp.status == 302 and resp.header["location"] == "dashboard.php"565end566})567568table.insert(fingerprints, {569name = "Xplico",570category = "web",571paths = {572{path = "/"}573},574target_check = function (host, port, path, response)575return response.status == 302 and get_cookie(response, "Xplico")576end,577login_combos = {578{username = "admin", password = "xplico"},579{username = "xplico", password = "xplico"}580},581login_check = function (host, port, path, user, pass)582local lurl = url.absolute(path, "users/login")583local resp1 = http_get_simple(host, port, lurl)584if not (resp1.status == 200 and resp1.body) then return false end585local html = get_tag_html(resp1.body, "form", {action="/users/login$"})586if not html then return false end587local form = {}588for input in get_tags(html, "input", {type="^hidden$", name="", value=""}) do589form[input.name] = input.value590end591form["data[User][username]"] = user592form["data[User][password]"] = pass593local resp2 = http_post_simple(host, port, lurl,594{cookies=resp1.cookies}, form)595local loc = resp2.header["location"] or ""596return resp2.status == 302597and (loc:find("/admins$") or loc:find("/pols/index$"))598end599})600601table.insert(fingerprints, {602name = "ExtraHop Web UI",603category = "web",604paths = {605{path = "/extrahop/"}606},607target_check = function (host, port, path, response)608return response.status == 200609and response.body610and response.body:find("csrfmiddlewaretoken", 1, true)611and response.body:lower():find("<title>extrahop login", 1, true)612end,613login_combos = {614{username = "admin", password = "admin"}615},616login_check = function (host, port, path, user, pass)617local resp1 = http_get_simple(host, port, path)618if not (resp1.status == 200 and resp1.body) then return false end619local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrfmiddlewaretoken$", value=""})620if not token then return false end621local form = {[token.name]=token.value,622next=path,623username=user,624password=pass}625local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}626local resp2 = http_post_simple(host, port, path,627{cookies=resp1.cookies, header=header}, form)628return resp2.status == 302629and (resp2.header["location"] or ""):sub(-#path) == path630end631})632633table.insert(fingerprints, {634name = "Nagios",635cpe = "cpe:/a:nagios:nagios",636category = "web",637paths = {638{path = "/"},639{path = "/nagios/"}640},641target_check = function (host, port, path, response)642return http_auth_realm(response) == "Nagios Access"643end,644login_combos = {645{username = "nagiosadmin", password = "nagios"},646{username = "nagiosadmin", password = "nagiosadmin"},647{username = "nagiosadmin", password = "PASSW0RD"},648{username = "nagiosadmin", password = "CactiEZ"}649},650login_check = function (host, port, path, user, pass)651return try_http_auth(host, port, path, user, pass, false)652end653})654655table.insert(fingerprints, {656name = "ManageEngine OpManager 10/11",657cpe = "cpe:/a:zohocorp:manageengine_opmanager",658category = "web",659paths = {660{path = "/"}661},662target_check = function (host, port, path, response)663if not (response.status == 200664and response.body665and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])[^'\"]-/LoginPage%.do%1")) then666return false667end668local resp = http_get_simple(host, port, url.absolute(path, "LoginPage.do"))669return resp.status == 200670and resp.body671and resp.body:find("ManageEngine", 1, true)672and resp.body:lower():find("<title>%s*manageengine opmanager%s*</title>")673and get_tag(resp.body, "form", {action="/jsp/login%.do$"})674end,675login_combos = {676{username = "IntegrationUser", password = "plugin"},677{username = "admin", password = "admin"}678},679login_check = function (host, port, path, user, pass)680local resp1 = http_get_simple(host, port, url.absolute(path, "LoginPage.do"))681if resp1.status ~= 200 then return false end682local form2 = {clienttype="html",683isCookieADAuth="",684domainName="NULL",685authType="localUserLogin",686webstart="",687ScreenWidth=1024,688ScreenHeight=768,689loginFromCookieData="",690userName=user,691password=pass,692uname=""}693local resp2 = http_post_simple(host, port,694url.absolute(path, "jsp/Login.do"),695{cookies=resp1.cookies}, form2)696return (resp2.status == 200 or resp2.status == 302)697and get_cookie(resp2, "OPUTILSTICKET", "^%x+$")698end699})700701table.insert(fingerprints, {702name = "ManageEngine OpManager 12",703cpe = "cpe:/a:zohocorp:manageengine_opmanager",704category = "web",705paths = {706{path = "/"}707},708target_check = function (host, port, path, response)709return response.status == 200710and response.body711and response.body:find("ManageEngine", 1, true)712and response.body:lower():find("<title>%s*manageengine opmanager%s*</title>")713and get_tag(response.body, "form", {action="^j_security_check%f[;\0]"})714end,715login_combos = {716{username = "admin", password = "admin"}717},718login_check = function (host, port, path, user, pass)719local resp1 = http_get_simple(host, port, path)720if resp1.status ~= 200 then return false end721local form2 = {AUTHRULE_NAME="Authenticator",722clienttype="html",723ScreenWidth=1024,724ScreenHeight=768,725loginFromCookieData="false",726ntlmv2="false",727j_username=user,728j_password=pass,729domainNameAD="Authenticator",730uname=""}731local resp2 = http_post_simple(host, port,732url.absolute(path, "j_security_check"),733{cookies=resp1.cookies}, form2)734return resp2.status == 303735and (resp2.header["location"] or ""):sub(-#path) == path736end737})738739table.insert(fingerprints, {740name = "ntopng",741cpe = "cpe:/a:ntop:ntopng",742category = "web",743paths = {744{path = "/"}745},746target_check = function (host, port, path, response)747local loc = response.header["location"] or ""748if not (response.status == 302749and loc:find("/lua/login.lua?referer=", 1, true)750and get_cookie(response, "session") == "") then751return false752end753local resp = http_get_simple(host, port, loc)754return resp.status == 200755and resp.body756and resp.body:find("ntopng", 1, true)757and resp.body:lower():find("<title>welcome to ntopng</title>", 1, true)758and get_tag(resp.body, "form", {action="/authorize%.html$"})759end,760login_combos = {761{username = "admin", password = "admin"}762},763login_check = function (host, port, path, user, pass)764local form = {user=user,765password=pass,766referer=host.name .. path}767local resp = http_post_simple(host, port,768url.absolute(path, "authorize.html"),769nil, form)770return resp.status == 302771and resp.header["location"] == path772and get_cookie(resp, "user") == user773end774})775776table.insert(fingerprints, {777name = "OpenNMS",778cpe = "cpe:/a:opennms:opennms",779category = "web",780paths = {781{path = "/login.jsp"},782{path = "/opennms/login.jsp"}783},784target_check = function (host, port, path, response)785return response.status == 200786and response.body787and response.body:find("OpenNMS", 1, true)788and response.body:lower():find("<title>%s*opennms web console%s*</title>")789and get_tag(response.body, "input", {name="^j_username$"})790end,791login_combos = {792{username = "admin", password = "admin"},793{username = "rtc", password = "rtc"}794},795login_check = function (host, port, path, user, pass)796local form = {j_username=user,797j_password=pass,798j_usergroups="",799Login=""}800local resp = http_post_simple(host, port,801url.absolute(path, "j_spring_security_check"),802nil, form)803return resp.status == 302804and (resp.header["location"] or ""):find("/index%.jsp%f[?\0]")805end806})807808table.insert(fingerprints, {809name = "SevOne NMS",810category = "web",811paths = {812{path = "/"}813},814target_check = function (host, port, path, response)815return response.status == 200816and get_cookie(response, "SEVONE")817and response.body818and response.body:lower():find("<title>sevone nms - network manager", 1, true)819end,820login_combos = {821{username = "Admin", password = "SevOne"},822{username = "SevOneStats", password = "n3v3rd13"}823},824login_check = function (host, port, path, user, pass)825local resp1 = http_get_simple(host, port, path)826if not (resp1.status == 200 and resp1.body) then return false end827local token = resp1.body:match("GlobalData%.Utilities%.Xsrf%.setToken%(%s*['\"](%x+)")828if not token then return false end829local form = {login=user,830passwd=pass,831browser="mozilla",832version=52,833tzString=os.date("!%a %b %d %Y %H:%M:%S GMT+0000"),834check_tz=0}835local refpath = url.absolute(path, "doms/login/index.php")836local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=refpath})),837["X-CSRFToken"]=token}838local resp2 = http_post_simple(host, port,839url.absolute(refpath, "processLogin.php"),840{cookies=resp1.cookies, header=header}, form)841if not (resp2.status == 200 and resp2.body) then return false end842local jstatus, jout = json.parse(resp2.body)843return jstatus and (jout.status == 0 or jout.status == -3)844end845})846847table.insert(fingerprints, {848name = "Device42 Appliance Manager",849category = "web",850paths = {851{path = "/"}852},853target_check = function (host, port, path, response)854return response.status == 302 and get_cookie(response, "d42amid")855end,856login_combos = {857{username = "d42admin", password = "default"}858},859login_check = function (host, port, path, user, pass)860local lurl = url.absolute(path, "accounts/login/")861local resp1 = http_get_simple(host, port, lurl .. "?next=" .. path)862if not (resp1.status == 200 and resp1.body) then return false end863local form = {csrfmiddlewaretoken=get_cookie(resp1, "d42amid_csrftoken"),864username=user,865password=pass,866next=path}867local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}868local resp2 = http_post_simple(host, port, lurl,869{cookies=resp1.cookies, header=header}, form)870return resp2.status == 302871and (resp2.header["location"] or ""):sub(-#path) == path872end873})874875table.insert(fingerprints, {876name = "Grafana",877category = "web",878paths = {879{path = "/"}880},881target_check = function (host, port, path, response)882return response.status == 302 and get_cookie(response, "grafana_sess")883end,884login_combos = {885{username = "admin", password = "admin"}886},887login_check = function (host, port, path, user, pass)888local header = {["Accept"]="application/json, text/plain, */*",889["Content-Type"]="application/json;charset=utf-8"}890local jin = {user=user, email="", password=pass}891json.make_object(jin)892local resp = http_post_simple(host, port, url.absolute(path, "login"),893{header=header}, json.generate(jin))894return resp.status == 200 and get_cookie(resp, "grafana_user") == user895end896})897898table.insert(fingerprints, {899name = "Apache Ambari",900cpe = "cpe:/a:apache:ambari",901category = "web",902paths = {903{path = "/"}904},905target_check = function (host, port, path, response)906return response.status == 200907and response.body908and response.body:find(">Ambari<", 1, true)909and response.body:lower():find("<title>ambari</title>", 1, true)910and get_tag(response.body, "script", {src="^javascripts/app%.js$"})911end,912login_combos = {913{username = "admin", password = "admin"}914},915login_check = function (host, port, path, user, pass)916return try_http_auth(host, port, url.absolute(path, "api/v1/users/admin"),917user, pass, false)918end919})920921table.insert(fingerprints, {922name = "Cloudera Manager",923cpe = "cpe:/a:cloudera:cloudera_manager",924category = "web",925paths = {926{path = "/"}927},928target_check = function (host, port, path, response)929return response.status == 200930and get_cookie(response, "CLOUDERA_MANAGER_SESSIONID")931end,932login_combos = {933{username = "admin", password = "admin"}934},935login_check = function (host, port, path, user, pass)936local form = {j_username=user,937j_password=pass,938returnUrl="",939submit=""}940local resp = http_post_simple(host, port,941url.absolute(path, "j_spring_security_check"),942nil, form)943return resp.status == 302944and (resp.header["location"] or ""):find("/cmf/postLogin%f[?\0]")945end946})947948table.insert(fingerprints, {949name = "OpenDaylight",950cpe = "cpe:/a:opendaylight:opendaylight",951category = "web",952paths = {953{path = "/"}954},955target_check = function (host, port, path, response)956return response.status == 200957and get_cookie(response, "JSESSIONID", "^%x+$")958and response.body959and response.body:find("OpenDaylight", 1, true)960and response.body:lower():find("<title>opendaylight ", 1, true)961and get_tag(response.body, "form", {action="^j_security_check%f[;\0]"})962end,963login_combos = {964{username = "admin", password = "admin"}965},966login_check = function (host, port, path, user, pass)967local resp1 = http_get_simple(host, port, path)968if resp1.status ~= 200 then return false end969local resp2 = http_post_simple(host, port,970url.absolute(path, "j_security_check"),971{cookies=resp1.cookies},972{j_username=user, j_password=pass})973return resp2.status == 302974and (resp2.header["location"] or ""):find(path, -#path, true)975end976})977978table.insert(fingerprints, {979name = "OrientDB Studio",980cpe = "cpe:/a:orientdb:orientdb",981category = "web",982paths = {983{path = "/"}984},985target_check = function (host, port, path, response)986return response.status == 200987and response.body988and response.body:find("OrientDB", 1, true)989and get_tag(response.body, "meta", {content="^OrientDB Studio$"})990and get_refresh_url(response.body, "/studio/index%.html$")991end,992login_combos = {993{username = "reader", password = "reader"},994{username = "writer", password = "writer"},995{username = "admin", password = "admin"}996},997login_check = function (host, port, path, user, pass)998local resp1 = http_get_simple(host, port, url.absolute(path, "listDatabases"))999if not (resp1.status == 200 and resp1.body) then return false end1000local jstatus, jout = json.parse(resp1.body)1001if not (jstatus and type(jout.databases) == "table") then return false end1002for _, db in ipairs(jout.databases) do1003if try_http_auth(host, port,1004url.absolute(path, "connect/" .. url.escape(db)),1005user, pass, false) then1006return true1007end1008end1009return false1010end1011})10121013table.insert(fingerprints, {1014name = "RockMongo",1015cpe = "cpe:/a:rockmongo:rockmongo",1016category = "web",1017paths = {1018{path = "/"}1019},1020target_check = function (host, port, path, response)1021local loc = response.header["location"] or ""1022if not (response.status == 3021023and loc:find("/index.php?action=login.index", 1, true)) then1024return false1025end1026local resp = http_get_simple(host, port, loc)1027return resp.status == 2001028and resp.body1029and resp.body:find("RockMongo", 1, true)1030and resp.body:lower():find("<title>rockmongo</title>")1031and get_tag(resp.body, "select", {name="^host$"})1032end,1033login_combos = {1034{username = "admin", password = "admin"}1035},1036login_check = function (host, port, path, user, pass)1037local form = {more=0,1038host=0,1039username=user,1040password=pass,1041db="",1042lang="en_us",1043expire=3}1044local resp = http_post_simple(host, port,1045url.absolute(path, "index.php?action=login.index&host=0"),1046nil, form)1047return resp.status == 3021048and (resp.header["location"] or ""):find("?action=admin.index", 1, true)1049and get_cookie(resp, "ROCK_LANG", "^[%a_]+$")1050end1051})10521053table.insert(fingerprints, {1054name = "Sambar Server",1055cpe = "cpe:/a:sambar:sambar_server",1056category = "web",1057paths = {1058{path = "/"}1059},1060target_check = function (host, port, path, response)1061return response.status == 2001062and (response.header["server"] or ""):find("^SAMBAR%f[%s\0]")1063end,1064login_combos = {1065{username = "admin", password = ""},1066{username = "anonymous", password = ""},1067{username = "billy-bob", password = ""}1068},1069login_check = function (host, port, path, user, pass)1070return try_http_auth(host, port, url.absolute(path, "session/login"),1071user, pass, true)1072end1073})10741075table.insert(fingerprints, {1076name = "WebLogic Server Console",1077cpe = "cpe:/a:bea:weblogic_server",1078category = "web",1079paths = {1080{path = "/console/"}1081},1082target_check = function (host, port, path, response)1083return response.status == 3021084and (response.header["location"] or ""):find("/console/login/LoginForm%.jsp%f[;\0]")1085end,1086login_combos = {1087{username = "weblogic", password = "weblogic"},1088{username = "weblogic", password = "weblogic1"},1089{username = "weblogic", password = "welcome1"},1090{username = "weblogic", password = "password"},1091{username = "system", password = "Passw0rd"},1092{username = "system", password = "password"},1093{username = "operator", password = "Passw0rd"},1094{username = "operator", password = "password"},1095{username = "monitor", password = "Passw0rd"},1096{username = "monitor", password = "password"},1097{username = "oraclesystemuser", password = "Passw0rd"},1098{username = "oraclesystemuser", password = "password"}1099},1100login_check = function (host, port, path, user, pass)1101local form = {j_username=user,1102j_password=pass,1103j_character_encoding="UTF-8"}1104local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}1105local resp = http_post_simple(host, port,1106url.absolute(path, "j_security_check"),1107{header=header}, form)1108if not (resp.status >= 200 and resp.status <= 399) then return false end1109if resp.status == 3021110and (resp.header["location"] or ""):find("/console/login/LoginForm%.jsp$") then1111return false1112end1113return true1114end1115})11161117table.insert(fingerprints, {1118name = "WebSphere Community Edition Console",1119cpe = "cpe:/a:ibm:websphere_application_server",1120category = "web",1121paths = {1122{path = "/console/"}1123},1124target_check = function (host, port, path, response)1125return response.status == 3021126and (response.header["location"] or ""):find("/portal%f[/].-/Welcome%f[?\0]")1127end,1128login_combos = {1129{username = "system", password = "manager"}1130},1131login_check = function (host, port, path, user, pass)1132local resp1 = http_get_simple(host, port, path)1133local resource = resp1.header["location"]1134if not (resp1.status == 302 and resource) then return false end1135local respath = resource:match("%f[/]/%f[^/].*"):gsub("/%.%f[/]", "")1136local resp2 = http_get_simple(host, port, respath)1137if resp2.status ~= 200 then return false end1138local form3 = {j_username=user,1139j_password=pass,1140submit="Login"}1141local resp3 = http_post_simple(host, port,1142url.absolute(respath, "j_security_check"),1143{cookies=resp2.cookies}, form3)1144return resp3.status == 3021145and (resp3.header["location"] or ""):find(respath, 1, true)1146end1147})11481149table.insert(fingerprints, {1150name = "JBoss EAP Admin Console",1151cpe = "cpe:/a:redhat:jboss_enterprise_application_platform",1152category = "web",1153paths = {1154{path = "/"}1155},1156target_check = function (host, port, path, response)1157return response.status == 2001158and response.body1159and response.body:find("/admin-console/", 1, true)1160and get_tag(response.body, "a", {href="/admin%-console/$"})1161and response.body:lower():find("<title>welcome to jboss", 1, true)1162end,1163login_combos = {1164{username = "admin", password = "admin"}1165},1166login_check = function (host, port, path, user, pass)1167local curl = url.absolute(path, "admin-console/")1168local resp1 = http_get_simple(host, port,1169url.absolute(curl, "secure/summary.seam"))1170local lurl = resp1.header["location"]1171if not (resp1.status == 302 and lurl) then return false end1172local lpath = lurl:match("%f[/]/%f[^/].*")1173local resp2 = http_get_simple(host, port, lpath)1174if resp2.status ~= 200 then return false end1175local form3 = {login_form="login_form",1176["login_form:name"]=user,1177["login_form:password"]=pass,1178["login_form:submit"]="Login",1179["javax.faces.ViewState"]="j_id1"}1180local resp3 = http_post_simple(host, port, lpath:gsub("[;?].*$", ""),1181{cookies=resp1.cookies}, form3)1182return resp3.status == 3021183and (resp3.header["location"] or ""):find("/admin-console/secure/summary.seam?conversationId=", 1, true)1184end1185})11861187table.insert(fingerprints, {1188name = "JBoss JMX Console",1189cpe = "cpe:/a:redhat:jboss_enterprise_application_platform",1190category = "web",1191paths = {1192{path = "/"}1193},1194target_check = function (host, port, path, response)1195return response.status == 2001196and response.body1197and response.body:find("/jmx-console/", 1, true)1198and get_tag(response.body, "a", {href="/jmx%-console/$"})1199and response.body:lower():find("<title>welcome to jboss", 1, true)1200end,1201login_combos = {1202{username = "admin", password = "admin"}1203},1204login_check = function (host, port, path, user, pass)1205return try_http_auth(host, port, url.absolute(path, "jmx-console/"),1206user, pass, false)1207end1208})12091210table.insert(fingerprints, {1211name = "JBoss Web Console",1212cpe = "cpe:/a:redhat:jboss_enterprise_web_platform",1213category = "web",1214paths = {1215{path = "/"}1216},1217target_check = function (host, port, path, response)1218return response.status == 2001219and response.body1220and response.body:find("/web-console/", 1, true)1221and get_tag(response.body, "a", {href="/web%-console/$"})1222and response.body:lower():find("<title>welcome to jboss", 1, true)1223end,1224login_combos = {1225{username = "admin", password = "admin"}1226},1227login_check = function (host, port, path, user, pass)1228return try_http_auth(host, port, url.absolute(path, "web-console/"),1229user, pass, false)1230end1231})12321233table.insert(fingerprints, {1234name = "Apache Tomcat Manager",1235cpe = "cpe:/a:apache:tomcat",1236category = "web",1237paths = {1238{path = "/manager/html/"},1239{path = "/manager/status/"},1240{path = "/tomcat/manager/html/"},1241{path = "/tomcat/manager/status/"},1242{path = "/cognos_express/manager/html/"}1243},1244target_check = function (host, port, path, response)1245return http_auth_realm(response) == "Tomcat Manager Application"1246end,1247login_combos = {1248{username = "tomcat", password = "tomcat"},1249{username = "admin", password = "admin"},1250{username = "admin", password = ""},1251{username = "admin", password = "tomcat"},1252{username = "ADMIN", password = "ADMIN"},1253{username = "ovwebusr", password = "OvW*busr1"},1254{username = "j2deployer", password = "j2deployer"},1255{username = "cxsdk", password = "kdsxc"},1256{username = "xampp", password = "xampp"},1257{username = "QCC", password = "QLogic66"},1258{username = "fhir", password = "FHIRDefaultPassword"},1259{username = "username", password = "password"},1260{username = "username1", password = "password"},1261{username = "pippo", password = "paperino"},1262{username = "topolino", password = "minnie"},1263{username = "root", password = "vagrant"},1264{username = "tomcat", password = "s3cret"},1265{username = "root", password = "owaspbwa"},1266{username = "admin", password = "owaspbwa"}1267},1268login_check = function (host, port, path, user, pass)1269return try_http_auth(host, port, path, user, pass, false)1270end1271})12721273table.insert(fingerprints, {1274name = "Apache Tomcat Host Manager",1275cpe = "cpe:/a:apache:tomcat",1276category = "web",1277paths = {1278{path = "/host-manager/html/"},1279{path = "/host-manager/text/"},1280{path = "/tomcat/host-manager/html/"},1281{path = "/tomcat/host-manager/text/"}1282},1283target_check = function (host, port, path, response)1284return http_auth_realm(response) == "Tomcat Host Manager Application"1285end,1286login_combos = {1287{username = "tomcat", password = "tomcat"},1288{username = "admin", password = "admin"},1289{username = "admin", password = ""},1290{username = "ADMIN", password = "ADMIN"},1291{username = "xampp", password = "xampp"},1292{username = "QCC", password = "QLogic66"},1293{username = "fhir", password = "FHIRDefaultPassword"},1294{username = "username", password = "password"},1295{username = "pippo", password = "paperino"},1296{username = "root", password = "vagrant"},1297{username = "tomcat", password = "s3cret"},1298{username = "root", password = "owaspbwa"},1299{username = "admin", password = "owaspbwa"}1300},1301login_check = function (host, port, path, user, pass)1302return try_http_auth(host, port, path, user, pass, false)1303end1304})13051306table.insert(fingerprints, {1307name = "Apache ActiveMQ",1308cpe = "cpe:/a:apache:activemq",1309category = "web",1310paths = {1311{path = "/admin/"}1312},1313target_check = function (host, port, path, response)1314return http_auth_realm(response) == "ActiveMQRealm"1315end,1316login_combos = {1317{username = "user", password = "user"},1318{username = "admin", password = "admin"}1319},1320login_check = function (host, port, path, user, pass)1321return try_http_auth(host, port, path, user, pass, false)1322end1323})13241325table.insert(fingerprints, {1326name = "Pivotal RabbitMQ",1327cpe = "cpe:/a:pivotal_software:rabbitmq",1328category = "web",1329paths = {1330{path = "/"}1331},1332target_check = function (host, port, path, response)1333return response.status == 2001334and response.body1335and response.body:find("RabbitMQ", 1, true)1336and response.body:lower():find("<title>rabbitmq management</title>", 1, true)1337and get_tag(response.body, "div", {id="^outer$"})1338end,1339login_combos = {1340{username = "guest", password = "guest"}1341},1342login_check = function (host, port, path, user, pass)1343return try_http_auth(host, port, url.absolute(path, "api/whoami"),1344user, pass, false)1345end1346})13471348table.insert(fingerprints, {1349name = "OSGi Management Console",1350category = "web",1351paths = {1352{path = "/system/console"},1353{path = "/lc/system/console"}1354},1355target_check = function (host, port, path, response)1356return http_auth_realm(response) == "OSGi Management Console"1357end,1358login_combos = {1359{username = "admin", password = "admin"},1360{username = "karaf", password = "karaf"},1361{username = "smx", password = "smx"}1362},1363login_check = function (host, port, path, user, pass)1364return try_http_auth(host, port, path, user, pass, false)1365end1366})13671368table.insert(fingerprints, {1369name = "Apache Axis2",1370cpe = "cpe:/a:apache:axis2",1371category = "web",1372paths = {1373{path = "/axis2/axis2-admin/"}1374},1375target_check = function (host, port, path, response)1376return response.status == 2001377and response.body1378and response.body:find("Axis2", 1, true)1379and response.body:lower():find("<title>login to axis2 :: administration page</title>", 1, true)1380end,1381login_combos = {1382{username = "admin", password = "axis2"}1383},1384login_check = function (host, port, path, user, pass)1385local resp = http_post_simple(host, port, url.absolute(path, "login"), nil,1386{userName=user,password=pass,submit=" Login "})1387return resp.status == 2001388and get_tag(resp.body or "", "a", {href="^axis2%-admin/logout$"})1389end1390})13911392table.insert(fingerprints, {1393name = "Apache Ofbiz",1394cpe = "cpe:/a:apache:ofbiz",1395category = "web",1396paths = {1397{path = "/webtools/"}1398},1399target_check = function (host, port, path, response)1400local loc = response.header["location"] or ""1401if not (response.status == 3021402and loc:find(url.absolute(path, "control/main"), 1, true)) then1403return false1404end1405local resp = http_get_simple(host, port, loc)1406return resp.status == 2001407and resp.body1408and resp.body:find(url.absolute(loc, "checkLogin"), 1, true)1409and resp.body:lower():find("powered by%s+<a%f[%s][^>]-%shref%s*=%s*['\"]https?://ofbiz%.apache%.org%W")1410end,1411login_combos = {1412{username = "admin", password = "ofbiz"}1413},1414login_check = function (host, port, path, user, pass)1415local form = {USERNAME=user,1416PASSWORD=pass,1417JavaScriptEnabled="Y"}1418local resp = http_post_simple(host, port,1419url.absolute(path, "control/login"),1420nil, form)1421return resp.status == 2001422and get_cookie(resp, path:match("/([^/]+)/$") .. ".autoUserLoginId") == user1423end1424})14251426table.insert(fingerprints, {1427name = "Opencast Matterhorn",1428category = "web",1429paths = {1430{path = "/"}1431},1432target_check = function (host, port, path, response)1433local loc = response.header["location"] or ""1434if not (response.status == 3021435and loc:find("/login%.html%f[;\0]")1436and get_cookie(response, "JSESSIONID", "^%w+$")) then1437return false1438end1439local resp = http_get_simple(host, port, loc)1440return resp.status == 2001441and resp.body1442and resp.body:find("Matterhorn", 1, true)1443and resp.body:lower():find("<title>opencast matterhorn ", 1, true)1444and get_tag(resp.body, "form", {action="/j_spring_security_check$"})1445end,1446login_combos = {1447{username = "admin", password = "opencast"}1448},1449login_check = function (host, port, path, user, pass)1450local form = {j_username=user,1451j_password=pass,1452submit="Login"}1453local resp = http_post_simple(host, port,1454url.absolute(path, "j_spring_security_check"),1455nil, form)1456return resp.status == 3021457and (resp.header["location"] or ""):find("/welcome%.html$")1458and get_cookie(resp, "JSESSIONID", "^%w+$")1459end1460})14611462table.insert(fingerprints, {1463name = "Opencast",1464category = "web",1465paths = {1466{path = "/"}1467},1468target_check = function (host, port, path, response)1469return response.status == 3021470and (response.header["location"] or ""):find("/admin%-ng/login%.html%f[;\0]")1471and get_cookie(response, "JSESSIONID", "^%w+$")1472end,1473login_combos = {1474{username = "admin", password = "opencast"}1475},1476login_check = function (host, port, path, user, pass)1477local resp = http_post_simple(host, port,1478url.absolute(path, "admin-ng/j_spring_security_check"),1479nil, {j_username=user, j_password=pass})1480return resp.status == 3021481and (resp.header["location"] or ""):find("/admin%-ng/index%.html$")1482and get_cookie(resp, "JSESSIONID", "^%w+$")1483end1484})14851486table.insert(fingerprints, {1487name = "Plumtree Portal",1488category = "web",1489paths = {1490{path = "/"}1491},1492target_check = function (host, port, path, response)1493return response.status == 3021494and (response.header["location"] or ""):find("/portal/server%.pt$")1495end,1496login_combos = {1497{username = "Administrator", password = ""}1498},1499login_check = function (host, port, path, user, pass)1500local form = {in_hi_space="Login",1501in_hi_spaceID="0",1502in_hi_control="Login",1503in_hi_dologin="true",1504in_tx_username=user,1505in_pw_userpass=pass,1506in_se_authsource=""}1507local resp = http_post_simple(host, port,1508url.absolute(path, "portal/server.pt"),1509nil, form)1510return resp.status == 3021511and (resp.header["location"] or ""):find("/portal/server%.pt[;?]")1512and get_cookie(resp, "plloginoccured") == "true"1513end1514})15151516table.insert(fingerprints, {1517name = "GLPI",1518cpe = "cpe:/a:glpi-project:glpi",1519category = "web",1520paths = {1521{path = "/"}1522},1523target_check = function (host, port, path, response)1524return response.status == 2001525and response.body1526and response.body:find("GLPI", 1, true)1527and response.body:lower():find("<title>glpi ", 1, true)1528and get_tag(response.body, "input", {name="^login_name$"})1529end,1530login_combos = {1531{username = "glpi", password = "glpi"},1532{username = "tech", password = "tech"},1533{username = "post-only", password = "postonly"},1534{username = "normal", password = "normal"}1535},1536login_check = function (host, port, path, user, pass)1537local resp1 = http_get_simple(host, port, path)1538if not (resp1.status == 200 and resp1.body) then return false end1539local token = get_tag(resp1.body, "input", {type="^hidden$", name="^_glpi_csrf_token$", value=""})1540if not token then return false end1541local form2 = {login_name=user,1542login_password=pass,1543submit="Post",1544[token.name]=token.value}1545local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path}))}1546local resp2 = http_post_simple(host, port, url.absolute(path, "login.php"),1547{cookies=resp1.cookies, header=header}, form2)1548return resp2.status == 2001549and (resp2.body or ""):find("%Wwindow%.location%s*=%s*(['\"])[^'\"]-/front/[%w.]+%.php%1")1550end1551})15521553table.insert(fingerprints, {1554name = "OTRS",1555cpe = "cpe:/a:otrs:otrs",1556category = "web",1557paths = {1558{path = "/otrs/"}1559},1560target_check = function (host, port, path, response)1561return response.status == 2001562and response.body1563and response.body:find("OTRS", 1, true)1564and response.body:find(url.absolute(path, "index.pl"), 1, true)1565and get_tag(response.body, "input", {name="^requestedurl$"})1566end,1567login_combos = {1568{username = "root@localhost", password = "root"},1569{username = "root@localhost", password = "changeme"}1570},1571login_check = function (host, port, path, user, pass)1572local form = {Action="Login",1573RequestedURL="",1574Lang="en",1575TimeOffset=0,1576User=user,1577Password=pass}1578local resp = http_post_simple(host, port, url.absolute(path, "index.pl"),1579nil, form)1580return resp.status == 3021581and get_cookie(resp, "OTRSAgentInterface", "^%w+$")1582end1583})15841585table.insert(fingerprints, {1586name = "Ilias (var.1)",1587cpe = "cpe:/a:ilias:ilias",1588category = "web",1589paths = {1590{path = "/"}1591},1592target_check = function (host, port, path, response)1593return response.status == 3021594and get_cookie(response, "ilClientId")1595and (response.header["location"] or ""):find("%f[^/\0]login%.php%?.*%f[^?&]client_id=")1596end,1597login_combos = {1598{username = "root", password = "homer"}1599},1600login_check = function (host, port, path, user, pass)1601local resp0 = http_get_simple(host, port, path)1602local furl = (resp0.header["location"] or ""):gsub("^https?://[^/]*", "")1603if not (resp0.status == 302 and furl:find("%f[^/\0]login%.php%?")) then1604return false1605end1606furl = url.absolute(path, furl)1607local resp1 = http_get_simple(host, port, furl, {cookies=resp0.cookies})1608if not (resp1.status == 200 and resp1.body) then return false end1609local frm = get_tag(resp1.body, "form", {name="^formlogin$", action="[?&;]client_id="})1610if not frm then return false end1611local form = {username=user,1612password=pass,1613["cmd[doStandardAuthentication]"]="Anmelden"}1614local resp2 = http_post_simple(host, port,1615url.absolute(furl, xmldecode(frm.action)),1616{cookies=resp0.cookies}, form)1617return resp2.status == 3021618and (resp2.header["location"] or ""):find("/ilias%.php?%?")1619end1620})16211622table.insert(fingerprints, {1623name = "Ilias (var.2)",1624cpe = "cpe:/a:ilias:ilias",1625category = "web",1626paths = {1627{path = "/"}1628},1629target_check = function (host, port, path, response)1630return response.status == 3021631and get_cookie(response, "ilClientId")1632and (response.header["location"] or ""):find("%f[^/\0]ilias%.php%f[?\0]")1633end,1634login_combos = {1635{username = "root", password = "homer"}1636},1637login_check = function (host, port, path, user, pass)1638local resp0 = http_get_simple(host, port, path)1639if resp0.status ~= 302 then return false end1640local form1 = {target="",1641client_id=get_cookie(resp0, "ilClientId"),1642cmd="force_login",1643lang="en"}1644local furl = url.absolute(path, "login.php?" .. url.build_query(form1))1645local resp1 = http_get_simple(host, port, furl, {cookies=resp0.cookies})1646if not (resp1.status == 200 and resp1.body) then return false end1647local frm = get_tag(resp1.body, "form", {name="^formlogin$", action="[?&;]client_id="})1648if not frm then return false end1649local form = {username=user,1650password=pass,1651["cmd[doStandardAuthentication]"]="Anmelden"}1652local resp2 = http_post_simple(host, port,1653url.absolute(furl, xmldecode(frm.action)),1654{cookies=resp0.cookies}, form)1655return resp2.status == 3021656and (resp2.header["location"] or ""):find("/ilias%.php?%?")1657end1658})16591660table.insert(fingerprints, {1661name = "Jitamin",1662category = "web",1663paths = {1664{path = "/"}1665},1666target_check = function (host, port, path, response)1667return response.status == 3021668and (response.header["location"] or ""):find("%?controller=Auth/AuthController&action=login$")1669and get_cookie(response, "JM_SID")1670end,1671login_combos = {1672{username = "admin", password = "admin"},1673{username = "[email protected]", password = "admin"}1674},1675login_check = function (host, port, path, user, pass)1676local lurl = path .. "?controller=Auth/AuthController&action="1677local resp1 = http_get_simple(host, port, lurl .. "login")1678if not (resp1.status == 200 and resp1.body) then return false end1679local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrf_token$", value=""})1680if not token then return false end1681local form = {[token.name]=token.value,1682username=user,1683password=pass}1684local resp2 = http_post_simple(host, port, lurl .. "check",1685{cookies=resp1.cookies}, form)1686return resp2.status == 3021687and (resp2.header["location"] or ""):find("%?controller=Dashboard/DashboardController&action=index$")1688end1689})16901691table.insert(fingerprints, {1692name = "Kanboard",1693cpe = "cpe:/a:kanboard:kanboard",1694category = "web",1695paths = {1696{path = "/"},1697{path = "/kanboard/"}1698},1699target_check = function (host, port, path, response)1700return response.status == 3021701and (response.header["location"] or ""):find("%?controller=AuthController&action=login$")1702and get_cookie(response, "KB_SID")1703end,1704login_combos = {1705{username = "admin", password = "admin"}1706},1707login_check = function (host, port, path, user, pass)1708local lurl = path .. "?controller=AuthController&action="1709local resp1 = http_get_simple(host, port, lurl .. "login")1710if not (resp1.status == 200 and resp1.body) then return false end1711local token = get_tag(resp1.body, "input", {type="^hidden$", name="^csrf_token$", value=""})1712if not token then return false end1713local form = {[token.name]=token.value,1714username=user,1715password=pass}1716local resp2 = http_post_simple(host, port, lurl .. "check",1717{cookies=resp1.cookies}, form)1718return resp2.status == 3021719and (resp2.header["location"] or ""):find("%?controller=DashboardController&action=show$")1720end1721})17221723table.insert(fingerprints, {1724name = "RainLoop Webmail",1725category = "web",1726paths = {1727{path = "/"},1728{path = "/rainloop/"},1729{path = "/webmail/"}1730},1731target_check = function (host, port, path, response)1732return response.status == 2001733and response.body1734and response.body:find("rainloop/v/", 1, true)1735and get_tag(response.body, "link", {href="^rainloop/v/%d[%d.]+%d/static/css/app%.min%.css%f[?\0]"})1736end,1737login_combos = {1738{username = "admin", password = "12345"}1739},1740login_check = function (host, port, path, user, pass)1741local resp1 = http_get_simple(host, port, path .. "?/AdminAppData")1742if not (resp1.status == 200 and resp1.body) then return false end1743local jstr = resp1.body:match('{[^{]*"Auth"%s*:.*"PluginsLink"%s*:[^}]*}')1744local jstatus, jout = json.parse(jstr or "{}")1745local token = jstatus and (jout.Token or jout.System and jout.System.token)1746if not token then return false end1747local form2 = {Login=user,1748Password=pass,1749Action="AdminLogin",1750XToken=token}1751local resp2 = http_post_simple(host, port, path .. "?/Ajax/&q[]=/0/",1752{cookies = resp1.cookies}, form2)1753if not (resp2.status == 200 and resp2.body) then return false end1754jstatus, jout = json.parse(resp2.body)1755return jstatus and jout.Action == "AdminLogin" and jout.Result1756end1757})17581759table.insert(fingerprints, {1760name = "TeamPass",1761cpe = "cpe:/a:teampass:teampass",1762category = "web",1763paths = {1764{path = "/"},1765{path = "/teampass/"},1766{path = "/TeamPass/"}1767},1768target_check = function (host, port, path, response)1769return have_openssl1770and tableaux.contains(openssl.supported_ciphers(), "aes-256-ecb")1771and tableaux.contains(openssl.supported_ciphers(), "aes-256-ctr")1772and response.status == 2001773and response.body1774and response.body:find("TeamPass", 1, true)1775and response.body:find("(['\"])sources/main%.queries%.php%1")1776end,1777login_combos = {1778{username = "admin", password = "admin"}1779},1780login_check = function (host, port, path, user, pass)1781local resp1 = http_get_simple(host, port, path)1782if not (resp1.status == 200 and resp1.body) then return false end1783local lurl = resp1.body:match("['\"]([^'\"]+)['\"]%s*,%s*{%s*type%s*:%s*['\"]identify_user['\"]")1784local aespwd = resp1.body:match("%Wreturn%s+Aes%.Ctr%.encrypt%s*%(%s*%w+%s*,%s*['\"](.-)['\"]%s*,%s*256%s*%)")1785or resp1.body:match("['\"]identify_user['\"]%s*,%s*data%s*:%s*prepareExchangedData%(%s*%w+%s*,%s*['\"]encode['\"]%s*,%s*['\"](.-)['\"]")1786if not (lurl and aespwd) then return false end1787aespwd = aespwd .. ("\0"):rep(32-#aespwd)1788local aeskey = openssl.encrypt("aes-256-ecb", aespwd, nil, aespwd):sub(1, 16):rep(2)1789local nonce = ("<I4"):pack(math.floor(stdnse.clock_ms() / 1000))1790.. string.char(math.random(0, 255)):rep(4)1791local randstr = random_alnum(10)1792local jin = {login=user,1793pw=pass,1794duree_session="60",1795screenHeight=tostring(math.random(480, 1024)),1796randomstring=randstr}1797json.make_object(jin)1798local ctext = base64.enc(nonce .. openssl.encrypt("aes-256-ctr", aeskey, nonce .. ("\0"):rep(8), json.generate(jin)))1799local resp2 = http_post_simple(host, port, url.absolute(path, lurl),1800{cookies = resp1.cookies},1801{type="identify_user",data=ctext})1802if not (resp2.status == 200 and resp2.body) then return false end1803local jstatus, jout = json.parse(resp2.body)1804return jstatus and jout[1] and jout[1].value == randstr1805end1806})18071808table.insert(fingerprints, {1809name = "CapeSoft TimeClock",1810category = "web",1811paths = {1812{path = "/"}1813},1814target_check = function (host, port, path, response)1815return response.status == 2001816and response.body1817and response.body:find("TimeClock", 1, true)1818and response.body:lower():find("<title>capesoft time clock web ", 1, true)1819and response.body:lower():find("%Whref%s*=%s*(['\"])employees%.php%1")1820end,1821login_combos = {1822{username = "9970", password = "password"}1823},1824login_check = function (host, port, path, user, pass)1825local resp = http_post_simple(host, port,1826url.absolute(path, "employees.php"), nil,1827{login=user,password=pass,action="Login"})1828return resp.status == 2001829and (resp.body or ""):find("%sclass%s*=%s*(['\"]?)logout%1[%s>]")1830end1831})18321833table.insert(fingerprints, {1834name = "BeEF",1835category = "web",1836paths = {1837{path = "/ui/authentication/"}1838},1839target_check = function (host, port, path, response)1840return response.status == 2001841and response.body1842and response.body:find("BeEF", 1, true)1843and response.body:lower():find("<title>beef authentication</title>", 1, true)1844end,1845login_combos = {1846{username = "beef", password = "beef"}1847},1848login_check = function (host, port, path, user, pass)1849local resp = http_post_simple(host, port, url.absolute(path, "login"), nil,1850{["username-cfrm"]=user, ["password-cfrm"]=pass})1851return resp.status == 2001852and (resp.body or ""):find("{%s*success%s*:%s*true%s*}")1853end1854})18551856table.insert(fingerprints, {1857name = "Greenbone Security Assistant",1858cpe = "cpe:/a:greenbone:greenbone_security_assistant",1859category = "web",1860paths = {1861{path = "/"}1862},1863target_check = function (host, port, path, response)1864local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")1865if not (response.status == 3031866and loc:find("/login/login%.html$")) then1867return false1868end1869local resp = http_get_simple(host, port, loc)1870return resp.status == 2001871and resp.body1872and resp.body:find("Greenbone", 1, true)1873and resp.body:lower():find("<title>greenbone security assistant</title>", 1, true)1874and get_tag(resp.body, "form", {action="/omp$"})1875end,1876login_combos = {1877{username = "admin", password = "admin"},1878{username = "sadmin", password = "changeme"}1879},1880login_check = function (host, port, path, user, pass)1881local lurl = url.absolute(path, "omp")1882local form = {cmd="login",1883text=lurl.."?r=1",1884login=user,1885password=pass}1886local resp = http_post_simple(host, port, lurl, nil, form)1887return resp.status == 3031888and (resp.header["location"] or ""):find("/omp%?.*%f[^?&]token=")1889end1890})18911892table.insert(fingerprints, {1893name = "Sagitta Hashstack",1894category = "web",1895paths = {1896{path = "/"}1897},1898target_check = function (host, port, path, response)1899local lurl = (response.header["location"] or ""):gsub("^https?://[^/]*", "")1900if not (response.status == 302 and lurl:find("/login$")) then1901return false1902end1903local resp = http_get_simple(host, port, lurl)1904return resp.status == 2001905and resp.body1906and resp.body:find("hashstack", 1, true)1907and resp.body:lower():find("<title>hashstack - login</title>", 1, true)1908and get_tag(resp.body, "form", {class="^form%-signin$"})1909end,1910login_combos = {1911{username = "admin", password = "admin"}1912},1913login_check = function (host, port, path, user, pass)1914local header = {["Accept"]="application/json, text/plain, */*",1915["Content-Type"]="application/json"}1916local jin = {username=user, password=pass}1917json.make_object(jin)1918local resp = http_post_simple(host, port, url.absolute(path, "login"),1919{header=header}, json.generate(jin))1920return resp.status == 200 and get_cookie(resp, "sid", ".")1921end1922})19231924table.insert(fingerprints, {1925name = "ZKSoftware WebServer",1926category = "web",1927paths = {1928{path = "/"}1929},1930target_check = function (host, port, path, response)1931return response.status == 2001932and response.header["server"] == "ZK Web Server"1933and response.body1934and response.body:find("%Wlocation%.href%s*=%s*(['\"])[^'\"]-/csl/login%1")1935end,1936login_combos = {1937{username = "administrator", password = "123456"}1938},1939login_check = function (host, port, path, user, pass)1940local resp1 = http_get_simple(host, port, path)1941if not (resp1.status == 200) then return false end1942local resp2 = http_post_simple(host, port, url.absolute(path, "csl/check"),1943{cookies=resp1.cookies},1944{username=user, userpwd=pass})1945return resp2.status == 2001946and get_tag(resp2.body or "", "frame", {src="/csl/menu$"})1947end1948})19491950table.insert(fingerprints, {1951name = "ComfortableMexicanSofa",1952category = "web",1953paths = {1954{path = "/admin/"}1955},1956target_check = function (host, port, path, response)1957if not (response.status == 302 and response.body) then return false end1958local loc = response.header["location"] or ""1959local _, pos = loc:find(url.absolute(path, "sites/"), 1, true)1960if not pos then return false end1961loc = loc:sub(pos)1962if not (loc == "/new" or loc:find("^/%d+/")) then return false end1963for _, ck in ipairs(response.cookies or {}) do1964if ck.name:find("_session$") then return ck.value:find("%-%-%x+$") end1965end1966return false1967end,1968login_combos = {1969{username = "username", password = "password"}1970},1971login_check = function (host, port, path, user, pass)1972return try_http_auth(host, port, url.absolute(path, "sites/new"),1973user, pass, false)1974end1975})19761977table.insert(fingerprints, {1978name = "Hippo CMS",1979category = "web",1980paths = {1981{path = "/"},1982{path = "/cms/"}1983},1984target_check = function (host, port, path, response)1985return response.status == 2001986and response.body1987and response.body:find("hippo-login", 1, true)1988and get_tag(response.body, "input", {name="^id2_hf_0$"})1989end,1990login_combos = {1991{username = "admin", password = "admin"},1992{username = "editor", password = "editor"},1993{username = "author", password = "author"}1994},1995login_check = function (host, port, path, user, pass)1996local lurl;1997local resp1 = http_get_simple(host, port, path)1998if not (resp1.status == 200 and resp1.body) then return false end1999local submit = get_tag(resp1.body, "input", {name="^:submit$", onclick=""})2000if submit then2001local qry = submit.onclick:match("=%s*wicketSubmitFormById%(['\"]id%d+['\"],%s*['\"](.-)['\"]")2002if not qry then return false end2003lurl = xmldecode(qry) .. "&random=" .. math.random()2004else2005local frm = get_tag(resp1.body, "form", {name="^signInForm$", action=""})2006if not frm then return false end2007lurl = frm.action2008end2009local form = {id2_hf_0="",2010username=user,2011password=pass,2012locale="en",2013[":submit"]="log in"}2014local resp2 = http_post_simple(host, port, url.absolute(path, lurl),2015{cookies=resp1.cookies}, form)2016return resp2.status == 3022017and (resp2.header["location"] or ""):sub(-#path) == path2018end2019})20202021---2022--ROUTERS2023---2024table.insert(fingerprints, {2025name = "Cisco IOS",2026cpe = "cpe:/o:cisco:ios",2027category = "routers",2028paths = {2029{path = "/"},2030},2031target_check = function (host, port, path, response)2032local realm = http_auth_realm(response) or ""2033return realm:gsub("_"," "):find("^level 15?%f[ ].* access$")2034end,2035login_combos = {2036{username = "", password = ""},2037{username = "cisco", password = "cisco"},2038{username = "Cisco", password = "Cisco"}2039},2040login_check = function (host, port, path, user, pass)2041return try_http_auth(host, port, path, user, pass, false)2042end2043})20442045table.insert(fingerprints, {2046name = "Cisco Small Business 200",2047category = "routers",2048paths = {2049{path = "/"}2050},2051target_check = function (host, port, path, response)2052return response.status == 2002053and response.body2054and response.body:find("/nikola_login.html", 1, true)2055and response.body:lower():find("<title>switch</title>", 1, true)2056end,2057login_combos = {2058{username = "cisco", password = "cisco"}2059},2060login_check = function (host, port, path, user, pass)2061local form = {uname=user,2062pwd2=base64.enc(pass),2063language_selector="en-US",2064err_flag=0,2065err_msg="",2066passpage="nikola_main2.html",2067failpage="nikola_login.html",2068submit_flag=0}2069local resp = http_post_simple(host, port,2070url.absolute(path, "nikola_login.html"),2071nil, form)2072return resp.status == 200 and get_cookie(resp, "SID", ".")2073end2074})20752076table.insert(fingerprints, {2077name = "Cisco Linksys",2078cpe = "cpe:/h:linksys:*",2079category = "routers",2080paths = {2081{path = "/"}2082},2083target_check = function (host, port, path, response)2084local realm = http_auth_realm(response) or ""2085return realm:find("^Linksys %u[%u%d]+%s*$")2086or realm:find("^WRT54GC%w*$")2087or realm == "NR041"2088end,2089login_combos = {2090{username = "", password = "admin"},2091{username = "admin", password = "admin"},2092},2093login_check = function (host, port, path, user, pass)2094return try_http_auth(host, port, path, user, pass, false)2095end2096})20972098table.insert(fingerprints, {2099name = "Cisco DPC3848VM",2100cpe = "cpe:/h:cisco:dpc3848vm",2101category = "routers",2102paths = {2103{path = "/"}2104},2105target_check = function (host, port, path, response)2106return response.status == 3022107and response.header["location"] == "Docsis_system.php"2108end,2109login_combos = {2110{username = "user", password = ""},2111{username = "", password = ""}2112},2113login_check = function (host, port, path, user, pass)2114local form = {username_login=user,2115password_login=pass,2116LanguageSelect="en",2117login="Log In"}2118local resp = http_post_simple(host, port, url.absolute(path, "check.php"),2119nil, form)2120if not (resp.status == 200 and resp.body) then return false end2121local lstatus = resp.body:match("%Wvar%s+login_status%s*=%s*(%-?%d+)")2122return tonumber(lstatus or "99") <= 02123end2124})21252126table.insert(fingerprints, {2127name = "Cisco EPC3925",2128cpe = "cpe:/h:cisco:epc3925",2129category = "routers",2130paths = {2131{path = "/"}2132},2133target_check = function (host, port, path, response)2134return response.status == 2002135and response.body2136and response.body:find("Docsis", 1, true)2137and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])Docsis_system%.asp%1")2138end,2139login_combos = {2140{username = "", password = ""}2141},2142login_check = function (host, port, path, user, pass)2143local form = {username_login=user,2144password_login=pass,2145LanguageSelect="en",2146Language_Submit="0",2147login="Log In"}2148local resp = http_post_simple(host, port,2149url.absolute(path, "goform/Docsis_system"),2150nil, form)2151return resp.status == 3022152and (resp.header["location"] or ""):find("/Quick_setup%.asp$")2153end2154})21552156table.insert(fingerprints, {2157name = "Cisco Configuration Utility (var.1)",2158category = "routers",2159paths = {2160{path = "/"}2161},2162target_check = function (host, port, path, response)2163return have_openssl2164and response.status == 2002165and response.body2166and response.body:find("cisco", 1, true)2167and response.body:find("%Wfunction%s+en_value%s*%(")2168and get_tag(response.body, "input", {name="^keep_name$"})2169end,2170login_combos = {2171{username = "cisco", password = "cisco"}2172},2173login_check = function (host, port, path, user, pass)2174pass = ("%s%02d"):format(pass, #pass)2175pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)2176local form = {submit_button="login",2177keep_name=0,2178enc=1,2179user=user,2180pwd=stdnse.tohex(openssl.md5(pass))}2181local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),2182nil, form)2183return resp.status == 2002184and (resp.body or ""):find("%Wvar%s+session_key%s*=%s*(['\"])%x*%1%s*;")2185end2186})21872188table.insert(fingerprints, {2189name = "Cisco Configuration Utility (var.2)",2190category = "routers",2191paths = {2192{path = "/"}2193},2194target_check = function (host, port, path, response)2195return have_openssl2196and response.status == 2002197and response.body2198and response.body:find("cisco", 1, true)2199and response.body:find("%Wfunction%s+en_value%s*%(")2200and get_tag(response.body, "input", {name="^gui_action$"})2201end,2202login_combos = {2203{username = "cisco", password = "cisco"}2204},2205login_check = function (host, port, path, user, pass)2206pass = ("%s%02d"):format(pass, #pass)2207pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)2208local form = {submit_button="login",2209submit_type="",2210gui_action="",2211wait_time=0,2212change_action="",2213enc=1,2214user=user,2215pwd=stdnse.tohex(openssl.md5(pass)),2216sel_lang="EN"}2217local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),2218nil, form)2219return resp.status == 2002220and get_tag(resp.body or "", "input", {name="^session_key$", value="^%x+$"})2221end2222})22232224table.insert(fingerprints, {2225name = "Cisco Router Access",2226category = "routers",2227paths = {2228{path = "/"}2229},2230target_check = function (host, port, path, response)2231return have_openssl2232and response.status == 2002233and response.body2234and response.body:find("%Wvar%s+nonce%s*=%s*(['\"])%x+%1")2235and response.body:find("%Wfunction%s+en_value%s*%(")2236and get_tag(response.body, "input", {name="^gui_action$"})2237end,2238login_combos = {2239{username = "", password = "admin"}2240},2241login_check = function (host, port, path, user, pass)2242local resp1 = http_get_simple(host, port, path)2243if not (resp1.status == 200 and resp1.body) then return false end2244local nonce = resp1.body:match("%Wvar%s+nonce%s*=%s*['\"](%x+)['\"]")2245if not nonce then return false end2246pass = ("%s%02d"):format(pass, #pass)2247pass = pass:rep(math.ceil(64 / #pass)):sub(1, 64)2248pass = stdnse.tohex(openssl.md5(pass))2249local wait_time = get_tag(resp1.body, "input", {name="^wait_time$"})2250local form = {submit_button="login",2251change_action="",2252gui_action="Apply",2253wait_time=wait_time and wait_time.value or "",2254submit_type="",2255http_username=user,2256http_passwd=stdnse.tohex(openssl.md5(pass .. nonce))}2257local resp2 = http_post_simple(host, port, url.absolute(path, "login.cgi"),2258nil, form)2259return resp2.status == 2002260and (resp2.body or ""):find(";session_id=%x+%W")2261end2262})22632264table.insert(fingerprints, {2265name = "Cisco IronPort",2266category = "routers",2267paths = {2268{path = "/"}2269},2270target_check = function (host, port, path, response)2271return response.status == 3032272and (response.header["server"] or ""):find("^glass/%d+%.")2273and (response.header["location"] or ""):find("/login%f[?\0]")2274and get_cookie(response, "sid", "^%w+$")2275end,2276login_combos = {2277{username = "admin", password = "ironport"}2278},2279login_check = function (host, port, path, user, pass)2280local refpath = url.absolute(path, "default")2281local form = {referrer=url.build(url_build_defaults(host, port, {path=refpath})),2282screen="login",2283username=user,2284password=pass,2285action="Login"}2286local resp = http_post_simple(host, port, url.absolute(path, "login"),2287nil, form)2288return resp.status == 3032289and (get_cookie(resp, "euq_authenticated", "^%w+$")2290or get_cookie(resp, "authenticated", "^%w+$"))2291end2292})22932294table.insert(fingerprints, {2295name = "Allied Telesis AR",2296cpe = "cpe:/h:alliedtelesyn:cable_dsl_router_at-ar*",2297category = "routers",2298paths = {2299{path = "/"}2300},2301target_check = function (host, port, path, response)2302local realm = http_auth_realm(response) or ""2303return realm:find("^Allied Telesis ")2304or realm:find("^Allied Telesyn ")2305or realm:find("^CentreCOM ")2306end,2307login_combos = {2308{username = "manager", password = "friend"}2309},2310login_check = function (host, port, path, user, pass)2311return try_http_auth(host, port, path, user, pass, false)2312end2313})23142315table.insert(fingerprints, {2316name = "HP ProCurve Switch",2317cpe = "cpe:/h:hp:procurve_switch",2318category = "routers",2319paths = {2320{path = "/"}2321},2322target_check = function (host, port, path, response)2323return response.status == 2002324and (response.header["server"] or ""):lower():find("^ehttp[/%s]")2325and response.body2326and response.body:find("ProCurve Switch", 1, true)2327and (response.body:find("%Wdocument%.location%s*=%s*(['\"])home%.html%1")2328or get_tag(response.body, "frame", {src="^nctabs%.html$"}))2329end,2330login_combos = {2331{username = "", password = ""}2332},2333login_check = function (host, port, path, user, pass)2334return try_http_auth(host, port,2335url.absolute(path, "security/web_access.html"),2336user, pass, false)2337end2338})23392340table.insert(fingerprints, {2341name = "Huawei USG",2342cpe = "cpe:/h:huawei:usg*",2343category = "routers",2344paths = {2345{path = "/"}2346},2347target_check = function (host, port, path, response)2348return response.status == 2002349and get_cookie(response, "SESSIONID", "&Huawei")2350end,2351login_combos = {2352{username = "admin", password = "Admin@123"},2353{username = "audit-admin", password = "Admin@123"}2354},2355login_check = function (host, port, path, user, pass)2356local resp1 = http_get_simple(host, port, path)2357local cookie2358for _, ck in ipairs(resp1.cookies or {}) do2359if ck.name == "SESSIONID" then2360cookie = "SESSIONID=" .. ck.value2361if not ck.httponly then2362cookie = cookie:match("^(.-)&")2363end2364break2365end2366end2367if not (resp1.status == 200 and cookie) then return false end2368local form = {["spring-security-redirect"]="",2369password=pass,2370language="en",2371lang="English",2372username=user,2373platcontent=""}2374local lurl = url.absolute(path, "default.html?dc=" .. math.floor(stdnse.clock_ms()))2375local resp2 = http_post_simple(host, port, lurl, {cookies=cookie}, form)2376return resp2.status == 2002377and (resp2.body or ""):find("top.location.replace(localHref)", 1, true)2378end2379})23802381table.insert(fingerprints, {2382name = "Moxa AirWorks",2383category = "routers",2384paths = {2385{path = "/Login.asp"}2386},2387target_check = function (host, port, path, response)2388return have_openssl2389and response.status == 2002390and response.body2391and response.body:find("Moxa AWK", 1, true)2392and response.body:find("/webNonce%W")2393and get_tag(response.body, "form", {action="/home%.asp$"})2394end,2395login_combos = {2396{username = "admin", password = "root"}2397},2398login_check = function (host, port, path, user, pass)2399local resp1 = http_get_simple(host, port, url.absolute(path, "Login.asp"))2400if not (resp1.status == 200 and resp1.body) then return false end2401local pcookie = resp1.body:match("%Wfunction%s+SetCookie%W[^}]-theName%s*=%s*['\"](.-)[='\"]")2402if not pcookie then return false end2403local form2 = {user=user, time=math.floor(stdnse.clock_ms())}2404local url2 = url.absolute(path, "webNonce?" .. url.build_query(form2))2405local resp2 = http_get_simple(host, port, url2,2406{cookies={{name=pcookie, value=""}}})2407if not (resp2.status == 200 and resp2.body) then return false end2408local cpass = stdnse.tohex(openssl.md5(pass .. resp2.body))2409local form3 = {Username=user,2410Password="",2411["Submit.x"]=0,2412["Submit.y"]=0}2413local resp3 = http_post_simple(host, port, url.absolute(path, "home.asp"),2414{cookies={{name=pcookie, value=cpass}}},2415form3)2416return resp3.status == 2002417and get_tag(resp3.body or "", "frame", {src="^main%.asp$"})2418end2419})24202421table.insert(fingerprints, {2422name = "Moxa EDR (var.1)",2423cpe = "cpe:/o:moxa:edr_g903_firmware",2424category = "routers",2425paths = {2426{path = "/Login.asp"}2427},2428target_check = function (host, port, path, response)2429return have_openssl2430and response.status == 2002431and response.body2432and response.body:find("Moxa EDR", 1, true)2433and response.body:find(">iGenSel2%((['\"])Username%1")2434and response.body:find("%Wdocument%.getElementById%(%s*(['\"])Username%1%s*%)%.value%s*%+%s*(['\"]):%2")2435end,2436login_combos = {2437{username = "admin", password = ""},2438{username = "user", password = ""}2439},2440login_check = function (host, port, path, user, pass)2441local cpass = stdnse.tohex(openssl.md5(#pass > 0 and pass or "NULL"))2442local cookies = {{name="admin:EDR", value=(user=="admin" and cpass or "")},2443{name="user:EDR", value=(user=="user" and cpass or "")}}2444local form1 = {Username=user,2445Password=pass,2446["Submit.x"]=0,2447["Submit.y"]=0}2448local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),2449{cookies=cookies}, form1)2450if resp1.status~=200 then return false end2451local resp2 = http_get_simple(host, port, url.absolute(path, "index.asp"),2452{cookies=cookies})2453return resp2.status == 2002454and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})2455end2456})24572458table.insert(fingerprints, {2459name = "Moxa EDR (var.2)",2460cpe = "cpe:/o:moxa:edr_g903_firmware",2461category = "routers",2462paths = {2463{path = "/Login.asp"}2464},2465target_check = function (host, port, path, response)2466return have_openssl2467and response.status == 2002468and response.body2469and response.body:find("Moxa EDR", 1, true)2470and response.body:find(">iGenSel2%((['\"])Username%1")2471and response.body:find("%Wdocument%.getElementById%(%s*(['\"])Username%1%s*%)%.value%s*;")2472end,2473login_combos = {2474{username = "admin", password = ""},2475{username = "user", password = ""}2476},2477login_check = function (host, port, path, user, pass)2478local cuser = #user > 0 and user or "unknown"2479local cpass = #pass > 0 and pass or "NULL"2480local cookies = {{name="NAME", value=url.escape(cuser)},2481{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}2482local form1 = {Username=user,2483Password=pass,2484["Submit.x"]=0,2485["Submit.y"]=0}2486local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),2487{cookies=cookies}, form1)2488if resp1.status~=200 then return false end2489local resp2 = http_get_simple(host, port, url.absolute(path, "home.asp"),2490{cookies=cookies})2491return resp2.status == 2002492and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})2493end2494})24952496table.insert(fingerprints, {2497name = "Moxa EDR (var.3)",2498cpe = "cpe:/o:moxa:edr_g903_firmware",2499category = "routers",2500paths = {2501{path = "/Login.asp"}2502},2503target_check = function (host, port, path, response)2504return have_openssl2505and response.status == 2002506and response.body2507and response.body:find("Moxa EDR", 1, true)2508and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")2509and not response.body:find("sysnotify_support", 1, true)2510and response.body:find("%Wvar%s+rndN%s*=%s*%d+%s*;")2511end,2512login_combos = {2513{username = "admin", password = "moxa"},2514{username = "user", password = "moxa"}2515},2516login_check = function (host, port, path, user, pass)2517local resp1 = http_get_simple(host, port, url.absolute(path, "Login.asp"))2518if not (resp1.status == 200 and resp1.body) then return false end2519local nonce = resp1.body:match("%Wvar%s+rndN%s*=%s*(%d+)%s*;")2520if not nonce then return false end2521local cuser = #user > 0 and user or "unknown"2522local cpass = pass .. nonce2523local cookies = {{name="NAME", value=url.escape(cuser)},2524{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}2525local form2 = {Username=user,2526Password=pass,2527["Submit.x"]=0,2528["Submit.y"]=0}2529local resp2 = http_post_simple(host, port, url.absolute(path, "init.asp"),2530{cookies=cookies}, form2)2531if resp2.status~=200 then return false end2532local resp3 = http_get_simple(host, port, url.absolute(path, "home.asp"),2533{cookies=cookies})2534return resp3.status == 2002535and get_tag(resp3.body or "", "frame", {src="^name%.asp$"})2536end2537})25382539table.insert(fingerprints, {2540name = "Moxa EDR (var.4)",2541category = "routers",2542paths = {2543{path = "/Login.asp"}2544},2545target_check = function (host, port, path, response)2546return have_openssl2547and response.status == 2002548and response.body2549and response.body:find("Moxa EDR", 1, true)2550and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")2551and not response.body:find("sysnotify_support", 1, true)2552and not response.body:find("%Wvar%s+rndN%s*=%s*%d+%s*;")2553end,2554login_combos = {2555{username = "admin", password = "moxa"},2556{username = "user", password = "moxa"}2557},2558login_check = function (host, port, path, user, pass)2559local cuser = #user > 0 and user or "unknown"2560local cpass = #pass > 0 and pass or "NULL"2561local cookies = {{name="NAME", value=url.escape(cuser)},2562{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))}}2563local form1 = {Username=user,2564Password=pass,2565["Submit.x"]=0,2566["Submit.y"]=0}2567local resp1 = http_post_simple(host, port, url.absolute(path, "init.asp"),2568{cookies=cookies}, form1)2569if resp1.status~=200 then return false end2570local resp2 = http_get_simple(host, port, url.absolute(path, "home.asp"),2571{cookies=cookies})2572return resp2.status == 2002573and get_tag(resp2.body or "", "frame", {src="^name%.asp$"})2574end2575})25762577table.insert(fingerprints, {2578name = "Moxa EDR (var.5)",2579cpe = "cpe:/o:moxa:edr_g903_firmware",2580category = "routers",2581paths = {2582{path = "/Login.asp"}2583},2584target_check = function (host, port, path, response)2585return have_openssl2586and response.status == 2002587and response.body2588and response.body:find("Moxa EDR", 1, true)2589and response.body:find("%Wdocument%.getElementById%(%s*(['\"])InputPassword%1%s*%)%.action%s*=%s*(['\"])[^'\"]-/init%.asp%2")2590and response.body:find("sysnotify_support", 1, true)2591end,2592login_combos = {2593{username = "admin", password = "moxa"},2594{username = "user", password = "moxa"}2595},2596login_check = function (host, port, path, user, pass)2597local cuser = #user > 0 and user or "unknown"2598local cpass = #pass > 0 and pass or "NULL"2599local cookies = {{name="sysnotify_support", value="yes"},2600{name="sysnotify_loginStatus", value="initial"},2601{name="lasttime", value=tostring(math.floor(stdnse.clock_ms()))},2602{name="sessionID", value=tostring(math.random(1000000000, 4294967295))},2603{name="NAME", value=url.escape(cuser)},2604{name="PASSWORD", value=stdnse.tohex(openssl.md5(cpass))},2605{name="AUTHORITY", value=""}}2606local form = {Username=user,2607Password=pass,2608["Submit.x"]=0,2609["Submit.y"]=0}2610local resp = http_post_simple(host, port, url.absolute(path, "init.asp"),2611{cookies=cookies}, form)2612return resp.status == 2002613and (resp.body or ""):find("%sonLoad%s*=%s*['\"]SetAuthorityCookie%(")2614end2615})26162617table.insert(fingerprints, {2618name = "Ovislink AirLive (basic auth)",2619cpe = "cpe:/h:ovislink:airlive_*",2620category = "routers",2621paths = {2622{path = "/"}2623},2624target_check = function (host, port, path, response)2625local realm = http_auth_realm(response) or ""2626return realm:find("^AirLive ")2627or realm:find("%f[%w]admin/airlive$")2628or realm:find("%f[%w]airlive/airlive$")2629end,2630login_combos = {2631{username = "admin", password = "airlive"},2632{username = "airlive", password = "airlive"}2633},2634login_check = function (host, port, path, user, pass)2635return try_http_auth(host, port, path, user, pass, false)2636end2637})26382639table.insert(fingerprints, {2640name = "Ovislink AirLive AP",2641cpe = "cpe:/h:ovislink:airlive_*",2642category = "routers",2643paths = {2644{path = "/index.asp"}2645},2646target_check = function (host, port, path, response)2647return response.status == 2002648and response.body2649and response.body:find("AirLive", 1, true)2650and response.body:lower():find("<title>airlive [%w-]+</title>")2651and response.body:lower():find("%shref%s*=%s*(['\"]?)sts_%w+%.asp%1[%s>]")2652end,2653login_combos = {2654{username = "", password = "airlive"}2655},2656login_check = function (host, port, path, user, pass)2657local resp = http_post_simple(host, port,2658url.absolute(path, "goform/asp_login"),2659nil, {psw=pass})2660return resp.status == 3022661and (resp.header["location"] or ""):find("/sts_%w+%.asp$")2662end2663})26642665table.insert(fingerprints, {2666name = "Ovislink AirLive WIAS (var.1)",2667cpe = "cpe:/h:ovislink:airlive_*",2668category = "routers",2669paths = {2670{path = "/"}2671},2672target_check = function (host, port, path, response)2673return response.status == 2002674and response.body2675and response.body:find("WIAS", 1, true)2676and response.body:lower():find("<title>wias%-%d+%a</title>")2677and get_tag(response.body, "form", {action="^check%.shtml$"})2678and get_tag(response.body, "input", {name="^password$"})2679end,2680login_combos = {2681{username = "admin", password = "airlive"}2682},2683login_check = function (host, port, path, user, pass)2684local resp = http_post_simple(host, port,2685url.absolute(path, "check.shtml"),2686nil, {username=user,password=pass})2687return resp.status == 3022688and resp.header["location"] == "home.shtml"2689end2690})26912692table.insert(fingerprints, {2693name = "Ovislink AirLive WIAS (var.2)",2694cpe = "cpe:/h:ovislink:airlive_*",2695category = "routers",2696paths = {2697{path = "/"}2698},2699target_check = function (host, port, path, response)2700return response.status == 2002701and response.body2702and response.body:find("AirLive", 1, true)2703and response.body:lower():find("<title>airlive wias%-%d+%a</title>")2704and get_tag(response.body, "form", {action="^check%.shtml$"})2705and get_tag(response.body, "input", {name="^adm_pwd$"})2706end,2707login_combos = {2708{username = "admin", password = "airlive"}2709},2710login_check = function (host, port, path, user, pass)2711local resp = http_post_simple(host, port,2712url.absolute(path, "check.shtml"),2713nil, {adm_name=user,adm_pwd=pass})2714return resp.status == 3022715and resp.header["location"] == "home.shtml"2716end2717})27182719table.insert(fingerprints, {2720name = "AirTies router",2721cpe = "cpe:/h:airties:air_*",2722category = "routers",2723paths = {2724{path = "/"}2725},2726target_check = function (host, port, path, response)2727return response.status == 2002728and response.body2729and get_refresh_url(response.body, "/js/%.js_check%.html$")2730end,2731login_combos = {2732{username = "admin", password = ""}2733},2734login_check = function (host, port, path, user, pass)2735local form = {redirect="",2736self="",2737user=user,2738password=pass,2739gonder="OK"}2740local resp = http_post_simple(host, port,2741url.absolute(path, "cgi-bin/login"),2742nil, form)2743return resp.status == 2002744and get_cookie(resp, "AIRTIESSESSION", "^%x+$")2745and get_refresh_url(resp.body or "", "/main%.html$")2746end2747})27482749table.insert(fingerprints, {2750name = "Arris Touchstone",2751cpe = "cpe:/a:arris:touchstone_*",2752category = "routers",2753paths = {2754{path = "/"}2755},2756target_check = function (host, port, path, response)2757return response.status == 2002758and response.body2759and response.body:find("sta_wifi", 1, true)2760and get_tag(response.body, "form", {action="^check%.php$"})2761end,2762login_combos = {2763{username = "admin", password = "password"}2764},2765login_check = function (host, port, path, user, pass)2766local resp = http_post_simple(host, port, url.absolute(path, "check.php"),2767nil, {username=user,password=pass})2768return resp.status == 2002769and get_cookie(resp, "PHPSESSID", "^%w+$")2770and (resp.body or ""):find("%Wlocation%.href%s*=%s*(['\"])admin_password_change%.php%1")2771end2772})27732774table.insert(fingerprints, {2775name = "ASUS TM router",2776cpe = "cpe:/h:asus:tm-*",2777category = "routers",2778paths = {2779{path = "/"}2780},2781target_check = function (host, port, path, response)2782return (http_auth_realm(response) or ""):find("^TM%-%u[%u%d]+$")2783end,2784login_combos = {2785{username = "admin", password = "password"}2786},2787login_check = function (host, port, path, user, pass)2788return try_http_auth(host, port, path, user, pass, false)2789end2790})27912792table.insert(fingerprints, {2793name = "ASUS router",2794category = "routers",2795paths = {2796{path = "/"}2797},2798target_check = function (host, port, path, response)2799local realm = http_auth_realm(response)2800if not realm then return false end2801local type = realm:match("^(%u+)%-%u[%u%d]+$")2802for t in ("DSL,EA,RP,RT,TM"):gmatch("%u+") do2803if t == type then return true end2804end2805return false2806end,2807login_combos = {2808{username = "admin", password = "admin"}2809},2810login_check = function (host, port, path, user, pass)2811return try_http_auth(host, port, path, user, pass, false)2812end2813})28142815table.insert(fingerprints, {2816name = "ASUS RX3041",2817category = "routers",2818paths = {2819{path = "/"}2820},2821target_check = function (host, port, path, response)2822return (http_auth_realm(response) or ""):find("^ *RX3041%f[ \0]")2823end,2824login_combos = {2825{username = "admin", password = "admin"}2826},2827login_check = function (host, port, path, user, pass)2828return try_http_auth(host, port, path, user, pass, false)2829end2830})28312832table.insert(fingerprints, {2833name = "Belkin G Wireless Router",2834cpe = "cpe:/h:belkin:f5d7234-4",2835category = "routers",2836paths = {2837{path = "/"}2838},2839target_check = function (host, port, path, response)2840return have_openssl2841and response.status == 2002842and response.body2843and response.body:find("setup_top.htm", 1, true)2844and response.body:find("status.stm", 1, true)2845end,2846login_combos = {2847{username = "", password = ""}2848},2849login_check = function (host, port, path, user, pass)2850local resp = http_post_simple(host, port,2851url.absolute(path, "cgi-bin/login.exe"), nil,2852{totalMSec = stdnse.clock_ms()/1000,2853pws = stdnse.tohex(openssl.md5(pass))})2854return resp.status == 3022855and (resp.header["location"] or ""):find("/index%.htm$")2856end2857})28582859table.insert(fingerprints, {2860name = "Belkin/Arris 2307",2861category = "routers",2862paths = {2863{path = "/"}2864},2865target_check = function (host, port, path, response)2866return response.status == 2002867and response.body2868and response.body:find("isAPmode", 1, true)2869and get_tag(response.body, "meta", {name="^description$", content="^%w+ 2307$"})2870end,2871login_combos = {2872{username = "", password = ""}2873},2874login_check = function (host, port, path, user, pass)2875local form = {page="",2876logout="",2877action="submit",2878pws=base64.enc(pass),2879itsbutton1="Submit",2880h_language="en",2881is_parent_window="1"}2882local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),2883nil, form)2884return resp.status == 2002885and (resp.body or ""):find("index.html", 1, true)2886end2887})28882889table.insert(fingerprints, {2890name = "D-Link DIR router (var.1)",2891cpe = "cpe:/h:d-link:dir-*",2892category = "routers",2893paths = {2894{path = "/"}2895},2896target_check = function (host, port, path, response)2897return response.status == 2002898and (response.header["server"] or ""):find(" DIR%-%d+")2899and response.body2900and response.body:find("AUTH.Login(", 1, true)2901and response.body:find('%WOBJ%("loginusr"%)%.value%s*=%s*""')2902and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")2903end,2904login_combos = {2905{username = "admin", password = ""}2906},2907login_check = function (host, port, path, user, pass)2908local form = {REPORT_METHOD="xml",2909ACTION="login_plaintext",2910USER=user,2911PASSWD=pass,2912CAPTCHA=""}2913local resp = http_post_simple(host, port, url.absolute(path, "session.cgi"),2914{cookies="uid="..random_alnum(10)}, form)2915return resp.status == 2002916and (resp.body or ""):find("<RESULT>SUCCESS</RESULT>", 1, true)2917end2918})29192920table.insert(fingerprints, {2921name = "D-Link DIR router (var.2)",2922cpe = "cpe:/h:d-link:dir-*",2923category = "routers",2924paths = {2925{path = "/"}2926},2927target_check = function (host, port, path, response)2928return response.status == 2002929and (response.header["server"] or ""):find(" DIR%-%d+")2930and response.body2931and response.body:find("AUTH.Login(", 1, true)2932and response.body:find('%WOBJ%("loginusr"%)%.value%s*=%s*username%W')2933and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")2934end,2935login_combos = {2936{username = "Admin", password = ""}2937},2938login_check = function (host, port, path, user, pass)2939local form = {REPORT_METHOD="xml",2940ACTION="login_plaintext",2941USER=user,2942PASSWD=pass,2943CAPTCHA=""}2944local resp = http_post_simple(host, port, url.absolute(path, "session.cgi"),2945{cookies="uid="..random_alnum(10)}, form)2946return resp.status == 2002947and (resp.body or ""):find("<RESULT>SUCCESS</RESULT>", 1, true)2948end2949})29502951table.insert(fingerprints, {2952name = "D-Link DIR router (var.3)",2953cpe = "cpe:/h:d-link:dir-*",2954category = "routers",2955paths = {2956{path = "/"}2957},2958target_check = function (host, port, path, response)2959return have_openssl2960and response.status == 2002961and (response.header["server"] or ""):find(" DIR%-%d+")2962and response.body2963and response.body:find("AUTH.Login_Hash(", 1, true)2964and response.body:lower():find("<title>d%-link systems[^<]+ home</title>")2965end,2966login_combos = {2967{username = "Admin", password = ""}2968},2969login_check = function (host, port, path, user, pass)2970local url2 = url.absolute(path, "authentication.cgi")2971local url1 = url2 .. "?captcha=&dummy=" .. math.floor(stdnse.clock_ms())2972local resp1 = http_get_simple(host, port, url1)2973if not (resp1.status == 200 and resp1.body) then return false end2974local jstatus, jout = json.parse(resp1.body)2975if not (jstatus and jout.uid and jout.challenge) then return false end2976local auth = stdnse.tohex(openssl.hmac("MD5", pass, user .. jout.challenge))2977local resp2 = http_post_simple(host, port, url2,2978{cookies = "uid=" .. jout.uid},2979{id=user, password=auth:upper()})2980if not (resp2.status == 200 and resp2.body) then return false end2981jstatus, jout = json.parse(resp2.body)2982return jstatus and jout.status == "ok"2983end2984})29852986table.insert(fingerprints, {2987name = "D-Link DIR-620",2988cpe = "cpe:/h:d-link:dir-620",2989category = "routers",2990paths = {2991{path = "/"}2992},2993target_check = function (host, port, path, response)2994return response.status == 2002995and response.body2996and response.body:find("DIR-620", 1, true)2997and response.body:lower():find("<title>dir-620</title>", 1, true)2998and get_tag(response.body, "form", {action="^index%.cgi$"})2999end,3000login_combos = {3001{username = "admin", password = "anonymous"}3002},3003login_check = function (host, port, path, user, pass)3004local cookies = {{name="user_ip", value="127.0.0.1"},3005{name="cookie_lang", value="rus"},3006{name="client_login", value=user},3007{name="client_password", value=pass}}3008local resp = http_post_simple(host, port, url.absolute(path, "index.cgi"),3009{cookies=cookies},3010{v2="y",rs_type="html",auth="auth"})3011return resp.status == 2003012and (resp.body or ""):find("%sid%s*=%s*(['\"])v_firmware_value%1%s*>%d")3013end3014})30153016table.insert(fingerprints, {3017name = "D-Link DIR router (basic auth)",3018cpe = "cpe:/h:d-link:dir-*",3019category = "routers",3020paths = {3021{path = "/"}3022},3023target_check = function (host, port, path, response)3024return (http_auth_realm(response) or ""):find("%f[%w]DIR%-%d%d%d%f[%u\0]")3025end,3026login_combos = {3027{username = "admin", password = "admin"},3028{username = "admin", password = ""}3029},3030login_check = function (host, port, path, user, pass)3031return try_http_auth(host, port, path, user, pass, false)3032end3033})30343035table.insert(fingerprints, {3036name = "D-Link DSL router",3037cpe = "cpe:/h:d-link:dsl-*",3038category = "routers",3039paths = {3040{path = "/"}3041},3042target_check = function (host, port, path, response)3043return response.status == 2003044and (response.header["server"] or ""):find("^mini_httpd/%d+%.")3045and response.body3046and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])[^'\"]-/cgi%-bin/webproc%1")3047end,3048login_combos = {3049{username = "admin", password = "admin"},3050{username = "admin", password = "password"},3051},3052login_check = function (host, port, path, user, pass)3053local lurl = url.absolute(path, "cgi-bin/webproc")3054local resp1 = http_get_simple(host, port, lurl)3055if not (resp1.status == 200) then return false end3056local form = {getpage="html/index.html",3057errorpage="html/main.html",3058["var:menu"]="setup",3059["var:page"]="wizard",3060["obj-action"]="auth",3061[":username"]=user,3062[":password"]=pass,3063[":action"]="login",3064[":sessionid"]=get_cookie(resp1, "sessionid")}3065local resp2 = http_post_simple(host, port, lurl,3066{cookies=resp1.cookies}, form)3067return resp2.status == 3023068and (resp2.header["location"] or ""):find("/cgi-bin/webproc?getpage=html/index.html&", 1, true)3069end3070})30713072table.insert(fingerprints, {3073name = "D-Link DSL router (basic auth)",3074cpe = "cpe:/h:d-link:dsl-*",3075category = "routers",3076paths = {3077{path = "/"}3078},3079target_check = function (host, port, path, response)3080return (http_auth_realm(response) or ""):find("^DSL%-%d%d%d%d?[BRU]%f[_\0]")3081end,3082login_combos = {3083{username = "admin", password = "admin"},3084{username = "support", password = "support"}3085},3086login_check = function (host, port, path, user, pass)3087return try_http_auth(host, port, path, user, pass, false)3088end3089})30903091table.insert(fingerprints, {3092name = "D-Link DSL T router (basic auth)",3093cpe = "cpe:/h:d-link:dsl-*",3094category = "routers",3095paths = {3096{path = "/"}3097},3098target_check = function (host, port, path, response)3099return (http_auth_realm(response) or ""):find("%f[^ \0]DSL%-%d%d%d%d?T$")3100end,3101login_combos = {3102{username = "admin", password = "admin"},3103{username = "user", password = "user"}3104},3105login_check = function (host, port, path, user, pass)3106return try_http_auth(host, port, path, user, pass, false)3107end3108})31093110table.insert(fingerprints, {3111name = "TP-Link (basic auth)",3112cpe = "cpe:/o:tp-link:lm_firmware",3113category = "routers",3114paths = {3115{path = "/"}3116},3117target_check = function (host, port, path, response)3118return response.status == 4013119and (http_auth_realm(response) or ""):find("^TP%-LINK")3120end,3121login_combos = {3122{username = "admin", password = "admin"}3123},3124login_check = function (host, port, path, user, pass)3125return try_http_auth(host, port, path, user, pass, false)3126end3127})31283129table.insert(fingerprints, {3130name = "TP-Link (MD5 cookie)",3131cpe = "cpe:/o:tp-link:lm_firmware",3132category = "routers",3133paths = {3134{path = "/"}3135},3136target_check = function (host, port, path, response)3137return have_openssl3138and response.status == 2003139and (http_auth_realm(response) or ""):find("^TP%-LINK")3140and response.body3141and response.body:find("%spassword%s*=%s*hex_md5")3142end,3143login_combos = {3144{username = "admin", password = "admin"}3145},3146login_check = function (host, port, path, user, pass)3147local auth = base64.enc(user .. ":" .. stdnse.tohex(openssl.md5(pass)))3148local cookie = "Authorization=" .. url.escape("Basic " .. auth)3149local resp = http_get_simple(host, port,3150url.absolute(path, "userRpm/LoginRpm.htm?Save=Save"),3151{cookies=cookie})3152return resp.status == 2003153and (resp.body or ""):find(">window%.parent%.location%.href%s*=%s*(['\"])[^'\"]-/userRpm/Index%.htm%1")3154end3155})31563157table.insert(fingerprints, {3158name = "TP-Link (plain cookie)",3159cpe = "cpe:/o:tp-link:lm_firmware",3160category = "routers",3161paths = {3162{path = "/"}3163},3164target_check = function (host, port, path, response)3165return response.status == 2003166and (http_auth_realm(response) or ""):find("^TP%-LINK")3167and response.body3168and not response.body:find("%spassword%s*=%s*hex_md5")3169end,3170login_combos = {3171{username = "admin", password = "admin"}3172},3173login_check = function (host, port, path, user, pass)3174local auth = base64.enc(user .. ":" .. pass)3175local cookie = "Authorization=" .. url.escape("Basic " .. auth)3176local resp = http_get_simple(host, port, path, {cookies=cookie})3177return resp.status == 2003178and (resp.body or ""):find("%shref%s*=%s*(['\"])[^'\"]-/userRpm/LogoutRpm%.htm%1")3179end3180})31813182table.insert(fingerprints, {3183name = "Comtrend NexusLink-5631",3184category = "routers",3185paths = {3186{path = "/"}3187},3188target_check = function (host, port, path, response)3189return http_auth_realm(response) == "DSL Router"3190end,3191login_combos = {3192{username = "apuser", password = "apuser"},3193{username = "root", password = "12345"}3194},3195login_check = function (host, port, path, user, pass)3196return try_http_auth(host, port, path, user, pass, false)3197end3198})31993200table.insert(fingerprints, {3201name = "iBall Baton",3202category = "routers",3203paths = {3204{path = "/"}3205},3206target_check = function (host, port, path, response)3207return (http_auth_realm(response) or ""):find("^iBall Baton ")3208end,3209login_combos = {3210{username = "admin", password = "admin"},3211{username = "support", password = "support"},3212{username = "user", password = "user"}3213},3214login_check = function (host, port, path, user, pass)3215return try_http_auth(host, port, path, user, pass, false)3216end3217})32183219table.insert(fingerprints, {3220name = "Link-Net LW/LWH router",3221category = "routers",3222paths = {3223{path = "/"}3224},3225target_check = function (host, port, path, response)3226if not (response.status == 3023227and (response.header["location"] or ""):find("/home%.asp$")) then3228return false3229end3230local resp = http_get_simple(host, port,3231url.absolute(path, "home.asp"))3232return resp.status == 2003233and resp.body3234and resp.body:find("LINK-NET", 1, true)3235and resp.body:find("%svendor%s*=%s*(['\"])LINK%-NET%1")3236and resp.body:lower():find("[%s>]wireless router</title>")3237end,3238login_combos = {3239{username = "admin", password = "admin"}3240},3241login_check = function (host, port, path, user, pass)3242return try_http_auth(host, port, url.absolute(path, "internet/wan.asp"),3243user, pass, false)3244end3245})32463247table.insert(fingerprints, {3248name = "Planex Broad Lanner",3249cpe = "cpe:/h:planex:brl-*",3250category = "routers",3251paths = {3252{path = "/"}3253},3254target_check = function (host, port, path, response)3255return response.status == 2003256and response.body3257and response.body:find("Planex Communications", 1, true)3258and get_tag(response.body, "meta", {content="^B%a%a%-04FM%a HTML"})3259and get_tag(response.body, "frame", {src="^top%.htm$"})3260end,3261login_combos = {3262{username = "", password = "password"}3263},3264login_check = function (host, port, path, user, pass)3265return try_http_auth(host, port, url.absolute(path, "top.htm"),3266user, pass, false)3267end3268})32693270table.insert(fingerprints, {3271name = "TrendChip ADSL Modem",3272category = "routers",3273paths = {3274{path = "/"}3275},3276target_check = function (host, port, path, response)3277return http_auth_realm(response) == "ADSL Modem"3278and (response.header["server"] or ""):find("^Boa/%d+%.")3279and get_cookie(response, "SESSIONID", "^%x+$")3280end,3281login_combos = {3282{username = "admin", password = "admin"},3283{username = "admin", password = "1234"},3284{username = ("qwertyuiop"):rep(13):sub(1, 128),3285password = ("1234567890"):rep(13):sub(1, 128)},3286{username = "user3",3287password = ("1234567890"):rep(13):sub(1, 128)},3288},3289login_check = function (host, port, path, user, pass)3290local resp1 = http_get_simple(host, port, path)3291if not resp1.status then return false end3292local auth = {username = user, password = pass}3293local resp2 = http_get_simple(host, port, path,3294{auth=auth, cookies=resp1.cookies})3295return resp2.status == 2003296end3297})32983299table.insert(fingerprints, {3300name = "Westell",3301category = "routers",3302paths = {3303{path = "/"}3304},3305target_check = function (host, port, path, response)3306return response.status == 3023307and (response.header["location"] or ""):find("/htmlV/PasswordChange%.asp$")3308end,3309login_combos = {3310{username = "admin", password = "password"}3311},3312login_check = function (host, port, path, user, pass)3313return try_http_auth(host, port,3314url.absolute(path, "htmlV/PasswordChange.asp"),3315user, pass, true)3316end3317})33183319table.insert(fingerprints, {3320name = "Yamaha RT 10.x",3321cpe = "cpe:/o:yahama:rt*",3322category = "routers",3323paths = {3324{path = "/"}3325},3326target_check = function (host, port, path, response)3327local lurl = response.status == 2003328and get_refresh_url(response.body or "", "/user/index[_%a]*.html$")3329if not lurl then return false end3330local resp = http_get_simple(host, port, lurl)3331return (http_auth_realm(resp) or ""):find("^YAMAHA%-RT ")3332end,3333login_combos = {3334{username = "", password = ""}3335},3336login_check = function (host, port, path, user, pass)3337local resp = http_get_simple(host, port, path)3338local lurl = resp.status == 2003339and get_refresh_url(resp.body or "", "/user/index[_%a]*.html$")3340if not lurl then return false end3341return try_http_auth(host, port, lurl, user, pass, false)3342end3343})33443345table.insert(fingerprints, {3346name = "Yamaha RT 11.x",3347cpe = "cpe:/o:yahama:rt*",3348category = "routers",3349paths = {3350{path = "/"}3351},3352target_check = function (host, port, path, response)3353return (http_auth_realm(response) or ""):find("^YAMAHA%-RT ")3354end,3355login_combos = {3356{username = "", password = ""}3357},3358login_check = function (host, port, path, user, pass)3359return try_http_auth(host, port, path, user, pass, false)3360end3361})33623363table.insert(fingerprints, {3364name = "Yamaha SWX",3365category = "routers",3366paths = {3367{path = "/login.html"}3368},3369target_check = function (host, port, path, response)3370return response.status == 2003371and response.body3372and response.body:find("Yamaha Corporation", 1, true)3373and get_tag(response.body, "form", {action="/goform/authenticate%.json$"})3374and get_tag(response.body, "input", {name="^URL$", value="/dashboard/index%.html$"})3375end,3376login_combos = {3377{username="", password=""}3378},3379login_check = function (host, port, path, user, pass)3380local form = {URL=url.absolute(path, "/dashboard/index.html"),3381USER=user,3382PASS=pass}3383local resp = http_post_simple(host, port,3384url.absolute(path, "goform/authenticate.json"),3385nil, form)3386if not (resp.status == 200 and resp.body) then return false end3387local jstatus, jout = json.parse(resp.body)3388return jstatus and jout.result == "SUCCESS"3389end3390})33913392table.insert(fingerprints, {3393name = "Zoom ADSL X5",3394category = "routers",3395paths = {3396{path = "/"}3397},3398target_check = function (host, port, path, response)3399return response.status == 3013400and (response.header["server"] or ""):find("^Nucleus/%d+%.")3401and (response.header["location"] or ""):find("/hag/pages/home%.htm$")3402end,3403login_combos = {3404{username = "admin", password = "zoomadsl"}3405},3406login_check = function (host, port, path, user, pass)3407return try_http_auth(host, port, url.absolute(path, "hag/pages/home.htm"),3408user, pass, false)3409end3410})34113412table.insert(fingerprints, {3413name = "ZTE F660",3414cpe = "cpe:/h:zte:f660",3415category = "routers",3416paths = {3417{path = "/"}3418},3419target_check = function (host, port, path, response)3420return response.status == 2003421and response.body3422and response.body:find("ZTE", 1, true)3423and response.body:lower():find("<title>f660</title>", 1, true)3424end,3425login_combos = {3426{username = "admin", password = "admin"}3427},3428login_check = function (host, port, path, user, pass)3429local resp1 = http_get_simple(host, port, path)3430if not (resp1.status == 200 and resp1.body) then return false end3431local ltoken = resp1.body:match("%WgetObj%(%s*['\"]Frm_Logintoken['\"]%s*%)%.value%s*=%s*['\"](%d+)['\"]%s*;")3432if not ltoken then return false end3433local form = {frashnum="",3434action="login",3435Frm_Logintoken=ltoken,3436Username=user,3437Password=pass}3438local resp2 = http_post_simple(host, port, path, {cookies=resp1.cookies}, form)3439return resp2.status == 3023440and (resp2.header["location"] or ""):find("/start%.ghtml$")3441end3442})34433444table.insert(fingerprints, {3445name = "ZTE ZXV10 I5xx",3446category = "routers",3447paths = {3448{path = "/"}3449},3450target_check = function (host, port, path, response)3451return response.status == 2003452and response.body3453and response.body:find("ZTE", 1, true)3454and get_tag(response.body, "form", {name="^flogin$", action="^getpage%.gch%?pid=1001$"})3455end,3456login_combos = {3457{username = "admin", password = "admin"}3458},3459login_check = function (host, port, path, user, pass)3460local resp1 = http_get_simple(host, port, path)3461if not (resp1.status == 200 and resp1.body) then return false end3462local stime = resp1.body:match("%Wdocument%.getElementById%(%s*['\"]submittime['\"]%s*%)%.value%s*=%s*['\"](%d+)['\"]%s*;")3463if not stime then return false end3464local form = {submenu=-1,3465menuPos=-1,3466nosubmenu=1,3467nextpage="welcome.gch",3468nextgch="",3469nextjs="welcome.js",3470title="Come In to Configuration",3471path="Welcome",3472submittime=stime,3473tUsername=user,3474tPassword=pass}3475local resp2 = http_post_simple(host, port,3476url.absolute(path, "getpage.gch?pid=1001"),3477nil, form)3478return resp2.status == 2003479and (resp2.body or ""):lower():find("<title>[^<]-configuration")3480end3481})34823483table.insert(fingerprints, {3484name = "ZTE ZXV10 W300",3485cpe = "cpe:/o:zte:zxv10_w300_firmware",3486category = "routers",3487paths = {3488{path = "/"}3489},3490target_check = function (host, port, path, response)3491return (http_auth_realm(response) or ""):find("^ZXV10 W300$")3492end,3493login_combos = {3494{username = "admin", password = "admin"}3495},3496login_check = function (host, port, path, user, pass)3497return try_http_auth(host, port, path, user, pass, false)3498end3499})35003501table.insert(fingerprints, {3502name = "3Com OfficeConnect VPN Firewall",3503cpe = "cpe:/h:3com:3cr870-95",3504category = "routers",3505paths = {3506{path = "/"}3507},3508target_check = function (host, port, path, response)3509return response.status == 2003510and response.body3511and response.body:find("3Com", 1, true)3512and response.body:find("%Wtop%.document%.location%s*=%s*(['\"])[^'\"]-/default%.htm%1")3513and get_tag(response.body, "meta", {["http-equiv"]="^3cnumber$"})3514end,3515login_combos = {3516{username = "", password = "admin"}3517},3518login_check = function (host, port, path, user, pass)3519local resp = http_post_simple(host, port,3520url.absolute(path, "cgi-bin/admin?page=x"),3521nil, {AdminPassword=pass,next=10,page="x"})3522return resp.status == 2003523and get_tag(resp.body or "", "input", {name="^tk$"})3524end3525})35263527table.insert(fingerprints, {3528name = "Corega",3529cpe = "cpe:/o:corega:cg-*",3530category = "routers",3531paths = {3532{path = "/"}3533},3534target_check = function (host, port, path, response)3535local realm = http_auth_realm(response) or ""3536return realm:find("^CG%-%u*BAR")3537or realm:find("^corega BAR ")3538end,3539login_combos = {3540{username = "root", password = ""}3541},3542login_check = function (host, port, path, user, pass)3543return try_http_auth(host, port, path, user, pass, false)3544end3545})35463547table.insert(fingerprints, {3548name = "Netgear ProSafe Firewall FVS318",3549cpe = "cpe:/h:netgear:fvs318",3550category = "routers",3551paths = {3552{path = "/"}3553},3554target_check = function (host, port, path, response)3555return response.status == 2003556and response.header["server"] == "Netgear"3557and response.body3558and get_tag(response.body, "frame", {src="^top%.html$"})3559end,3560login_combos = {3561{username = "admin", password = "password"}3562},3563login_check = function (host, port, path, user, pass)3564return try_http_auth(host, port, url.absolute(path, "top.html"),3565user, pass, false)3566end3567})35683569table.insert(fingerprints, {3570name = "Netgear Router (legacy)",3571category = "routers",3572paths = {3573{path = "/"}3574},3575target_check = function (host, port, path, response)3576return (http_auth_realm(response) or ""):find("^R[PT][13]1[14]$")3577end,3578login_combos = {3579{username = "admin", password = "1234"}3580},3581login_check = function (host, port, path, user, pass)3582return try_http_auth(host, port, path, user, pass, false)3583end3584})35853586table.insert(fingerprints, {3587name = "Netgear Router",3588category = "routers",3589paths = {3590{path = "/"}3591},3592target_check = function (host, port, path, response)3593local realm = http_auth_realm(response) or ""3594return realm:find("^NETGEAR %u+%d+[%w-]+%s*$")3595or realm == "Netgear"3596or realm == "FR114P"3597end,3598login_combos = {3599{username = "admin", password = "password"}3600},3601login_check = function (host, port, path, user, pass)3602return try_http_auth(host, port, path, user, pass, false)3603end3604})36053606table.insert(fingerprints, {3607name = "Netgear ProSafe Plus Switch",3608cpe = "cpe:/h:netgear:gs108*",3609category = "routers",3610paths = {3611{path = "/"}3612},3613target_check = function (host, port, path, response)3614return response.status == 2003615and response.body3616and response.body:find("loginTData", 1, true)3617and response.body:lower():find("<title>netgear ", 1, true)3618end,3619login_combos = {3620{username = "", password = "password"}3621},3622login_check = function (host, port, path, user, pass)3623local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),3624nil, {password=pass})3625return resp.status == 200 and get_cookie(resp, "GS108SID", ".")3626end3627})36283629table.insert(fingerprints, {3630name = "Netgear Smart Switch",3631category = "routers",3632paths = {3633{path = "/"}3634},3635target_check = function (host, port, path, response)3636return response.status == 2003637and response.body3638and response.body:find("document.forms[0].pwd.focus();", 1, true)3639and response.body:lower():find("%saction%s*=%s*(['\"])[^'\"]-/base/%w+_login%.html%1")3640and response.body:lower():find("<title>netgear ", 1, true)3641end,3642login_combos = {3643{username = "", password = "password"}3644},3645login_check = function (host, port, path, user, pass)3646local resp1 = http_get_simple(host, port, path)3647if not (resp1.status == 200 and resp1.body) then return false end3648local lurl = resp1.body:match("['\"]([^'\"]-/base/%w+_login%.html)")3649if not lurl then return false end3650local button = lurl:find("main_login", 1, true) and "" or "_button"3651local form = {pwd=pass,3652["login" .. button .. ".x"]=0,3653["login" .. button .. ".y"]=0,3654err_flag=0,3655err_msg=""}3656local resp2 = http_post_simple(host, port, lurl, nil, form)3657return resp2.status == 200 and get_cookie(resp2, "SID", ".")3658end3659})36603661table.insert(fingerprints, {3662name = "Netgear Intelligent Edge",3663category = "routers",3664paths = {3665{path = "/"}3666},3667target_check = function (host, port, path, response)3668return response.status == 2003669and response.body3670and response.body:find("document.forms[0].uname.focus();", 1, true)3671and response.body:lower():find("%saction%s*=%s*(['\"])[^'\"]-/base/%w+_login%.html%1")3672and response.body:lower():find("<title>netgear ", 1, true)3673end,3674login_combos = {3675{username = "admin", password = ""}3676},3677login_check = function (host, port, path, user, pass)3678local resp1 = http_get_simple(host, port, path)3679if not (resp1.status == 200 and resp1.body) then return false end3680local lurl = resp1.body:match("['\"]([^'\"]-/base/%w+_login%.html)")3681if not lurl then return false end3682local form = {uname=user,3683pwd=pass,3684["login_button.x"]=0,3685["login_button.y"]=0,3686err_flag=0,3687err_msg="",3688submt=""}3689local resp2 = http_post_simple(host, port, lurl, nil, form)3690return resp2.status == 200 and get_cookie(resp2, "SID", ".")3691end3692})36933694table.insert(fingerprints, {3695name = "Netgear Gigabit Enterprise Switch",3696category = "routers",3697paths = {3698{path = "/"}3699},3700target_check = function (host, port, path, response)3701return response.status == 2003702and response.body3703and response.body:find("/base/web_main.html", 1, true)3704and response.body:lower():find("<title>netgear system login</title>", 1, true)3705end,3706login_combos = {3707{username = "admin", password = ""}3708},3709login_check = function (host, port, path, user, pass)3710return try_http_auth(host, port, url.absolute(path, "base/web_main.html"),3711user, pass, false)3712end3713})37143715table.insert(fingerprints, {3716name = "PLANET Smart Gigabit Switch",3717category = "routers",3718paths = {3719{path = "/"}3720},3721target_check = function (host, port, path, response)3722return response.status == 2003723and response.body3724and response.body:find(">Welcome to PLANET ", 1, true)3725and get_tag(response.body, "form", {action="/pass$"})3726end,3727login_combos = {3728{username = "", password = "admin"}3729},3730login_check = function (host, port, path, user, pass)3731local form = {password=pass,3732x=0,3733y=0}3734local resp = http_post_simple(host, port, url.absolute(path, "pass"),3735nil, form)3736if not (resp.status == 2003737and get_tag(resp.body or "", "frame", {src="/planet%.htm$"})) then3738return false3739end3740http_get_simple(host, port, url.absolute(path, "logout?submit=Apply"))3741return true3742end3743})37443745table.insert(fingerprints, {3746name = "PLANET Managed Switch (var.1)",3747category = "routers",3748paths = {3749{path = "/"}3750},3751target_check = function (host, port, path, response)3752local server = response.header["server"] or ""3753return (http_auth_realm(response) or ""):find("^Loging?$")3754and (server == "Vitesse Web Server"3755or server == "WebServer")3756and response.body3757and response.body:find(">Authorization required to access this URL.<", 1, true)3758end,3759login_combos = {3760{username = "admin", password = "admin"}3761},3762login_check = function (host, port, path, user, pass)3763return try_http_auth(host, port, path, user, pass, false)3764end3765})37663767table.insert(fingerprints, {3768name = "PLANET Managed Switch (var.2)",3769category = "routers",3770paths = {3771{path = "/"}3772},3773target_check = function (host, port, path, response)3774local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")3775if not (response.status == 3023776and loc:find("/default%.html$")) then3777return false3778end3779local resp = http_get_simple(host, port, loc)3780return resp.status == 2003781and resp.body3782and resp.body:find("1366X768", 1, true)3783and resp.body:lower():find("<title>switch web management (1366x768 is recommended)</title>", 1, true)3784and get_tag(resp.body, "form", {action="/goform/WebSetting%.html$"})3785end,3786login_combos = {3787{username = "admin", password = "admin"}3788},3789login_check = function (host, port, path, user, pass)3790local form = {name=user,3791pwd=pass,3792app="login"}3793local resp = http_post_simple(host, port,3794url.absolute(path, "goform/WebSetting.html"),3795nil, form)3796return resp.status == 2033797and resp.body3798and get_tag(resp.body, "frame", {src="/frontboard%.html$"})3799end3800})38013802table.insert(fingerprints, {3803name = "PLANET Managed Switch (var.3)",3804category = "routers",3805paths = {3806{path = "/"}3807},3808target_check = function (host, port, path, response)3809return response.status == 2003810and response.body3811and response.body:find("/cgi-bin/get.cgi?cmd=portlink&lg=", 1, true)3812and get_tag(response.body, "frame", {src="/cgi%-bin/get%.cgi%?cmd=portlink&lg=%w+$"})3813and response.body:lower():find("<title>managed switch</title>", 1, true)3814end,3815login_combos = {3816{username = "admin", password = "admin"}3817},3818login_check = function (host, port, path, user, pass)3819return try_http_auth(host, port,3820url.absolute(path, "cgi-bin/get.cgi?cmd=portlink&lg=en"),3821user, pass, false)3822end3823})38243825table.insert(fingerprints, {3826name = "PLANET Wireless Router",3827category = "routers",3828paths = {3829{path = "/"}3830},3831target_check = function (host, port, path, response)3832return response.status == 2003833and response.body3834and response.body:find("PLANET Technology", 1, true)3835and response.body:find("(['\"])dataCenter%.js%1")3836and response.body:find("%Wauth_action%s*:%s*(['\"])login%1")3837end,3838login_combos = {3839{username = "admin", password = "admin"},3840{username = "admin", password = ""}3841},3842login_check = function (host, port, path, user, pass)3843local form = {username=user,3844password=base64.enc(pass:gsub("%s", "@")),3845getPage="index.html",3846action="Apply",3847auth_action="login",3848mode="AUTH",3849_flg=0}3850local resp = http_post_simple(host, port,3851url.absolute(path, "postCenter.js"),3852nil, form)3853if not (resp.status == 200 and resp.body) then return false end3854local jstatus, jout = json.parse(resp.body:gsub("'", "\""))3855if not (jstatus and jout.result == "0") then return false end3856http_get_simple(host, port, url.absolute(path, "login.html"))3857return true3858end3859})38603861table.insert(fingerprints, {3862name = "Rubytech chassis",3863category = "routers",3864paths = {3865{path = "/"}3866},3867target_check = function (host, port, path, response)3868return response.status == 2003869and response.body3870and response.body:find("fake_server.html", 1, true)3871and get_tag(response.body, "form", {action="^fake_server%.html$"})3872and get_tag(response.body, "input", {name="^textpass$"})3873end,3874login_combos = {3875{username = "admin", password = "admin"}3876},3877login_check = function (host, port, path, user, pass)3878local form = stdnse.output_table()3879form.textuser=user3880form.textpass=pass3881form.Submit="Login"3882form.randstr=math.random()3883local resp = http_post_simple(host, port,3884url.absolute(path, "fake_server.html"),3885nil, form)3886return resp.status == 2003887and (resp.body or ""):find("%Wlocation%.href%s*=%s*['\"][^'\"]-/main_frame%.html%?")3888end3889})38903891table.insert(fingerprints, {3892name = "ZyXEL Prestige",3893category = "routers",3894paths = {3895{path = "/"}3896},3897target_check = function (host, port, path, response)3898local realm = http_auth_realm(response) or ""3899return realm:find("^Prestige ")3900or realm:find("^P[%u-]*645ME")3901end,3902login_combos = {3903{username = "admin", password = "1234"}3904},3905login_check = function (host, port, path, user, pass)3906return try_http_auth(host, port, path, user, pass, false)3907end3908})39093910table.insert(fingerprints, {3911name = "ZyXEL ZyWALL (var.1)",3912category = "routers",3913paths = {3914{path = "/"}3915},3916target_check = function (host, port, path, response)3917return have_openssl3918and response.status == 2003919and (response.header["server"] or ""):find("^RomPager/%d+%.")3920and response.body3921and response.body:find("rpAuth.html", 1, true)3922and response.body:find("%WchangeURL%(%s*(['\"])[^'\"]-%f[%w]rpAuth%.html%1%s*%)")3923end,3924login_combos = {3925{username = "", password = "1234"}3926},3927login_check = function (host, port, path, user, pass)3928local form = {LoginPassword="ZyXEL ZyWALL Series",3929hiddenPassword=stdnse.tohex(openssl.md5(pass)),3930Prestige_Login="Login"}3931local resp = http_post_simple(host, port,3932url.absolute(path, "Forms/rpAuth_1"),3933nil, form)3934return resp.status == 3033935and (resp.header["location"] or ""):find("/passWarning%.html$")3936end3937})39383939table.insert(fingerprints, {3940name = "ZyXEL ZyWALL (var.2)",3941category = "routers",3942paths = {3943{path = "/"}3944},3945target_check = function (host, port, path, response)3946return response.status == 2003947and response.body3948and response.body:find("ZyWALL", 1, true)3949and response.body:lower():find("<title>zywall %w")3950and get_tag(response.body, "input", {name="^pwd_r$"})3951end,3952login_combos = {3953{username = "admin", password = "1234"}3954},3955login_check = function (host, port, path, user, pass)3956local form = {username=user,3957pwd=pass,3958pwd_r="",3959password=pass}3960local resp = http_post_simple(host, port, path, nil, form)3961return resp.status == 3023962and resp.header["location"] == "ext-js/web-pages/login/chgpw.html"3963and get_cookie(resp, "authtok", "^[%w+-]+$")3964end3965})39663967table.insert(fingerprints, {3968name = "Adtran NetVanta",3969cpe = "cpe:/h:adtran:netvanta_*",3970category = "routers",3971paths = {3972{path = "/"}3973},3974target_check = function (host, port, path, response)3975return (http_auth_realm(response) or ""):find("^NetVanta %d+%f[ \0]")3976end,3977login_combos = {3978{username = "admin", password = "password"}3979},3980login_check = function (host, port, path, user, pass)3981return try_http_auth(host, port, path, user, pass, false)3982end3983})39843985table.insert(fingerprints, {3986name = "Siemens Gigaset SX762/763",3987cpe = "cpe:/h:siemens:gigaset_sx76*",3988category = "routers",3989paths = {3990{path = "/"}3991},3992target_check = function (host, port, path, response)3993return response.status == 3033994and (response.header["server"] or ""):find("^SiemensGigaset%-Server/%d+%.")3995and (response.header["location"] or ""):find("/UE/welcome_login%.html$")3996end,3997login_combos = {3998{username = "", password = "admin"}3999},4000login_check = function (host, port, path, user, pass)4001local form = {form_submission_type="login",4002form_submission_parameter="",4003current_page="welcome_login.html",4004next_page="home_security.html",4005i=1,4006admin_role_name="administrator",4007operator_role_name="operator",4008subscriber_role_name="subscriber",4009choose_role=0,4010your_password=pass,4011Login="OK"}4012local resp = http_post_simple(host, port,4013url.absolute(path, "UE/ProcessForm"),4014nil, form)4015return resp.status == 3034016and (resp.header["location"] or ""):find("/UE/home_security%.html$")4017end4018})40194020table.insert(fingerprints, {4021name = "Siemens Scalance X-200",4022cpe = "cpe:/o:siemens:scalance_x-200_series_firmware",4023category = "routers",4024paths = {4025{path = "/"}4026},4027target_check = function (host, port, path, response)4028return have_openssl4029and response.status == 2004030and get_cookie(response, "siemens_ad_session", "^%x+")4031and response.body4032and response.body:find(" SCALANCE X ", 1, true)4033and get_tag(response.body, "input", {name="^nonceA$"})4034end,4035login_combos = {4036{username = "admin", password = "admin"},4037{username = "user", password = "user"}4038},4039login_check = function (host, port, path, user, pass)4040local resp1 = http_get_simple(host, port, path)4041if not (resp1.status == 200 and resp1.body) then return false end4042local nonce = get_tag(resp1.body, "input", {name="^nonceA$", value="^%x+$"})4043if not nonce then return false end4044local auth = stdnse.tohex(openssl.md5(table.concat({user, pass, nonce.value}, ":")))4045local resp2 = http_post_simple(host, port, path, {cookies=resp1.cookies},4046{encoded=user..":"..auth, nonceA=nonce.value})4047return resp2.status == 2004048and (resp2.body or ""):find("%Wlocation%.href%s*=%s*(['\"])index1%.html%1")4049end4050})40514052table.insert(fingerprints, {4053name = "Siemens Scalance M873/M875",4054category = "routers",4055paths = {4056{path = "/"}4057},4058target_check = function (host, port, path, response)4059return (http_auth_realm(response) or ""):find("^SCALANCE M%-?87%d%f[%D]")4060end,4061login_combos = {4062{username = "admin", password = "scalance"}4063},4064login_check = function (host, port, path, user, pass)4065return try_http_auth(host, port, path, user, pass, true)4066end4067})40684069table.insert(fingerprints, {4070name = "Siemens RUGGEDCOM WIN",4071cpe = "cpe:/h:siemens:ruggedcom_win*",4072category = "routers",4073paths = {4074{path = "/"}4075},4076target_check = function (host, port, path, response)4077return http_auth_realm(response) == ""4078and get_cookie(response, "sessionId", "^%d+$")4079and (response.header["server"] or ""):find("^BS/%d+%.")4080end,4081login_combos = {4082{username = "admin", password = "generic"}4083},4084login_check = function (host, port, path, user, pass)4085local resp1 = http_get_simple(host, port, path)4086if not get_cookie(resp1, "sessionId", "^%d+$") then return false end4087local resp2 = http_get_simple(host, port, path,4088{cookies=resp1.cookies,4089auth={username=user,password=pass}})4090return resp2.status == 2004091and get_refresh_url(resp2.body, "/0/m%d+$")4092end4093})40944095table.insert(fingerprints, {4096name = "Siemens RUGGEDCOM ROS (var.1)",4097cpe = "cpe:/o:siemens:ruggedcom_rugged_operating_system",4098category = "routers",4099paths = {4100{path = "/"}4101},4102target_check = function (host, port, path, response)4103local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")4104if not (response.status == 3024105and loc:find("/InitialPage%.asp$")) then4106return false4107end4108local resp = http_get_simple(host, port, loc)4109return resp.status == 2004110and resp.body4111and resp.body:find("RuggedSwitch Operating System", 1, true)4112and get_tag(resp.body, "a", {href="^Menu%.asp%?UID=%d+$"})4113end,4114login_combos = {4115{username = "admin", password = "admin"},4116{username = "operator", password = "operator"},4117{username = "guest", password = "guest"}4118},4119login_check = function (host, port, path, user, pass)4120local resp1 = http_get_simple(host, port,4121url.absolute(path, "InitialPage.asp"))4122if not (resp1.status == 200 and resp1.body) then return false end4123local llink = get_tag(resp1.body, "a", {href="^Menu%.asp%?UID=%d+$"})4124if not llink then return false end4125local lurl = url.absolute(path, llink.href)4126local resp2 = http_get_simple(host, port, lurl)4127if resp2.status ~= 401 then return false end4128return try_http_auth(host, port, lurl, user, pass, false)4129end4130})41314132table.insert(fingerprints, {4133name = "Siemens RUGGEDCOM ROS (var.2)",4134cpe = "cpe:/o:siemens:ruggedcom_rugged_operating_system",4135category = "routers",4136paths = {4137{path = "/"}4138},4139target_check = function (host, port, path, response)4140local loc = (response.header["location"] or ""):gsub("^https?://[^/]*", "")4141if not (response.status == 3024142and loc:find("/InitialPage%.asp$")) then4143return false4144end4145local resp = http_get_simple(host, port, loc)4146return resp.status == 2004147and resp.body4148and resp.body:find("goahead.gif", 1, true)4149and resp.body:find("LogIn", 1, true)4150and get_tag(resp.body, "form", {action="/goform/postLoginData%?UID=%d+$"})4151end,4152login_combos = {4153{username = "admin", password = "admin"},4154{username = "operator", password = "operator"},4155{username = "guest", password = "guest"}4156},4157login_check = function (host, port, path, user, pass)4158local resp1 = http_get_simple(host, port,4159url.absolute(path, "InitialPage.asp"))4160if not (resp1.status == 200 and resp1.body) then return false end4161local frm = get_tag(resp1.body, "form", {action="/goform/postLoginData%?UID=%d+$"})4162if not frm then return false end4163local form = {User=user,4164Password=pass,4165choice="LogIn"}4166local resp2 = http_post_simple(host, port, url.absolute(path, frm.action),4167nil, form)4168return (resp2.status == 203 or resp2.status == 200)4169and get_tag(resp2.body or "", "a", {href="/logout%.asp%?uid=%d+$"})4170end4171})41724173table.insert(fingerprints, {4174name = "Siemens RUGGEDCOM ROX",4175category = "routers",4176paths = {4177{path = "/login.html"}4178},4179target_check = function (host, port, path, response)4180return response.status == 2004181and response.body4182and response.body:find("/skins/macified/styles/master.css", 1, true)4183and response.body:find("confdLogin();", 1, true)4184and get_tag(response.body, "a", {onclick="^confdlogin%(%);"})4185and get_tag(response.body, "body", {onload="^loadbannercontent%(%);"})4186end,4187login_combos = {4188{username = "admin", password = "admin"},4189{username = "oper", password = "oper"},4190{username = "guest", password = "guest"}4191},4192login_check = function (host, port, path, user, pass)4193local resp = http_post_simple(host, port, url.absolute(path, "confd/login"),4194nil, {user=user,passwd=pass})4195return resp.status == 2004196and (resp.body or ""):find("^(['\"])sess%d+%1$")4197end4198})41994200table.insert(fingerprints, {4201name = "VideoFlow DVP",4202category = "routers",4203paths = {4204{path = "/login.html"}4205},4206target_check = function (host, port, path, response)4207return response.status == 2004208and response.body4209and response.body:find("/skins/macified/styles/master.css", 1, true)4210and response.body:find("confdLogin();", 1, true)4211and get_tag(response.body, "a", {onclick="^confdlogin%(%);"})4212and get_tag(response.body, "body", {onload="^document%.form%.username%.focus%(%);"})4213end,4214login_combos = {4215{username = "root", password = "videoflow"},4216{username = "admin", password = "admin"},4217{username = "oper", password = "oper"},4218{username = "private", password = "private"},4219{username = "public", password = "public"},4220{username = "devel", password = "leved"}4221},4222login_check = function (host, port, path, user, pass)4223local resp = http_post_simple(host, port, url.absolute(path, "confd/login"),4224nil, {user=user,passwd=pass})4225return resp.status == 2004226and (resp.body or ""):find("^(['\"])sess%d+%1$")4227end4228})42294230table.insert(fingerprints, {4231name = "Foxconn Femtocell",4232category = "routers",4233paths = {4234{path = "/"}4235},4236target_check = function (host, port, path, response)4237return response.status == 2004238and response.body4239and response.body:find("login.cgi", 1, true)4240and get_tag(response.body, "form", {action="^cgi%-bin/login%.cgi$"})4241and response.body:lower():find("<title>femtocell management system</title>", 1, true)4242end,4243login_combos = {4244{username = "admin", password = "admin"}4245},4246login_check = function (host, port, path, user, pass)4247local lurl = ("cgi-bin/login.cgi?username=%s&password=%s&Submit=Login"):format(4248url.escape(user), url.escape(pass))4249local resp = http_get_simple(host, port, url.absolute(path, lurl))4250return resp.status == 2004251and get_cookie(resp, "sessionID", ".")4252and (resp.body or ""):find("%Wwindow%.location%s*=%s*(['\"])mainFrame%.cgi%1")4253end4254})42554256table.insert(fingerprints, {4257name = "Datum Systems SnIP",4258cpe = "cpe:/o:datumsystems:snip",4259category = "routers",4260paths = {4261{path = "/"}4262},4263target_check = function (host, port, path, response)4264return (http_auth_realm(response) or ""):find("^SnIP%d+$")4265end,4266login_combos = {4267{username = "admin", password = "admin"}4268},4269login_check = function (host, port, path, user, pass)4270return try_http_auth(host, port, path, user, pass, false)4271end4272})42734274table.insert(fingerprints, {4275name = "Option GlobeSurfer II",4276category = "routers",4277paths = {4278{path = "/"}4279},4280target_check = function (host, port, path, response)4281return have_openssl4282and response.status == 2004283and response.body4284and response.body:find("GlobeSurfer II", 1, true)4285and response.body:find("%Wf%.action%s*=%s*(['\"])[^'\"]-/cache/%d+/upgrade%.cgi%1")4286and get_cookie(response, "session_id", "^%d+$")4287end,4288login_combos = {4289{username = "admin", password = "admin"},4290{username = "admin", password = ""}4291},4292login_check = function (host, port, path, user, pass)4293local resp1 = http_get_simple(host, port, path)4294if not (resp1.status == 200 and resp1.body) then return false end4295local page2 = get_tag(resp1.body, "input", {name="^active_page$", value="^%d+$"})4296local url2 = resp1.body:match(".*%Wfunction%s+mimic_button%s*%([^}]-%Wcase%s+0%s*:[^}]-%Wf%.action%s*=%s*['\"]([^'\"]-/cache/%d+/index%.cgi)['\"]")4297if not (page2 and url2) then return false end4298local form2 = {active_page=page2.value,4299prev_page=0,4300page_title="Connection status",4301nav_stack_0=page2.value,4302mimic_button_field="sidebar: sidebar_logout..",4303button_value="",4304transaction_id=0}4305local resp2 = http_post_simple(host, port, url2,4306{cookies=resp1.cookies}, form2)4307if not (resp2.status == 200 and resp2.body) then return false end4308local authkey = get_tag(resp2.body, "input", {name="^auth_key$", value="^%d+$"})4309local transid = get_tag(resp2.body, "input", {name="^transaction_id$", value="^%d+$"})4310local page3 = get_tag(resp2.body, "input", {name="^active_page$", value="^%d+$"})4311local url3 = resp2.body:match(".*%Wfunction%s+mimic_button%s*%([^}]-%Wcase%s+0%s*:[^}]-%Wf%.action%s*=%s*['\"]([^'\"]-/cache/(%d+)/index%.cgi)['\"]")4312if not (authkey and transid and page3 and url3) then return false end4313local form3 = {active_page=page3.value,4314prev_page=page2.value,4315page_title="Login",4316nav_stack_0=page3.value,4317["nav_" .. page3.value .. "_button_value"]="sidebar_logout",4318mimic_button_field="submit_button_login_submit: ..",4319button_value="sidebar_logout",4320transaction_id=transid.value,4321lang=0,4322user_name=user,4323["password_" .. get_cookie(resp2, "session_id")]="",4324md5_pass=stdnse.tohex(openssl.md5(pass .. authkey.value)),4325auth_key=authkey.value}4326local resp3 = http_post_simple(host, port, url3,4327{cookies=resp2.cookies}, form3)4328return resp3.status == 2004329and (resp3.body or ""):find("sidebar%5Fadvanced..", 1, true)4330end4331})43324333table.insert(fingerprints, {4334name = "Option GlobeSurfer III",4335category = "routers",4336paths = {4337{path = "/"}4338},4339target_check = function (host, port, path, response)4340return have_openssl4341and response.status == 2004342and response.body4343and response.body:find("md5_pass", 1, true)4344and response.body:lower():find("<title>[^<]-globesurfer%W")4345and get_cookie(response, "rg_cookie_session_id", "^%d+$")4346end,4347login_combos = {4348{username = "admin", password = "admin"},4349{username = "admin", password = ""}4350},4351login_check = function (host, port, path, user, pass)4352local resp1 = http_get_simple(host, port, path)4353if not (resp1.status == 200 and resp1.body) then return false end4354local authkey = get_tag(resp1.body, "input", {name="^auth_key$", value="^%d+$"})4355if not authkey then return false end4356local form = {active_page="page_login",4357prev_page="",4358page_title="Login",4359mimic_button_field="submit_button_login_submit: ..",4360button_value="",4361strip_page_top=0,4362page_title_text="Login",4363page_icon_number=30,4364defval_lang=0,4365defval_username="",4366md5_pass=stdnse.tohex(openssl.md5(pass .. authkey.value)),4367auth_key=authkey.value,4368lang=0,4369username=user,4370["password_" .. get_cookie(resp1, "rg_cookie_session_id")]=""}4371local resp2 = http_post_simple(host, port, url.absolute(path, "index.cgi"),4372{cookies=resp1.cookies}, form)4373return resp2.status == 3024374and (resp2.header["location"] or ""):find("active%5fpage=page%5fhome", 1, true)4375end4376})43774378table.insert(fingerprints, {4379name = "Digi TransPort",4380category = "routers",4381paths = {4382{path = "/login.asp"}4383},4384target_check = function (host, port, path, response)4385return response.status == 2004386and response.body4387and response.body:find("TransPort WR", 1, true)4388and response.body:lower():find("<title>transport wr", 1, true)4389and get_cookie(response, "SID", "^%x+$")4390end,4391login_combos = {4392{username = "username", password = "password"}4393},4394login_check = function (host, port, path, user, pass)4395local resp1 = http_get_simple(host, port, path)4396if not (resp1.status == 200 and resp1.cookies) then return false end4397local form = {username=user,4398password=pass,4399login="LOG IN"}4400local resp2 = http_post_simple(host, port, path,4401{cookies=resp1.cookies}, form)4402return resp2.status == 3024403and (resp2.header["location"] or ""):find("/default%.asp$")4404end4405})44064407table.insert(fingerprints, {4408name = "Sea Tel MXP",4409category = "routers",4410paths = {4411{path = "/"}4412},4413target_check = function (host, port, path, response)4414return response.status == 2004415and response.header["server"] == "Micro Digital Web Server"4416and response.body4417and response.body:find("MXP", 1, true)4418and response.body:lower():find("%Wwindow%.location%.href%s*=%s*(['\"])login%.html%1")4419end,4420login_combos = {4421{username = "Dealer", password = "seatel1"},4422{username = "SysAdmin", password = "seatel2"},4423{username = "User", password = "seatel3"}4424},4425login_check = function (host, port, path, user, pass)4426local form = {uId=user,4427uPwd=pass,4428uLoginMode="in",4429callConter=0}4430local resp = http_post_simple(host, port,4431url.absolute(path, "cgi-bin/userValidate"),4432nil, form)4433return resp.status == 2004434and (resp.body or ""):find("^%s*%^true%s*$")4435end4436})44374438table.insert(fingerprints, {4439name = "Thrane & Thrane Sailor 900 VSAT (var.1)",4440category = "routers",4441paths = {4442{path = "/"}4443},4444target_check = function (host, port, path, response)4445return response.status == 2004446and get_cookie(response, "tt_adm", "^%l+$")4447and response.body4448and get_tag(response.body, "form", {action="%?pageid=%w+$"})4449and get_tag(response.body, "input", {name="^pass_login$"})4450end,4451login_combos = {4452{username = "admin", password = "1234"}4453},4454login_check = function (host, port, path, user, pass)4455local resp1 = http_get_simple(host, port, path)4456if not (resp1.status == 200 and resp1.body) then return false end4457local frm = get_tag(resp1.body, "form", {action="%?pageid=%w+$"})4458if not frm then return false end4459local resp2 = http_post_simple(host, port, url.absolute(path, frm.action),4460nil, {user_login=user,pass_login=pass})4461return resp2.status == 2004462and url.unescape(get_cookie(resp2, "tt_adm", "%%3[Aa]") or ""):find(":" .. user .. ":", 1, true)4463end4464})44654466table.insert(fingerprints, {4467name = "Thrane & Thrane Sailor 900 VSAT (var.2)",4468category = "routers",4469paths = {4470{path = "/"}4471},4472target_check = function (host, port, path, response)4473return response.status == 2004474and get_cookie(response, "tt_adm", "^%l+$")4475and response.body4476and response.body:find("900 VSAT", 1, true)4477and get_tag(response.body, "a", {href="%?pageid=administration$"})4478end,4479login_combos = {4480{username = "admin", password = "1234"}4481},4482login_check = function (host, port, path, user, pass)4483local resp1 = http_get_simple(host, port, path)4484if not (resp1.status == 200 and resp1.body) then return false end4485local llink = get_tag(resp1.body, "a", {href="%?pageid=administration$"})4486if not llink then return false end4487local resp2 = http_post_simple(host, port, url.absolute(path, llink.href),4488nil, {user_login=user,pass_login=pass})4489return resp2.status == 2004490and url.unescape(get_cookie(resp2, "tt_adm", "%%3[Aa]") or ""):find(":" .. user .. ":", 1, true)4491end4492})44934494table.insert(fingerprints, {4495name = "Ubiquiti AirOS",4496category = "routers",4497paths = {4498{path = "/"}4499},4500target_check = function (host, port, path, response)4501if not (response.status == 3024502and (response.header["location"] or ""):find("/cookiechecker?uri=/", 1, true)) then4503return false4504end4505for _, ck in ipairs(response.cookies or {}) do4506if ck.name == "AIROS_SESSIONID" or ck.name:find("^AIROS_%x+$") then4507return ck.value:find("^%x+$")4508end4509end4510return false4511end,4512login_combos = {4513{username = "ubnt", password = "ubnt"}4514},4515login_check = function (host, port, path, user, pass)4516local resp = http_post_multipart(host, port,4517url.absolute(path, "login.cgi"), nil,4518{uri=path, username=user, password=pass})4519return resp.status == 3024520and resp.header["location"] == path4521end4522})45234524table.insert(fingerprints, {4525name = "Ubiquiti EdgeOS",4526category = "routers",4527paths = {4528{path = "/"}4529},4530target_check = function (host, port, path, response)4531return response.status == 2004532and response.body4533and response.body:find(">EdgeOS<", 1, true)4534and response.body:find("%WEDGE%.Config%s*=")4535and response.body:lower():find("<title>edgeos</title>")4536end,4537login_combos = {4538{username = "ubnt", password = "ubnt"}4539},4540login_check = function (host, port, path, user, pass)4541local resp = http_post_simple(host, port, path, nil,4542{username=user,password=pass})4543return (resp.status == 302 or resp.status == 303)4544and (resp.header["location"] or ""):sub(-#path) == path4545and get_cookie(resp, "PHPSESSID", "^%w+$")4546end4547})45484549table.insert(fingerprints, {4550name = "Ubiquiti EdgeSwitch",4551category = "routers",4552paths = {4553{path = "/"}4554},4555target_check = function (host, port, path, response)4556return response.status == 2004557and response.body4558and response.body:find(">Ubiquiti EdgeSwitch<", 1, true)4559and response.body:lower():find("<title>ubiquiti edgeswitch</title>")4560and get_tag(response.body, "script", {src="/static/scripts/bundle%-%x+%.js$"})4561end,4562login_combos = {4563{username = "ubnt", password = "ubnt"}4564},4565login_check = function (host, port, path, user, pass)4566local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=path})),4567["Content-Type"]="application/json",4568["Accept"]="application/json, text/plain, */*"}4569local jin = {username=user, password=pass}4570json.make_object(jin)4571local resp = http_post_simple(host, port,4572url.absolute(path, "api/v1.0/user/login"),4573{header=header}, json.generate(jin))4574return resp.status == 2004575and (resp.header["x-auth-token"] or ""):find("^%x+$")4576end4577})45784579table.insert(fingerprints, {4580name = "NetComm ADSL router",4581category = "routers",4582paths = {4583{path = "/"}4584},4585target_check = function (host, port, path, response)4586return (http_auth_realm(response) or ""):find("^NetComm ")4587end,4588login_combos = {4589{username = "admin", password = "admin"}4590},4591login_check = function (host, port, path, user, pass)4592return try_http_auth(host, port, path, user, pass, false)4593end4594})45954596table.insert(fingerprints, {4597name = "Netcomm NTC",4598category = "routers",4599paths = {4600{path = "/index.html"}4601},4602target_check = function (host, port, path, response)4603return response.status == 2004604and response.body4605and response.body:find("NetComm", 1, true)4606and response.body:lower():find("/netcomm_gui_banner.jpg", 1, true)4607and get_cookie(response, "_appwebSessionId_", "^%x+$")4608end,4609login_combos = {4610{username = "root", password = "admin"},4611{username = "admin", password = "admin"}4612},4613login_check = function (host, port, path, user, pass)4614local resp = http_post_simple(host, port, path, nil,4615{username=user,password=pass})4616return resp.status == 3024617and (resp.header["location"] or ""):find("/st[as]tus%.html%f[?\0]")4618end4619})46204621table.insert(fingerprints, {4622name = "Netcomm 3G17Wn",4623category = "routers",4624paths = {4625{path = "/"}4626},4627target_check = function (host, port, path, response)4628return response.status == 2004629and response.body4630and response.body:find(">3G17Wn", 1, true)4631and get_cookie(response, "_appwebSessionId_", "^%x+$")4632end,4633login_combos = {4634{username = "admin", password = "admin"}4635},4636login_check = function (host, port, path, user, pass)4637local resp = http_post_simple(host, port, path, nil,4638{username=user,password=pass})4639return resp.status == 3024640and (resp.header["location"] or ""):find("/adm/status%.asp$")4641end4642})46434644table.insert(fingerprints, {4645name = "NetComm 3G21WB",4646category = "routers",4647paths = {4648{path = "/"}4649},4650target_check = function (host, port, path, response)4651return response.status == 2004652and response.body4653and response.body:find("3G21WB", 1, true)4654and response.body:lower():find("<title>3g21wb", 1, true)4655and get_tag(response.body, "frame", {src="^menu%.html$"})4656end,4657login_combos = {4658{username = "admin", password = "admin"}4659},4660login_check = function (host, port, path, user, pass)4661return try_http_auth(host, port, url.absolute(path, "menu.html"),4662user, pass, false)4663end4664})46654666table.insert(fingerprints, {4667name = "NetComm 3G42WT",4668category = "routers",4669paths = {4670{path = "/"}4671},4672target_check = function (host, port, path, response)4673return response.status == 2004674and response.body4675and response.body:find("3G42WT", 1, true)4676and response.body:lower():find("<title>3g42wt", 1, true)4677and get_tag(response.body, "frame", {src="^login%.html$"})4678end,4679login_combos = {4680{username = "admin", password = "admin"}4681},4682login_check = function (host, port, path, user, pass)4683return try_http_auth(host, port, url.absolute(path, "login.html"),4684user, pass, false)4685end4686})46874688table.insert(fingerprints, {4689name = "PacketFront DRG600",4690category = "routers",4691paths = {4692{path = "/"}4693},4694target_check = function (host, port, path, response)4695return http_auth_realm(response) == "drg600.wifi"4696end,4697login_combos = {4698{username = "admin", password = ""}4699},4700login_check = function (host, port, path, user, pass)4701return try_http_auth(host, port, path, user, pass, false)4702end4703})47044705table.insert(fingerprints, {4706name = "Airlink ACEmanager",4707cpe = "cpe:/h:sierrawireless:airlink_mp_*",4708category = "routers",4709paths = {4710{path = "/"}4711},4712target_check = function (host, port, path, response)4713return response.status == 2004714and response.body4715and response.body:find("Sierra Wireless AirLink", 1, true)4716and response.body:lower():find("<title>:+%s+acemanager%s+:+</title>")4717end,4718login_combos = {4719{username = "user", password = "12345"}4720},4721login_check = function (host, port, path, user, pass)4722local encuser = xmlencode(user)4723local header = {["Content-Type"]="text/xml"}4724local msg = [=[4725<request xmlns="urn:acemanager">4726<connect>4727<login>__USER__</login>4728<password><![CDATA[__PASS__]]></password>4729</connect>4730</request>4731]=]4732msg = msg:gsub("%f[^\0\n]%s+", "")4733msg = msg:gsub("__%w+__", {__USER__=encuser, __PASS__=pass})4734local resp = http_post_simple(host, port,4735url.absolute(path, "xml/Connect.xml"),4736{header=header}, msg)4737return resp.status == 200 and get_cookie(resp, "token", "^%d+$")4738end4739})47404741table.insert(fingerprints, {4742name = "Mimosa Relay",4743category = "routers",4744paths = {4745{path = "/"}4746},4747target_check = function (host, port, path, response)4748return response.status == 2004749and response.body4750and response.body:find("Mimosa", 1, true)4751and response.body:find("%Wmimosa%.isConnected%s*=")4752end,4753login_combos = {4754{username = "configure", password = "mimosa"}4755},4756login_check = function (host, port, path, user, pass)4757local resp = http_post_simple(host, port,4758path .. "?q=index.login&mimosa_ajax=1",4759nil, {username=user,password=pass})4760if not (resp.status == 200 and resp.body) then return false end4761local jstatus, jout = json.parse(resp.body)4762return jstatus and (jout.role or 0) ~= 04763end4764})47654766table.insert(fingerprints, {4767name = "IRTE Digital Radio Link",4768category = "routers",4769paths = {4770{path = "/"}4771},4772target_check = function (host, port, path, response)4773return response.status == 2004774and response.header["server"] == "Z-World Rabbit"4775and response.body4776and get_tag(response.body, "frame", {src="^objsum00%.html$"})4777end,4778login_combos = {4779{username = "", password = "0000"},4780{username = "", password = "111111"}4781},4782login_check = function (host, port, path, user, pass)4783local form1 = stdnse.output_table()4784form1.infield5 = 14785form1.infield6 = pass4786local resp1 = http_post_multipart(host, port,4787url.absolute(path, "pswd.cgi"), nil, form1)4788if not (resp1.status == 200 and (resp1.body or ""):find("(['\"])password%.html%1")) then4789return false4790end4791local resp2 = http_get_simple(host, port,4792url.absolute(path, "password.html"))4793return resp2.status == 2004794and get_tag(resp2.body or "", "input", {name="^infield5$", value="^2$"})4795end4796})47974798table.insert(fingerprints, {4799name = "Motorola AP",4800category = "routers",4801paths = {4802{path = "/"}4803},4804target_check = function (host, port, path, response)4805return response.status == 2004806and (response.header["server"] or ""):find("^lighttpd/%d+%.")4807and response.body4808and response.body:find(">Motorola", 1, true)4809and response.body:lower():find("<title>motorola solutions</title>", 1, true)4810end,4811login_combos = {4812{username = "admin", password = "motorola"}4813},4814login_check = function (host, port, path, user, pass)4815local form = {_dc = math.floor(stdnse.clock_ms()),4816username = user,4817password = pass}4818local lurl = url.absolute(path, "rest.fcgi/services/rest/login?" .. url.build_query(form))4819local resp = http_get_simple(host, port, lurl)4820if not (resp.status == 200 and resp.body) then return false end4821local jstatus, jout = json.parse(resp.body)4822return jstatus and jout.status4823end4824})48254826table.insert(fingerprints, {4827name = "Motorola RF Switch",4828category = "routers",4829paths = {4830{path = "/"}4831},4832target_check = function (host, port, path, response)4833return response.status == 2004834and (response.header["server"] or ""):find("^thttpd/%d+%.")4835and response.body4836and response.body:find(">Motorola", 1, true)4837and response.body:lower():find("<title>motorola wireless network management</title>", 1, true)4838end,4839login_combos = {4840{username = "admin", password = "superuser"}4841},4842login_check = function (host, port, path, user, pass)4843local login = ("J20K34NMMT89XPIJ34S login %s %s"):format(stdnse.tohex(user), stdnse.tohex(pass))4844local lurl = url.absolute(path, "usmCgi.cgi/?" .. url.escape(login))4845local resp = http_get_simple(host, port, lurl)4846return resp.status == 2004847and (resp.body or ""):find("^login 0 ")4848end4849})48504851table.insert(fingerprints, {4852name = "Pakedge C36 Macrocell Controller",4853category = "routers",4854paths = {4855{path = "/"}4856},4857target_check = function (host, port, path, response)4858return response.status == 3024859and response.header["location"] == "./c36/login.php"4860end,4861login_combos = {4862{username = "pakedge", password = "pakedgec"}4863},4864login_check = function (host, port, path, user, pass)4865local form = {rtype="login",4866username=user,4867password=pass}4868local resp = http_post_simple(host, port,4869url.absolute(path, "c36/ajax/login.php"),4870nil, form)4871if not (resp.status == 200 and resp.body) then return false end4872local jstatus, jout = json.parse(resp.body)4873return jstatus and jout.ok4874end4875})48764877table.insert(fingerprints, {4878name = "ArubaOS WebUI",4879cpe = "cpe:/o:arubanetworks:arubaos",4880category = "routers",4881paths = {4882{path = "/"}4883},4884target_check = function (host, port, path, response)4885return response.status == 4014886and response.body4887and response.body:find("/images/arubalogo.gif", 1, true)4888and response.body:find("/screens/wms/wms.login", 1, true)4889end,4890login_combos = {4891{username = "admin", password = "admin"}4892},4893login_check = function (host, port, path, user, pass)4894local form = {opcode="login",4895url="/",4896needxml=0,4897uid=user,4898passwd=pass}4899local resp = http_post_simple(host, port,4900url.absolute(path, "screens/wms/wms.login"),4901nil, form)4902return resp.status == 2004903and (resp.body or ""):find("/screens/wmsi/monitor.summary.html", 1, true)4904end4905})49064907table.insert(fingerprints, {4908name = "Aruba AirWave",4909cpe = "cpe:/a:arubanetworks:airwave",4910category = "routers",4911paths = {4912{path = "/"}4913},4914target_check = function (host, port, path, response)4915return response.status == 2004916and response.body4917and response.body:find("/noauth/theme/airwave/favicon.ico", 1, true)4918and response.body:lower():find("%shref%s*=%s*(['\"])[^'\"]-/mercury%.%d+%.css%1")4919end,4920login_combos = {4921{username = "admin", password = "admin"}4922},4923login_check = function (host, port, path, user, pass)4924local form = {credential_0=user,4925credential_1=pass,4926destination=url.absolute(path, "index.html")}4927local resp = http_post_simple(host, port, url.absolute(path, "LOGIN"),4928nil, form)4929return resp.status == 3024930and (resp.header["location"] or ""):find("/index%.html$")4931end4932})49334934table.insert(fingerprints, {4935name = "Nortel VPN Router",4936cpe = "cpe:/h:nortel:vpn_router_*",4937category = "routers",4938paths = {4939{path = "/"}4940},4941target_check = function (host, port, path, response)4942return response.status == 2004943and response.header["server"] == "HTTP Server"4944and response.body4945and response.body:find(">Nortel", 1, true)4946and response.body:lower():find("<title>nortel vpn router</title>", 1, true)4947end,4948login_combos = {4949{username = "admin", password = "setup"}4950},4951login_check = function (host, port, path, user, pass)4952return try_http_auth(host, port, url.absolute(path, "manage/bdy_sys.htm"),4953user, pass, false)4954end4955})49564957table.insert(fingerprints, {4958name = "pfSense (var.1)",4959cpe = "cpe:/a:bsdperimeter:pfsense",4960category = "routers",4961paths = {4962{path = "/"}4963},4964target_check = function (host, port, path, response)4965return response.status == 2004966and response.body4967and response.body:find("/pfsense/login.css", 1, true)4968and get_tag(response.body, "form", {name="^login_iform$"})4969end,4970login_combos = {4971{username = "admin", password = "pfsense"}4972},4973login_check = function (host, port, path, user, pass)4974local form = {usernamefld=user,4975passwordfld=pass,4976login="Login"}4977local resp = http_post_simple(host, port, url.absolute(path, "index.php"),4978nil, form)4979return resp.status == 3024980and resp.header["location"] == path4981and get_cookie(resp, "PHPSESSID", "^%x+$")4982end4983})49844985table.insert(fingerprints, {4986name = "pfSense (var.2)",4987cpe = "cpe:/a:pfsense:pfsense",4988category = "routers",4989paths = {4990{path = "/"}4991},4992target_check = function (host, port, path, response)4993return response.status == 2004994and response.body4995and response.body:find("pfSense", 1, true)4996and get_tag(response.body, "input", {name="^__csrf_magic$"})4997end,4998login_combos = {4999{username = "admin", password = "pfsense"}5000},5001login_check = function (host, port, path, user, pass)5002local resp1 = http_get_simple(host, port, path)5003if not (resp1.status == 200 and resp1.body) then return false end5004local token = get_tag(resp1.body, "input", {type="^hidden$", name="^__csrf_magic$", value=""})5005if not token then return false end5006local form = {[token.name]=token.value,5007usernamefld=user,5008passwordfld=pass,5009login=""}5010local resp2 = http_post_simple(host, port, url.absolute(path, "index.php"),5011{cookies=resp1.cookies}, form)5012return resp2.status == 3025013and resp2.header["location"] == path5014and get_cookie(resp2, "PHPSESSID", "^%w+$")5015end5016})50175018table.insert(fingerprints, {5019name = "ScreenOS",5020cpe = "cpe:/o:juniper:netscreen_screenos",5021category = "routers",5022paths = {5023{path = "/"}5024},5025target_check = function (host, port, path, response)5026return response.status == 2005027and (response.header["server"] or ""):find("^Virata%-EmWeb/R%d+_")5028and response.body5029and response.body:lower():find("admin_pw", 1, true)5030end,5031login_combos = {5032{username = "netscreen", password = "netscreen"}5033},5034login_check = function (host, port, path, user, pass)5035local form = {admin_id="",5036admin_pw="",5037time=tostring(math.floor(stdnse.clock_ms())):sub(5),5038un=base64.enc(user),5039pw=base64.enc(pass)}5040local resp = http_post_simple(host, port, url.absolute(path, "index.html"),5041nil, form)5042return resp.status == 3035043and (resp.header["location"] or ""):find("/nswebui.html?", 1, true)5044end5045})50465047table.insert(fingerprints, {5048name = "F5 TMOS",5049cpe = "cpe:/o:f5:tmos",5050category = "routers",5051paths = {5052{path = "/"}5053},5054target_check = function (host, port, path, response)5055return response.status == 2005056and response.body5057and response.body:find("F5 Networks", 1, true)5058and response.body:find("BIG-IP", 1, true)5059and response.body:find("/tmui/tmui/system/settings/redirect.jsp", 1, true)5060end,5061login_combos = {5062{username = "admin", password = "admin"}5063},5064login_check = function (host, port, path, user, pass)5065local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "tmui/login.jsp")}))}5066local resp = http_post_simple(host, port,5067url.absolute(path, "tmui/logmein.html?"),5068{header=header}, {username=user,passwd=pass})5069return resp.status == 3025070and get_cookie(resp, "BIGIPAuthCookie", "^%x+$")5071end5072})50735074table.insert(fingerprints, {5075name = "F5 BIG-IQ",5076cpe = "cpe:/a:f5:big-iq_centralized_management",5077category = "routers",5078paths = {5079{path = "/"}5080},5081target_check = function (host, port, path, response)5082return response.status == 3015083and response.header["server"] == "webd"5084and (response.header["location"] or ""):find("/ui/login/?$")5085end,5086login_combos = {5087{username = "admin", password = "admin"}5088},5089login_check = function (host, port, path, user, pass)5090local header = {["Content-Type"]="application/json;charset=utf-8"}5091local jin = {username=user, password=pass, needsToken=true}5092json.make_object(jin)5093local resp = http_post_simple(host, port,5094url.absolute(path, "mgmt/shared/authn/login"),5095{header=header}, json.generate(jin))5096if not (resp.status == 200 and resp.body) then return false end5097local jstatus, jout = json.parse(resp.body)5098return jstatus and jout.username == user and jout.token5099end5100})51015102table.insert(fingerprints, {5103name = "Citrix NetScaler",5104cpe = "cpe:/a:citrix:netscaler",5105category = "routers",5106paths = {5107{path = "/"}5108},5109target_check = function (host, port, path, response)5110return response.status == 2005111and response.body5112and response.body:find("NetScaler", 1, true)5113and response.body:lower():find("<title>citrix login</title>", 1, true)5114end,5115login_combos = {5116{username = "nsroot", password = "nsroot"}5117},5118login_check = function (host, port, path, user, pass)5119local form = {username=user,5120password=pass,5121url="",5122timezone_offset=0}5123local resp = http_post_simple(host, port,5124url.absolute(path, "login/do_login"),5125nil, form)5126return resp.status == 3025127and (resp.header["location"] or ""):find("/menu/neo$")5128and get_cookie(resp, "startupapp") == "neo"5129end5130})51315132table.insert(fingerprints, {5133name = "Citrix NetScaler MAS",5134category = "routers",5135paths = {5136{path = "/"}5137},5138target_check = function (host, port, path, response)5139return response.status == 3025140and (response.header["location"] or ""):find("/admin_ui/mas/ent/login%.html$")5141end,5142login_combos = {5143{username = "nsroot", password = "nsroot"}5144},5145login_check = function (host, port, path, user, pass)5146local jin = {login={username=user,password=pass}}5147json.make_object(jin)5148local resp = http_post_simple(host, port,5149url.absolute(path, "nitro/v1/config/login"),5150nil, {object=json.generate(jin)})5151if not (resp.status == 200 and resp.body) then return false end5152local jstatus, jout = json.parse(resp.body)5153return jstatus and jout.errorcode == 0 and jout.resourceName == user5154end5155})51565157---5158--VoIP5159---5160table.insert(fingerprints, {5161name = "Aastra IP Phone",5162category = "voip",5163paths = {5164{path = "/"}5165},5166target_check = function (host, port, path, response)5167return (http_auth_realm(response) or ""):find("^Aastra %d+i$")5168end,5169login_combos = {5170{username = "admin", password = "22222"}5171},5172login_check = function (host, port, path, user, pass)5173return try_http_auth(host, port, path, user, pass, false)5174end5175})51765177table.insert(fingerprints, {5178name = "Aastra AXS 5000",5179category = "voip",5180paths = {5181{path = "/"}5182},5183target_check = function (host, port, path, response)5184local lurl = response.header["location"] or ""5185if not (response.status == 302 and lurl:find("/rhm$")) then return false end5186local resp = http_get_simple(host, port, lurl)5187return http_auth_realm(resp) == "Aastra 5000"5188end,5189login_combos = {5190{username = "admin", password = "admin"}5191},5192login_check = function (host, port, path, user, pass)5193return try_http_auth(host, port, url.absolute(path, "rhm"),5194user, pass, false)5195end5196})51975198table.insert(fingerprints, {5199name = "Aastra OpenCom 1000",5200category = "voip",5201paths = {5202{path = "/"}5203},5204target_check = function (host, port, path, response)5205return have_openssl5206and response.status == 2005207and response.body5208and response.body:find("OpenCom", 1, true)5209and response.body:lower():find("<title>opencom 1000</title>", 1, true)5210and get_tag(response.body, "frame", {src="/login%.html$"})5211end,5212login_combos = {5213{username = "Admin", password = "Admin"}5214},5215login_check = function (host, port, path, user, pass)5216local resp1 = http_get_simple(host, port, url.absolute(path, "login.html"))5217if not (resp1.status == 200 and resp1.body) then return false end5218local token = get_tag(resp1.body, "input", {name="^login$", value="^%x+$"})5219if not token then return false end5220pass = stdnse.tohex(openssl.md5(pass))5221local form2 = {login=stdnse.tohex(openssl.md5(token.value .. pass)),5222user=user,5223password="",5224ButtonOK="OK"}5225local resp2 = http_post_simple(host, port,5226url.absolute(path, "summary.html"),5227nil, form2)5228return resp2.status == 3025229and (resp2.header["location"] or ""):find("/%?uid=0x%x+$")5230end5231})52325233table.insert(fingerprints, {5234name = "Cisco TelePresence",5235category = "voip",5236paths = {5237{path = "/"}5238},5239target_check = function (host, port, path, response)5240return response.status == 3025241and (response.header["location"] or ""):find("/web/signin$")5242end,5243login_combos = {5244{username = "admin", password = ""}5245},5246login_check = function (host, port, path, user, pass)5247local resp = http_post_simple(host, port,5248url.absolute(path, "web/signin/open"), nil,5249{username=user, password=pass})5250if not (resp.status == 200 and resp.body) then return false end5251local jstatus, jout = json.parse(resp.body)5252return jstatus and jout.result == "ok"5253end5254})52555256table.insert(fingerprints, {5257name = "Dialogic PowerMedia XMS Console",5258category = "voip",5259paths = {5260{path = "/"}5261},5262target_check = function (host, port, path, response)5263return response.status == 2005264and response.body5265and response.body:find("/verifyLogin/", 1, true)5266and response.body:lower():find("<title>%s*dialogic xms admin console%s*</title>")5267end,5268login_combos = {5269{username = "viewer", password = "admin"},5270{username = "admin", password = "admin"},5271{username = "superadmin", password = "admin"}5272},5273login_check = function (host, port, path, user, pass)5274local resp = http_post_simple(host, port,5275url.absolute(path, "index.php/verifyLogin/login"),5276nil, {usernameId=user, passwordId=pass})5277return resp.status == 2005278and get_cookie(resp, "ci_session", "USERNAME")5279end5280})52815282table.insert(fingerprints, {5283name = "Dialogic PowerMedia XMS NodeController",5284category = "voip",5285paths = {5286{path = "/"}5287},5288target_check = function (host, port, path, response)5289return http_auth_realm(response) == "NodeController"5290end,5291login_combos = {5292{username = "admin", password = "admin"}5293},5294login_check = function (host, port, path, user, pass)5295return try_http_auth(host, port, path, user, pass, false)5296end5297})52985299table.insert(fingerprints, {5300name = "Dialogic PowerMedia XMS RESTful API",5301category = "voip",5302paths = {5303{path = "/"}5304},5305target_check = function (host, port, path, response)5306return http_auth_realm(response) == "XMS RESTful API"5307end,5308login_combos = {5309{username = "admin", password = "admin"}5310},5311login_check = function (host, port, path, user, pass)5312return try_http_auth(host, port, path, user, pass, false)5313end5314})53155316table.insert(fingerprints, {5317name = "Grandstream VoIP Device",5318category = "voip",5319paths = {5320{path = "/cgi-bin/login"}5321},5322target_check = function (host, port, path, response)5323return response.status == 2005324and response.body5325and response.body:find("Grandstream", 1, true)5326and response.body:lower():find("<title>grandstream ?device configuration</title>")5327and get_tag(response.body, "input", {name="^gnkey$", type="^hidden$", value="^0b82$"})5328end,5329login_combos = {5330{username = "", password = "admin"},5331{username = "", password = "123"}5332},5333login_check = function (host, port, path, user, pass)5334local resp = http_post_simple(host, port, url.absolute(path, "dologin"),5335nil, {P2=pass,Login="Login",gnkey="0b82"})5336return resp.status == 200 and get_cookie(resp, "session_id", "^%x+$")5337end5338})53395340table.insert(fingerprints, {5341name = "Grandstream GXP2200",5342category = "voip",5343paths = {5344{path = "/"}5345},5346target_check = function (host, port, path, response)5347return response.status == 2005348and response.body5349and response.body:find("%Wdocument%.title%s*=%s*(['\"])GXP2200%1")5350and response.body:lower():find("enterprise multimedia phone for android", 1, true)5351end,5352login_combos = {5353{username = "admin", password = "admin"},5354{username = "user", password = "123"}5355},5356login_check = function (host, port, path, user, pass)5357local form = {action="login",5358Username=user,5359Secret=pass,5360time=math.floor(stdnse.clock_ms())}5361local resp = http_get_simple(host, port,5362url.absolute(path, "manager?" .. url.build_query(form)))5363return resp.status == 200 and get_cookie(resp, "phonecookie", "^%x+$")5364end5365})53665367table.insert(fingerprints, {5368name = "Polycom SoundPoint (var.1)",5369category = "voip",5370paths = {5371{path = "/"}5372},5373target_check = function (host, port, path, response)5374return response.status == 2005375and response.body5376and response.body:find("Polycom", 1, true)5377and response.body:find("submitLoginInfo", 1, true)5378and response.body:lower():find("<title>polycom - configuration utility</title>", 1, true)5379and get_tag(response.body, "body", {onload="^document%.login%.password%.focus%(%)$"})5380end,5381login_combos = {5382{username = "Polycom", password = "456"},5383{username = "User", password = "123"}5384},5385login_check = function (host, port, path, user, pass)5386local qstr = url.build_query({t=os.date("!%a, %d %b %Y %H:%M:%S GMT")})5387return try_http_auth(host, port, url.absolute(path, "auth.htm?" .. qstr),5388user, pass, false)5389end5390})53915392table.insert(fingerprints, {5393name = "Polycom SoundPoint (var.2)",5394category = "voip",5395paths = {5396{path = "/"}5397},5398target_check = function (host, port, path, response)5399return response.status == 2005400and response.body5401and response.body:find("Polycom", 1, true)5402and response.body:find("submitLoginInfo", 1, true)5403and response.body:lower():find("<title>polycom - configuration utility</title>", 1, true)5404and get_tag(response.body, "input", {name="^password$", autocomplete="^off$"})5405end,5406login_combos = {5407{username = "Polycom", password = "456"},5408{username = "User", password = "123"}5409},5410login_check = function (host, port, path, user, pass)5411local creds = {username = user, password = pass, digest = false}5412local resp = http_post_simple(host, port,5413url.absolute(path, "form-submit/auth.htm"),5414{auth=creds}, "")5415return resp.status == 2005416and (resp.body or ""):find("|SUCCESS|", 1, true)5417end5418})54195420table.insert(fingerprints, {5421name = "Polycom SoundPoint (basic auth)",5422cpe = "cpe:/h:polycom:soundpoint_ip_*",5423category = "voip",5424paths = {5425{path = "/"}5426},5427target_check = function (host, port, path, response)5428return response.header["server"] == "Polycom SoundPoint IP Telephone HTTPd"5429and http_auth_realm(response) == "SPIP Configuration"5430end,5431login_combos = {5432{username = "Polycom", password = "456"}5433},5434login_check = function (host, port, path, user, pass)5435return try_http_auth(host, port, path, user, pass, false)5436end5437})54385439table.insert(fingerprints, {5440name = "Polycom RSS 4000",5441cpe = "cpe:/h:polycom:recording_and_streaming_server_4000",5442category = "voip",5443paths = {5444{path = "/portal/login.jsf"}5445},5446target_check = function (host, port, path, response)5447return response.status == 2005448and response.body5449and response.body:find("Polycom", 1, true)5450and response.body:lower():find("<title>polycom rss 4000</title>", 1, true)5451and get_tag(response.body, "input", {id="^loginform:username$"})5452end,5453login_combos = {5454{username = "admin", password = "admin"}5455},5456login_check = function (host, port, path, user, pass)5457local resp1 = http_get_simple(host, port, path)5458if not (resp1.status == 200 and resp1.body) then return false end5459local vstate = get_tag(resp1.body, "input", {name="^javax%.faces%.viewstate$", value="^%-?%d+:%-?%d+$"})5460if not vstate then return false end5461local opts2 = {header={["Faces-Request"]="partial/ajax"},5462cookies=resp1.cookies}5463local form2 = {loginForm="loginForm",5464["loginForm:userName"]=user,5465["loginForm:password"]=pass,5466["loginForm:domain"]="LOCAL",5467["javax.faces.ViewState"]=vstate.value,5468["javax.faces.source"]="loginForm:loginBt",5469["javax.faces.partial.event"]="click",5470["javax.faces.partial.execute"]="loginForm:loginBt @component",5471["javax.faces.partial.render"]="@component",5472["org.richfaces.ajax.component"]="loginForm:loginBt",5473["loginForm:loginBt"]="loginForm:loginBt",5474["AJAX:EVENTS_COUNT"]=1,5475["javax.faces.partial.ajax"]="true"}5476local resp2 = http_post_simple(host, port, path, opts2, form2)5477return resp2.status == 2005478and (resp2.body or ""):find("<complete>checkLogin('')", 1, true)5479end5480})54815482table.insert(fingerprints, {5483name = "Polycom RMX 500",5484cpe = "cpe:/h:polycom:rmx_500",5485category = "voip",5486paths = {5487{path = "/"}5488},5489target_check = function (host, port, path, response)5490return response.status == 2005491and response.body5492and response.body:find("<RMX1000_UI>", 1, true)5493and response.body:lower():find("<title></title>", 1, true)5494end,5495login_combos = {5496{username = "POLYCOM", password = "POLYCOM"}5497},5498login_check = function (host, port, path, user, pass)5499local msg = [[5500<?xml version="1.0" encoding="UTF-8" ?>5501<RMX1000_UI version="1.0.0.0">5502<FROM_PAGE id="login">5503<SESSION_ID value="" />5504<_CGI_NO_REFRESH value="YES" />5505<SEL_LANG value="en" />5506<IS_CGI value="YES" />5507<DEV_IP_V4 value="" />5508<LOGINNAME value="__USER__" />5509<PASSWD value="__PASS__" />5510<rmx1000_ip value="127.0.0.1" />5511<proxy_log_ip value="" />5512<LOGIN_FLAG value="__IPADDR__.__TSTAMP__" />5513<_CGI_UI_LANG value="en" />5514<cfg_ui_hide value="YES" />5515<_CGI_TIME value="__TIME__" />5516</FROM_PAGE>5517</RMX1000_UI>]]5518msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")5519msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),5520__PASS__=xmlencode(pass),5521__IPADDR__=xmlencode(host.ip),5522__TSTAMP__=math.floor(stdnse.clock_ms()),5523__TIME__=xmlencode(os.date("!%a %b %d %Y %H:%M:%S GMT+0000"))})5524local qstr = url.build_query({_dst_in_xml_raw=msg})5525local resp = http_get_simple(host, port,5526url.absolute(path, "cgi-bin/rmx_cgi?" .. qstr))5527return resp.status == 2005528and (resp.body or ""):find("<SESSION_ID>%x+</SESSION_ID>")5529end5530})55315532table.insert(fingerprints, {5533name = "Polycom RMX 1000",5534cpe = "cpe:/h:polycom:rmx_1000",5535category = "voip",5536paths = {5537{path = "/"}5538},5539target_check = function (host, port, path, response)5540return response.status == 2005541and response.body5542and response.body:find("<RMX1000_UI>", 1, true)5543and response.body:lower():find("<title>polycom rmx 1000</title>", 1, true)5544end,5545login_combos = {5546{username = "POLYCOM", password = "POLYCOM"}5547},5548login_check = function (host, port, path, user, pass)5549local msg = [[5550<?xml version="1.0" encoding="UTF-8" ?>5551<RMX1000_UI version="1.0.0.0">5552<FROM_PAGE id="login">5553<SESSION_ID value="" />5554<_CGI_NO_REFRESH value="NO" />5555<SEL_LANG value="en" />5556<IS_CGI value="YES" />5557<DEV_IP_V4 value="" />5558<LOGINNAME value="__USER__" />5559<PASSWD value="__PASS__" />5560<rmx1000_ip value="127.0.0.1" />5561<proxy_log_ip value="" />5562<_CGI_UI_LANG value="en" />5563<cfg_ui_hide value="YES" />5564<_CGI_TIME value="__TIME__" />5565</FROM_PAGE>5566</RMX1000_UI>]]5567msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")5568msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),5569__PASS__=xmlencode(stdnse.tohex(pass)),5570__TIME__=xmlencode(os.date("!%a %b %d %Y %H:%M:%S GMT+0000"))})5571local resp = http_post_simple(host, port,5572url.absolute(path, "cgi-bin/rmx1000_cgi"),5573nil, {_dst_in_xml_raw=msg})5574return resp.status == 2005575and (resp.body or ""):find("<SESSION_ID>%x+</SESSION_ID>")5576end5577})55785579table.insert(fingerprints, {5580name = "Polycom RPAD",5581category = "voip",5582paths = {5583{path = "/"}5584},5585target_check = function (host, port, path, response)5586return response.status == 2005587and response.header["server"] == "Polycom RPAD"5588and response.body5589and get_refresh_url(response.body, "/edge/$")5590end,5591login_combos = {5592{username = "LOCAL\\admin", password = "admin"}5593},5594login_check = function (host, port, path, user, pass)5595local form = {j_username=base64.enc(user),5596j_password=base64.enc(pass)}5597local resp = http_post_simple(host, port,5598url.absolute(path, "edge/security/check"),5599nil, form)5600if not (resp.status == 200 and resp.body) then return false end5601local jstatus, jout = json.parse(b64decode(resp.body:gsub("%s+","")) or "")5602return jstatus and jout.success5603end5604})56055606table.insert(fingerprints, {5607name = "Teles Gateway",5608category = "voip",5609paths = {5610{path = "/"}5611},5612target_check = function (host, port, path, response)5613return response.status == 2005614and response.header["server"] == "TELES AG"5615and response.body5616and get_tag(response.body, "frame", {src="/common/navibar_[%w_]+_login%.html$"})5617end,5618login_combos = {5619{username = "teles-admin", password = "tcs-admin"},5620{username = "teles-user", password = "tcs-user"},5621{username = "teles-carrier", password = "tcs-carrier"}5622},5623login_check = function (host, port, path, user, pass)5624local resp1 = http_get_simple(host, port, path)5625if not (resp1.status == 200 and resp1.body) then return false end5626local frame = get_tag(resp1.body, "frame", {src="/common/navibar_[%w_]+_login%.html$"})5627if not frame then return false end5628local nurl = url.absolute(path, frame.src)5629local resp2 = http_get_simple(host, port, nurl)5630if not (resp2.status == 200 and resp2.body) then return false end5631local lurl = resp2.body:lower():match("<a%f[%s][^>]-%shref%s*=%s*['\"]?([^'\">%s]*)[^>]*>login</a")5632if not lurl then return false end5633return try_http_auth(host, port, url.absolute(nurl, lurl), user, pass, false)5634end5635})56365637table.insert(fingerprints, {5638name = "Mediatrix",5639category = "voip",5640paths = {5641{path = "/"}5642},5643target_check = function (host, port, path, response)5644return response.status == 3025645and (response.header["location"] or ""):find("%f[^/\0]system_info%.esp$")5646end,5647login_combos = {5648{username = "admin", password = "admin"},5649{username = "admin", password = "administrator"},5650{username = "public", password = ""}5651},5652login_check = function (host, port, path, user, pass)5653local resp = http_post_simple(host, port, url.absolute(path, "login.esp"),5654nil, {username=user,passwd=pass})5655return resp.status == 3025656and (resp.header["location"] or ""):find("%f[^/\0]system_info%.esp$")5657end5658})56595660table.insert(fingerprints, {5661name = "Mediatrix (basic auth)",5662category = "voip",5663paths = {5664{path = "/"}5665},5666target_check = function (host, port, path, response)5667local realm = http_auth_realm(response)5668return (realm == "Mediatrix" or realm == "default")5669and (response.body or ""):lower():find("<title>authentication error: access denied, authorization required.</title>", 1, true)5670end,5671login_combos = {5672{username = "admin", password = "1234"},5673{username = "root", password = "5678"}5674},5675login_check = function (host, port, path, user, pass)5676return try_http_auth(host, port, path, user, pass, true)5677end5678})56795680table.insert(fingerprints, {5681name = "Mediatrix iPBX",5682category = "voip",5683paths = {5684{path = "/"}5685},5686target_check = function (host, port, path, response)5687return response.status == 2005688and response.body5689and response.body:find("PBX Administration", 1, true)5690and get_tag(response.body, "a", {href="^admin/$"})5691and response.body:lower():find("<title>ipbx</title>", 1, true)5692end,5693login_combos = {5694{username = "admin", password = "admin"}5695},5696login_check = function (host, port, path, user, pass)5697return try_http_auth(host, port, url.absolute(path, "admin/config.php"),5698user, pass, false)5699end5700})57015702table.insert(fingerprints, {5703name = "Openstage IP Phone",5704category = "voip",5705paths = {5706{path = "/"}5707},5708target_check = function (host, port, path, response)5709return response.status == 2005710and response.body5711and response.body:find("Unify", 1, true)5712and get_tag(response.body, "frame", {src="[?&]page=webmp_user_login%f[&\0]"})5713end,5714login_combos = {5715{username = "", password = "123456"}5716},5717login_check = function (host, port, path, user, pass)5718local form = {page_submit="WEBMp_Admin_Login",5719lang="en",5720AdminPassword=pass}5721local resp = http_post_simple(host, port, url.absolute(path, "page.cmd"),5722nil, form)5723return resp.status == 2005724and get_cookie(resp, "webm", "%d+|[%d-]*[1-9a-f][%d-]*")5725end5726})57275728table.insert(fingerprints, {5729name = "Yealink IP Phone",5730cpe = "cpe:/o:yealink:voip_phone_firmware",5731category = "voip",5732paths = {5733{path = "/"}5734},5735target_check = function (host, port, path, response)5736return (http_auth_realm(response) or ""):find(" IP [Pp]hone SIP%-%u%d+%u?$")5737end,5738login_combos = {5739{username = "admin", password = "admin"},5740{username = "user", password = "user"},5741{username = "var", password = "var"}5742},5743login_check = function (host, port, path, user, pass)5744return try_http_auth(host, port, path, user, pass, false)5745end5746})57475748---5749--Digital recorders5750---5751table.insert(fingerprints, {5752name = "DM Digital Sprite 2",5753category = "security",5754paths = {5755{path = "/"}5756},5757target_check = function (host, port, path, response)5758return response.status == 2005759and response.body5760and response.body:find("Dedicated Micros", 1, true)5761and response.body:find("webpages/index.shtml", 1, true)5762and get_tag(response.body, "meta", {name="^author$", content="^dedicated micros "})5763end,5764login_combos = {5765{username = "dm", password = "web"}5766},5767login_check = function (host, port, path, user, pass)5768return try_http_auth(host, port, url.absolute(path, "frmpages/index.html"),5769user, pass, true)5770end5771})57725773table.insert(fingerprints, {5774name = "DM NetVu",5775category = "security",5776paths = {5777{path = "/"}5778},5779target_check = function (host, port, path, response)5780return response.status == 2005781and response.body5782and response.body:find("Dedicated Micros", 1, true)5783and response.body:find("/gui/gui_outer_frame.shtml", 1, true)5784and get_tag(response.body, "meta", {name="^author$", content="^dedicated micros "})5785end,5786login_combos = {5787{username = "", password = ""}5788},5789login_check = function (host, port, path, user, pass)5790local lurl = url.absolute(path, "gui/frmpages/gui_system.shtml")5791local resp = http_get_simple(host, port, lurl)5792if resp.status == 200 then5793return (resp.body or ""):find('top.render_table("System Page"', 1, true)5794end5795return try_http_auth(host, port, lurl, user, pass, true)5796end5797})57985799table.insert(fingerprints, {5800name = "LevelOne WCS-0050 Camera",5801category = "security",5802paths = {5803{path = "/"}5804},5805target_check = function (host, port, path, response)5806return http_auth_realm(response) == "LevelOne WCS-0050"5807end,5808login_combos = {5809{username = "admin", password = "admin"}5810},5811login_check = function (host, port, path, user, pass)5812return try_http_auth(host, port, path, user, pass, false)5813end5814})58155816table.insert(fingerprints, {5817name = "LG Smart IP Device",5818category = "security",5819paths = {5820{path = "/"}5821},5822target_check = function (host, port, path, response)5823return response.status == 2005824and response.body5825and response.body:find(">LG Smart IP Device<", 1, true)5826and get_tag(response.body, "frame", {src="^login_org%.php$"})5827end,5828login_combos = {5829{username = "admin", password = "admin"}5830},5831login_check = function (host, port, path, user, pass)5832return try_http_auth(host, port, url.absolute(path, "digest.php"),5833user, pass, false)5834end5835})58365837table.insert(fingerprints, {5838name = "MOBOTIX Camera",5839category = "security",5840paths = {5841{path = "/"},5842{path = "/control/userimage.html"}5843},5844target_check = function (host, port, path, response)5845return response.status == 4015846and http_auth_realm(response)5847and response.body5848and response.body:find("MOBOTIX AG", 1, true)5849end,5850login_combos = {5851{username = "admin", password = "meinsm"}5852},5853login_check = function (host, port, path, user, pass)5854return try_http_auth(host, port, path, user, pass, false)5855end5856})58575858table.insert(fingerprints, {5859name = "OEM GoAhead-Webs IP Camera",5860category = "security",5861paths = {5862{path = "/"}5863},5864target_check = function (host, port, path, response)5865return response.header["server"] == "GoAhead-Webs"5866and http_auth_realm(response) == "GoAhead"5867end,5868login_combos = {5869{username = "admin", password = "888888"},5870{username = "admin", password = "12345"},5871{username = "admin", password = "123456"},5872{username = "admin", password = ""}5873},5874login_check = function (host, port, path, user, pass)5875return try_http_auth(host, port, path, user, pass, true)5876end5877})58785879table.insert(fingerprints, {5880name = "IPCC P2P Camera",5881category = "security",5882paths = {5883{path = "/"}5884},5885target_check = function (host, port, path, response)5886return response.header["server"] == "GoAhead-Webs"5887and http_auth_realm(response) == "WIFICAM"5888end,5889login_combos = {5890{username = "admin", password = "admin"}5891},5892login_check = function (host, port, path, user, pass)5893return try_http_auth(host, port, path, user, pass, true)5894end5895})58965897table.insert(fingerprints, {5898name = "AXIS 2100 Network Camera",5899cpe = "cpe:/h:axis:2100_network_camera",5900category = "security",5901paths = {5902{path = "/"}5903},5904target_check = function (host, port, path, response)5905return response.status == 2005906and (response.header["server"] or ""):find("^Boa/%d+%.")5907and response.body5908and response.body:find("AXIS", 1, true)5909and response.body:lower():find("<title>axis ", 1, true)5910end,5911login_combos = {5912{username = "root", password = "pass"},5913{username = "admin", password = "admin"}5914},5915login_check = function (host, port, path, user, pass)5916return try_http_auth(host, port, url.absolute(path, "view/view.shtml"),5917user, pass, false)5918end5919})59205921table.insert(fingerprints, {5922name = "AXIS C/M/P/V Series Device",5923category = "security",5924paths = {5925{path = "/"}5926},5927target_check = function (host, port, path, response)5928if response.status == 302 then5929if not (response.header["location"] or ""):find("/index%.shtml$") then5930return false5931end5932response = http_get_simple(host, port,5933url.absolute(path, "index.shtml"))5934end5935return response.status == 2005936and response.body5937and response.body:find("/axis-cgi/pwdroot/set_language.cgi?", 1, true)5938and response.body:lower():find("<title>index page</title>", 1, true)5939end,5940login_combos = {5941{username = "root", password = ""}5942},5943login_check = function (host, port, path, user, pass)5944local resp = http_get_simple(host, port,5945url.absolute(path, "pwdroot/pwdRoot.shtml"))5946return resp.status == 2005947and resp.body5948and get_tag(resp.body, "input", {value="^" .. user .. "$"})5949and get_tag(resp.body, "input", {name="^pwd_confirm$"})5950end5951})59525953table.insert(fingerprints, {5954name = "AXIS Network Video Door Station",5955category = "security",5956paths = {5957{path = "/"}5958},5959target_check = function (host, port, path, response)5960if response.status == 302 then5961if not (response.header["location"] or ""):find("/index%.shtml$") then5962return false5963end5964response = http_get_simple(host, port,5965url.absolute(path, "index.shtml"))5966end5967return response.status == 2005968and response.body5969and response.body:find("%Wvar%s+refreshUrl%s*=%s*(['\"])[^'\"]-/view/view%.shtml%?id=%d+%1")5970and response.body:lower():find("<title>index page</title>", 1, true)5971end,5972login_combos = {5973{username = "root", password = "pass"}5974},5975login_check = function (host, port, path, user, pass)5976local form = {id=math.random(1000,30000),5977imagepath=url.absolute(path, "mjpg/1/video.mjpg"),5978size=1}5979return try_http_auth(host, port,5980url.absolute(path, "view/view.shtml?" .. url.build_query(form)),5981user, pass, true)5982end5983})59845985table.insert(fingerprints, {5986name = "AXIS Entry Manager",5987category = "security",5988paths = {5989{path = "/"}5990},5991target_check = function (host, port, path, response)5992return response.status == 2005993and response.body5994and response.body:find("/webapp/pacs/index.shtml?id=", 1, true)5995and (response.body:find("%Wvar%s+refreshUrl%s*=%s*(['\"])[^'\"]-/webapp/pacs/index%.shtml%?id=%d+%1")5996or get_refresh_url(response.body, "/webapp/pacs/index%.shtml%?id=%d+$"))5997and response.body:lower():find("<title>index page</title>", 1, true)5998end,5999login_combos = {6000{username = "root", password = "pass"}6001},6002login_check = function (host, port, path, user, pass)6003local form = {action="list",6004group="Properties.System.Language",6005_=math.floor(stdnse.clock_ms())}6006return try_http_auth(host, port,6007url.absolute(path, "axis-cgi/param.cgi?" .. url.build_query(form)),6008user, pass, true)6009end6010})60116012table.insert(fingerprints, {6013name = "Panasonic Network Camera",6014category = "security",6015paths = {6016{path = "/"}6017},6018target_check = function (host, port, path, response)6019return response.status == 2006020and response.body6021and response.body:find("./live/index2.html?Language=", 1, true)6022and (response.body:find("%Wlocation%.replace%((['\"])%./live/index2%.html%?Language=%d+%1")6023or response.body:find("%Wwindow%.open%((['\"])%./live/index2%.html%?Language=%d+%1"))6024and response.body:lower():find("<title>%a%a%-%a%w+ ")6025end,6026login_combos = {6027{username = "admin", password = "12345"}6028},6029login_check = function (host, port, path, user, pass)6030return try_http_auth(host, port,6031url.absolute(path, "live/index2.html?Language=0"),6032user, pass, false)6033end6034})60356036table.insert(fingerprints, {6037name = "Sanyo Network Camera (no auth)",6038category = "security",6039paths = {6040{path = "/"}6041},6042target_check = function (host, port, path, response)6043if not (response.status == 2006044and response.body6045and response.body:find("SANYO", 1, true)6046and response.body:lower():find("<title>sanyo +network camera</title>")6047and get_tag(response.body, "form", {name="^lang_set$"})) then6048return false6049end6050local resp = http_get_simple(host, port,6051url.absolute(path, "cgi-bin/change_id.cgi"))6052return resp.status == 2006053end,6054login_combos = {6055{username = "", password = ""}6056},6057login_check = function (host, port, path, user, pass)6058return true6059end6060})60616062table.insert(fingerprints, {6063name = "Sanyo Network Camera (admin auth)",6064category = "security",6065paths = {6066{path = "/"}6067},6068target_check = function (host, port, path, response)6069if not (response.status == 2006070and response.body6071and response.body:find("SANYO", 1, true)6072and response.body:lower():find("<title>sanyo +network camera</title>")6073and get_tag(response.body, "form", {name="^lang_set$"})) then6074return false6075end6076local resp = http_get_simple(host, port,6077url.absolute(path, "cgi-bin/change_id.cgi"))6078return http_auth_realm(resp) == "You need advanced ID"6079end,6080login_combos = {6081{username = "admin", password = "admin"},6082{username = "admin2", password = "admin2"},6083{username = "admin3", password = "admin3"},6084{username = "operator", password = "operator"},6085{username = "guest", password = "guest"}6086},6087login_check = function (host, port, path, user, pass)6088local lurl = url.absolute(path, "cgi-bin/change_id.cgi?" .. math.floor(stdnse.clock_ms()))6089return try_http_auth(host, port, lurl, user, pass, false)6090end6091})60926093table.insert(fingerprints, {6094name = "Sanyo Network Camera (user auth)",6095category = "security",6096paths = {6097{path = "/"}6098},6099target_check = function (host, port, path, response)6100return http_auth_realm(response) == "You need ID"6101and response.body6102and response.body:lower():find("<title>sanyo network camera</title>", 1, true)6103end,6104login_combos = {6105{username = "admin", password = "admin"},6106{username = "admin2", password = "admin2"},6107{username = "admin3", password = "admin3"},6108{username = "operator", password = "operator"},6109{username = "guest", password = "guest"}6110},6111login_check = function (host, port, path, user, pass)6112return try_http_auth(host, port, path, user, pass, false)6113end6114})61156116table.insert(fingerprints, {6117name = "Sony Network Camera (Boa 1)",6118cpe = "cpe:/h:sony:snc_*",6119category = "security",6120paths = {6121{path = "/en/index.html"}6122},6123target_check = function (host, port, path, response)6124return response.status == 2006125and (response.header["server"] or ""):find("^Boa/%d+%.")6126and response.body6127and response.body:lower():find("%ssrc%s*=%s*(['\"])indexbar%.html%1")6128end,6129login_combos = {6130{username = "admin", password = "admin"}6131},6132login_check = function (host, port, path, user, pass)6133return try_http_auth(host, port, url.absolute(path, "l4/index.html"),6134user, pass, false)6135end6136})61376138table.insert(fingerprints, {6139name = "Sony Network Camera (Boa 2)",6140cpe = "cpe:/h:sony:snc_*",6141category = "security",6142paths = {6143{path = "/en/index.html"}6144},6145target_check = function (host, port, path, response)6146return response.status == 2006147and (response.header["server"] or ""):find("^Boa/%d+%.")6148and response.body6149and response.body:lower():find("<title>sony network camera snc-", 1, true)6150end,6151login_combos = {6152{username = "admin", password = "admin"}6153},6154login_check = function (host, port, path, user, pass)6155local resp1 = http_get_simple(host, port, path)6156if not (resp1.status == 200 and resp1.body) then return false end6157local _, lurl = resp1.body:match("=%s*window%.open%(%s*(['\"])(.-)%1")6158if not lurl then return false end6159lurl = url.absolute(path, lurl)6160return try_http_auth(host, port, lurl, user, pass, false)6161end6162})61636164table.insert(fingerprints, {6165name = "Sony Network Camera (NetEVI/Virgo)",6166cpe = "cpe:/h:sony:snc_*",6167category = "security",6168paths = {6169{path = "/index.html"}6170},6171target_check = function (host, port, path, response)6172local server = response.header["server"] or ""6173return response.status == 2006174and server:find("^NetEVI/%d+%.") or server:find("^Virgo/%d+%.")6175and response.body6176and response.body:lower():find("<title>sony network camera snc-", 1, true)6177end,6178login_combos = {6179{username = "admin", password = "admin"}6180},6181login_check = function (host, port, path, user, pass)6182return try_http_auth(host, port, url.absolute(path, "home/l4/admin.html"),6183user, pass, false)6184end6185})61866187table.insert(fingerprints, {6188name = "Sony Network Camera (thttpd)",6189cpe = "cpe:/h:sony:snc_*",6190category = "security",6191paths = {6192{path = "/"}6193},6194target_check = function (host, port, path, response)6195return response.status == 2006196and (response.header["server"] or ""):find("^thttpd/%d+%.")6197and response.body6198and response.body:find("adm/file.cgi?next_file=setting.htm", 1, true)6199and response.body:lower():find("<title>sony network camera snc-", 1, true)6200end,6201login_combos = {6202{username = "admin", password = "admin"}6203},6204login_check = function (host, port, path, user, pass)6205return try_http_auth(host, port,6206url.absolute(path, "adm/file.cgi?next_file=setting.htm"),6207user, pass, false)6208end6209})62106211table.insert(fingerprints, {6212name = "Basler Camera",6213category = "security",6214paths = {6215{path = "/"}6216},6217target_check = function (host, port, path, response)6218return response.status == 2006219and response.body6220and response.body:lower():find("<title>[^<]- web client [^<]- basler ag</title>")6221end,6222login_combos = {6223{username = "admin", password = "admin"}6224},6225login_check = function (host, port, path, user, pass)6226local resp = http_post_simple(host, port,6227url.absolute(path, "cgi-bin/auth_if.cgi?Login"),6228nil, {["Auth.Username"]=user, ["Auth.Password"]=pass})6229return resp.status == 2006230and (resp.body or ""):find("[{,]%s*success%s*:%s*true%s*[,}]")6231end6232})62336234table.insert(fingerprints, {6235name = "IQinVision Camera (var.1)",6236category = "security",6237paths = {6238{path = "/"}6239},6240target_check = function (host, port, path, response)6241local server = response.header["server"] or ""6242return response.status == 4016243and response.body6244and (server:find("^IQinVision Embedded ")6245and response.body:find("<xmp>%s*Please Authenticate%s*</xmp>")6246or server:find("^IQhttpD/%d+%.")6247and response.body:find("Authorization required for the URL", 1, true))6248end,6249login_combos = {6250{username = "login", password = "access"},6251{username = "root", password = "system"}6252},6253login_check = function (host, port, path, user, pass)6254return try_http_auth(host, port, path, user, pass, false)6255end6256})62576258table.insert(fingerprints, {6259name = "IQinVision Camera (var.2)",6260category = "security",6261paths = {6262{path = "/"}6263},6264target_check = function (host, port, path, response)6265return have_openssl6266and response.status == 4036267and (response.header["server"] or ""):find("^IQinVision Embedded ")6268and get_cookie(response, "SrvrNonce", "^%x+")6269end,6270login_combos = {6271{username = "login", password = "access"},6272{username = "root", password = "system"}6273},6274login_check = function (host, port, path, user, pass)6275local resp1 = http_get_simple(host, port, path)6276local nonce = get_cookie(resp1, "SrvrNonce")6277if not nonce then return false end6278local creds = stdnse.tohex(openssl.md5(table.concat({nonce, user,6279pass:upper()}, ":")))6280local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)6281local resp2 = http_get_simple(host, port, path, {cookies=cookies})6282return resp2.status == 2006283end6284})62856286table.insert(fingerprints, {6287name = "IQinVision Camera (var.3)",6288category = "security",6289paths = {6290{path = "/"}6291},6292target_check = function (host, port, path, response)6293local server = response.header["server"] or ""6294if not (response.status == 2006295and response.body6296and (server:find("^IQinVision Embedded ")6297and response.body:find(">IQ", 1, true)6298and response.body:lower():find("<title>iq", 1, true)6299or server:find("^IQhttpD/%d+%.")6300and response.body:find("%Wself%.location%s*=%s*(['\"])dptzvid%.html%1"))) then6301return false6302end6303local resp = http_get_simple(host, port, url.absolute(path, "accessset.html"))6304return resp.status == 4016305end,6306login_combos = {6307{username = "root", password = "system"}6308},6309login_check = function (host, port, path, user, pass)6310return try_http_auth(host, port, url.absolute(path, "accessset.html"),6311user, pass, false)6312end6313})63146315table.insert(fingerprints, {6316name = "IQinVision Camera (var.4)",6317category = "security",6318paths = {6319{path = "/"}6320},6321target_check = function (host, port, path, response)6322if not (have_openssl6323and response.status == 2006324and (response.header["server"] or ""):find("^IQinVision Embedded ")6325and response.body6326and response.body:find(">IQ", 1, true)6327and response.body:lower():find("<title>iq", 1, true)) then6328return false6329end6330local resp = http_get_simple(host, port, url.absolute(path, "accessset.html"))6331return resp.status == 4036332and get_cookie(resp, "SrvrNonce", "^%x+")6333end,6334login_combos = {6335{username = "root", password = "system"}6336},6337login_check = function (host, port, path, user, pass)6338local lurl = url.absolute(path, "accessset.html")6339local resp1 = http_get_simple(host, port, lurl)6340local nonce = get_cookie(resp1, "SrvrNonce")6341if not nonce then return false end6342local creds = stdnse.tohex(openssl.md5(table.concat({nonce, user,6343pass:upper()}, ":")))6344local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)6345local resp2 = http_get_simple(host, port, lurl, {cookies=cookies})6346return resp2.status == 2006347end6348})63496350table.insert(fingerprints, {6351name = "Sentry360 FS-IP5000 Camera",6352category = "security",6353paths = {6354{path = "/"}6355},6356target_check = function (host, port, path, response)6357return response.status == 2006358and response.header["server"] == "Sentry360"6359and response.body6360and get_tag(response.body, "img", {src="^logo_cam_page%.png$"})6361end,6362login_combos = {6363{username = "Admin", password = "1234"}6364},6365login_check = function (host, port, path, user, pass)6366local rnd1 = math.random(10000000, 99999999)6367local rnd2 = math.random(10000000, 99999999)6368local lurl = url.absolute(path, ("load.set?rnd=%d&rnd=%d"):format(rnd1, rnd2))6369return try_http_auth(host, port, lurl, user, pass, false)6370end6371})63726373table.insert(fingerprints, {6374name = "SerVision TVG",6375cpe = "cpe:/o:servision:hvg_video_gateway_firmware",6376category = "security",6377paths = {6378{path = "/"}6379},6380target_check = function (host, port, path, response)6381return response.status == 2006382and (response.header["server"] or ""):find("^2%.2%.")6383and response.body6384and response.body:find("TO_LOAD", 1, true)6385and get_tag(response.body, "input", {name="^user_username$"})6386end,6387login_combos = {6388{username = "svuser", password = "servconf"},6389{username = "anybody", password = "Bantham"}6390},6391login_check = function (host, port, path, user, pass)6392local form = {user_username=user,6393user_password=pass,6394LOADED=1,6395TO_LOAD="index.htm"}6396local resp = http_post_simple(host, port, url.absolute(path, "index.htm"),6397nil, form)6398return resp.status == 2016399and (resp.body or ""):find("%WloadMain%((['\"])main%.htm%1%)")6400end6401})64026403table.insert(fingerprints, {6404name = "Speco IP Camera",6405category = "security",6406paths = {6407{path = "/"}6408},6409target_check = function (host, port, path, response)6410return response.status == 2006411and response.body6412and response.body:find('src="newlogin.html"', 1, true)6413and response.body:lower():find("<title>speco ip camera</title>", 1, true)6414end,6415login_combos = {6416{username = "admin", password = "1234"}6417},6418login_check = function (host, port, path, user, pass)6419local resp = http_get_simple(host, port,6420url.absolute(path, "httpapi?GetUserLevel&ipAddress="),6421{auth={username=user, password=pass}})6422return resp.status == 2006423and (resp.body or ""):lower():find("userlevel:", 1, true)6424end6425})64266427table.insert(fingerprints, {6428name = "Brickcom Camera",6429cpe = "cpe:/o:brickom:*",6430category = "security",6431paths = {6432{path = "/"}6433},6434target_check = function (host, port, path, response)6435return (http_auth_realm(response) or ""):find("^Brickcom%s")6436end,6437login_combos = {6438{username = "admin", password = "admin"}6439},6440login_check = function (host, port, path, user, pass)6441return try_http_auth(host, port, path, user, pass, false)6442end6443})64446445table.insert(fingerprints, {6446name = "ACTi Camera",6447category = "security",6448paths = {6449{path = "/"}6450},6451target_check = function (host, port, path, response)6452return response.status == 2006453and response.body6454and response.body:find('gPwd="123456"', 1, true)6455and response.body:lower():find("<title>web configurator</title>", 1, true)6456end,6457login_combos = {6458{username = "admin", password = "123456"}6459},6460login_check = function (host, port, path, user, pass)6461local lurl = ("cgi-bin/system?USER=%s&PWD=%s&LOGIN&SYSTEM_INFO"):format(6462url.escape(user), url.escape(pass))6463local resp = http_get_simple(host, port, url.absolute(path, lurl))6464return resp.status == 2006465and (resp.body or ""):find("LOGIN='1'", 1, true)6466end6467})64686469table.insert(fingerprints, {6470name = "Ovislink AirLive BU",6471cpe = "cpe:/h:ovislink:airlive_bu-*",6472category = "security",6473paths = {6474{path = "/"}6475},6476target_check = function (host, port, path, response)6477return response.status == 2006478and (response.header["server"] or ""):find("^Boa/%d+%.")6479and response.body6480and response.body:find("controlmenu.htm", 1, true)6481and get_tag(response.body, "frame", {src="^controlmenu%.htm$"})6482and response.body:lower():find("<title>airlive</title>", 1, true)6483end,6484login_combos = {6485{username = "admin", password = "airlive"}6486},6487login_check = function (host, port, path, user, pass)6488return try_http_auth(host, port, url.absolute(path, "setting.htm"),6489user, pass, false)6490end6491})64926493table.insert(fingerprints, {6494name = "American Dynamics IP Dome",6495category = "security",6496paths = {6497{path = "/"}6498},6499target_check = function (host, port, path, response)6500return response.status == 2006501and response.body6502and response.body:find("gbl_locale", 1, true)6503and response.body:lower():find("<title>american dynamics", 1, true)6504end,6505login_combos = {6506{username = "admin", password = "admin"}6507},6508login_check = function (host, port, path, user, pass)6509local form = {gbl_locale=1,6510accessRoute="",6511username=user,6512password=pass}6513local resp = http_post_simple(host, port, url.absolute(path, "index.php"),6514nil, form)6515return resp.status == 2006516and (resp.body or ""):find("gbl_username%s*=")6517end6518})65196520table.insert(fingerprints, {6521name = "exacqVision",6522category = "security",6523paths = {6524{path = "/"}6525},6526target_check = function (host, port, path, response)6527if not (response.status == 2006528and response.body6529and response.body:find("%Wlocation%.replace%(%s*(['\"])login%.web%1%s*%)%s*;")) then6530return false6531end6532local resp = http_get_simple(host, port, url.absolute(path, "login.web"))6533return resp.status == 2006534and resp.body6535and resp.body:find("exacqVision", 1, true)6536and resp.body:lower():find("<title>login</title>", 1, true)6537end,6538login_combos = {6539{username = "admin", password = "admin256"}6540},6541login_check = function (host, port, path, user, pass)6542local form = {u=user,6543p=pass,6544l=1,6545s=0,6546output="json",6547responseVersion=2,6548save=1}6549local resp = http_post_simple(host, port, url.absolute(path, "login.web"),6550nil, form)6551if not (resp.status == 200 and resp.body) then return false end6552local jstatus, jout = json.parse(resp.body)6553return jstatus and jout.login and jout.success6554end6555})65566557table.insert(fingerprints, {6558name = "GeoVision Camera",6559category = "security",6560paths = {6561{path = "/"}6562},6563target_check = function (host, port, path, response)6564return response.status == 2006565and response.header["server"] == "GeoHttpServer"6566and response.body6567and (response.body:find('action="webcam_login"', 1, true)6568or response.body:find('action="phoneinfo"', 1, true))6569end,6570login_combos = {6571{username = "admin", password = "admin"}6572},6573login_check = function (host, port, path, user, pass)6574local form = {id=user,6575pwd=pass,6576ViewType=2,6577Login="Login"}6578local resp = http_post_simple(host, port,6579url.absolute(path, "webcam_login"),6580nil, form)6581return resp.status == 2006582and resp.body6583and (resp.body:find('%sname%s*=%s*"IDKey"%f[%s][^>]-%svalue%s*=%s*"[%x-]+"')6584or resp.body:find('%?IDKey=[%x-]+'))6585end6586})65876588table.insert(fingerprints, {6589name = "GeoVision Web-Manager",6590category = "security",6591paths = {6592{path = "/"}6593},6594target_check = function (host, port, path, response)6595return have_openssl6596and response.status == 2006597and response.body6598and response.body:find("GeoVision", 1, true)6599and response.body:find("%Wlocation%.href%s*=%s*(['\"])ssi%.cgi/Login%.htm%1")6600and response.body:lower():find("<title>geovision ", 1, true)6601end,6602login_combos = {6603{username = "guest", password = "guest"},6604{username = "admin", password = "admin"}6605},6606login_check = function (host, port, path, user, pass)6607local resp1 = http_get_simple(host, port,6608url.absolute(path, "ssi.cgi/Login.htm"))6609if not (resp1.status == 200 and resp1.body) then return false end6610local nonce1, nonce2 = resp1.body:match("%Wvar%s+cc1%s*=%s*['\"](%x+)['\"]%s*;%s*var%s+cc2%s*=%s*['\"](%x+)['\"]")6611if not nonce1 then return false end6612local hashfnc = function (p, a, b) return stdnse.tohex(openssl.md5(table.concat({a,p:lower(),b}))):upper() end6613local form = {username="",6614password="",6615Apply="Apply",6616umd5=hashfnc(user, nonce1, nonce2),6617pmd5=hashfnc(pass, nonce2, nonce1),6618browser=1}6619local resp2 = http_post_simple(host, port,6620url.absolute(path, "LoginPC.cgi"),6621nil, form)6622return resp2.status == 2006623and get_cookie(resp2, "CLIENT_ID", "^%d+$")6624end6625})66266627table.insert(fingerprints, {6628name = "GeoVision WebControl",6629category = "security",6630paths = {6631{path = "/"}6632},6633target_check = function (host, port, path, response)6634return (http_auth_realm(response) or ""):find("^Welcome to GV%-%w+ WebControl$")6635end,6636login_combos = {6637{username = "admin", password = "admin"}6638},6639login_check = function (host, port, path, user, pass)6640return try_http_auth(host, port, path, user, pass, false)6641end6642})66436644table.insert(fingerprints, {6645name = "Arecont Vision (no auth)",6646category = "security",6647paths = {6648{path = "/"}6649},6650target_check = function (host, port, path, response)6651return response.status == 2006652and response.body6653and response.body:find(">Arecont Vision", 1, true)6654and response.body:lower():find("<title>arecont vision camera</title>", 1, true)6655and get_tag(response.body, "div", {class="^avmenu$"})6656end,6657login_combos = {6658{username = "", password = ""}6659},6660login_check = function (host, port, path, user, pass)6661return true6662end6663})66646665table.insert(fingerprints, {6666name = "Arecont Vision (basic auth)",6667category = "security",6668paths = {6669{path = "/"}6670},6671target_check = function (host, port, path, response)6672return http_auth_realm(response) == "Arecont Vision"6673end,6674login_combos = {6675{username = "admin", password = ""},6676{username = "viewer", password = ""}6677},6678login_check = function (host, port, path, user, pass)6679return try_http_auth(host, port, path, user, pass, false)6680end6681})66826683table.insert(fingerprints, {6684name = "Avigilon Camera",6685category = "security",6686paths = {6687{path = "/"}6688},6689target_check = function (host, port, path, response)6690return (http_auth_realm(response) or ""):find("^Avigilon%-%d+$")6691end,6692login_combos = {6693{username = "admin", password = "admin"}6694},6695login_check = function (host, port, path, user, pass)6696return try_http_auth(host, port, path, user, pass, true)6697end6698})66996700table.insert(fingerprints, {6701name = "Canon Camera",6702cpe = "cpe:/h:canon:network_camera_server_vb*",6703category = "security",6704paths = {6705{path = "/"}6706},6707target_check = function (host, port, path, response)6708return response.status == 2006709and response.body6710and response.body:find("img/canon_logo.gif", 1, true)6711and get_tag(response.body, "img", {src="^img/canon_logo%.gif$"})6712and response.body:lower():find("<title>network camera</title>", 1, true)6713end,6714login_combos = {6715{username = "root", password = "camera"}6716},6717login_check = function (host, port, path, user, pass)6718return try_http_auth(host, port,6719url.absolute(path, "admin/index.html?lang=en"),6720user, pass, "any")6721end6722})67236724table.insert(fingerprints, {6725name = "Brovotech IPCAM",6726category = "security",6727paths = {6728{path = "/"}6729},6730target_check = function (host, port, path, response)6731return response.status == 3026732and (response.header["location"] or ""):find("/cn/viewer_index%.asp$")6733end,6734login_combos = {6735{username = "admin", password = "admin"}6736},6737login_check = function (host, port, path, user, pass)6738return try_http_auth(host, port, url.absolute(path, "cn/viewer_index.asp"),6739user, pass, true)6740end6741})67426743table.insert(fingerprints, {6744name = "Grandstream Camera",6745cpe = "cpe:/o:grandstream:gxv_device_firmware",6746category = "security",6747paths = {6748{path = "/index.html"}6749},6750target_check = function (host, port, path, response)6751return response.status == 2006752and response.header["server"] == "GS-Webs"6753and response.body6754and response.body:lower():find("%stype%s*=%s*['\"]application/x%-vnd%-npgs_")6755end,6756login_combos = {6757{username = "admin", password = "admin"}6758},6759login_check = function (host, port, path, user, pass)6760return try_http_auth(host, port, url.absolute(path, "Pages/system.html"),6761user, pass, false)6762end6763})67646765table.insert(fingerprints, {6766name = "Hikvision (var.1)",6767category = "security",6768paths = {6769{path = "/index.asp"}6770},6771target_check = function (host, port, path, response)6772return response.status == 2006773and response.body6774and response.body:find("%Wwindow%.location%.href%s*=%s*['\"]doc/page/login%.asp['\"?]")6775and response.body:lower():find("<title>index</title>", 1, true)6776end,6777login_combos = {6778{username = "admin", password = "12345"}6779},6780login_check = function (host, port, path, user, pass)6781local resp = http_get_simple(host, port,6782url.absolute(path, "PSIA/Custom/SelfExt/userCheck"),6783{auth={username=user, password=pass}})6784return resp.status == 2006785and (resp.body or ""):lower():find("<statusvalue>200</statusvalue>", 1, true)6786end6787})67886789table.insert(fingerprints, {6790name = "Hikvision (var.2)",6791category = "security",6792paths = {6793{path = "/"}6794},6795target_check = function (host, port, path, response)6796return response.status == 2006797and response.body6798and response.body:find("%Wwindow%.location%.href%s*=%s*['\"]doc/page/login%.asp['\"?]")6799and response.body:lower():find("<title>index</title>", 1, true)6800end,6801login_combos = {6802{username = "admin", password = "12345"}6803},6804login_check = function (host, port, path, user, pass)6805local resp = http_get_simple(host, port,6806url.absolute(path, "ISAPI/Security/userCheck"),6807{auth={username=user, password=pass}})6808return resp.status == 2006809and (resp.body or ""):lower():find("<statusvalue>200</statusvalue>", 1, true)6810end6811})68126813table.insert(fingerprints, {6814name = "TI Megapixel IP Camera",6815category = "security",6816paths = {6817{path = "/"}6818},6819target_check = function (host, port, path, response)6820return http_auth_realm(response) == "Megapixel IP Camera"6821and response.header["server"] == "HKVision-Webs"6822end,6823login_combos = {6824{username = "admin", password = "admin"}6825},6826login_check = function (host, port, path, user, pass)6827return try_http_auth(host, port, path, user, pass, false)6828end6829})68306831table.insert(fingerprints, {6832name = "MayGion Camera (no auth)",6833category = "security",6834paths = {6835{path = "/"}6836},6837target_check = function (host, port, path, response)6838return response.status == 2006839and response.header["server"] == "WebServer(IPCamera_Logo)"6840and response.body6841and get_tag(response.body, "iframe", {src="^video%.htm$"})6842end,6843login_combos = {6844{username = "", password = ""}6845},6846login_check = function (host, port, path, user, pass)6847return true6848end6849})68506851table.insert(fingerprints, {6852name = "MayGion Camera",6853category = "security",6854paths = {6855{path = "/"}6856},6857target_check = function (host, port, path, response)6858return response.status == 2006859and response.header["server"] == "WebServer(IPCamera_Logo)"6860and response.body6861and response.body:find("login.xml", 1, true)6862end,6863login_combos = {6864{username = "admin", password = "admin"}6865},6866login_check = function (host, port, path, user, pass)6867local form = {user=user,6868usr=user,6869password=pass,6870pwd=pass}6871local lurl = "login.xml?" .. url.build_query(form)6872local resp = http_get_simple(host, port, url.absolute(path, lurl))6873return resp.status == 2006874and get_cookie(resp, "user") == user6875and get_cookie(resp, "password") == pass6876and get_cookie(resp, "usrLevel") == "0"6877end6878})68796880table.insert(fingerprints, {6881name = "OEM Boa IP Camera (var.1)",6882category = "security",6883paths = {6884{path = "/"}6885},6886target_check = function (host, port, path, response)6887return response.status == 4016888and (http_auth_realm(response) or ""):find(" IP Camera$")6889and (response.header["server"] or ""):find("^Boa/%d+%.")6890end,6891login_combos = {6892{username = "admin", password = "admin"}6893},6894login_check = function (host, port, path, user, pass)6895return try_http_auth(host, port, path, user, pass, false)6896end6897})68986899table.insert(fingerprints, {6900name = "OEM Boa IP Camera (var.2)",6901category = "security",6902paths = {6903{path = "/"}6904},6905target_check = function (host, port, path, response)6906return response.status == 2006907and (response.header["server"] or ""):find("^Boa/%d+%.")6908and get_tag(response.body, "script", {src="^profile$"})6909and get_tag(response.body, "img", {id="^setting$",onclick="%f[%w]window%.location=(['\"])setting%.htm%1$"})6910end,6911login_combos = {6912{username = "admin", password = "admin"}6913},6914login_check = function (host, port, path, user, pass)6915return try_http_auth(host, port, url.absolute(path, "setting.htm"),6916user, pass, false)6917end6918})69196920table.insert(fingerprints, {6921name = "OEM Boa IP Camera (var.3)",6922category = "security",6923paths = {6924{path = "/"}6925},6926target_check = function (host, port, path, response)6927return response.status == 2006928and (response.header["server"] or ""):find("^Boa/%d+%.")6929and get_tag(response.body, "script", {src="^profile$"})6930and response.body:lower():find("<title>ip camera viewer</title>", 1, true)6931end,6932login_combos = {6933{username = "admin", password = "12345"}6934},6935login_check = function (host, port, path, user, pass)6936return try_http_auth(host, port, url.absolute(path, "setting.htm"),6937user, pass, false)6938end6939})69406941table.insert(fingerprints, {6942name = "OEM Netcam",6943category = "security",6944paths = {6945{path = "/"},6946},6947target_check = function (host, port, path, response)6948return (http_auth_realm(response) or ""):find("^[Nn]etcam$")6949end,6950login_combos = {6951{username = "admin", password = "admin"}6952},6953login_check = function (host, port, path, user, pass)6954return try_http_auth(host, port, path, user, pass, false)6955end6956})69576958table.insert(fingerprints, {6959name = "Planet IP Cam",6960category = "security",6961paths = {6962{path = "/"},6963},6964target_check = function (host, port, path, response)6965return http_auth_realm(response) == "PLANET IP CAM"6966end,6967login_combos = {6968{username = "admin", password = "admin"}6969},6970login_check = function (host, port, path, user, pass)6971return try_http_auth(host, port, path, user, pass, false)6972end6973})69746975table.insert(fingerprints, {6976name = "Planet IP Surveillance",6977category = "security",6978paths = {6979{path = "/"},6980},6981target_check = function (host, port, path, response)6982return response.status == 2006983and response.body6984and response.body:find("ipcam_language", 1, true)6985and get_tag(response.body, "frame", {src="^asp/view%.asp$"})6986and response.body:lower():find("<title>planet ip surveillance web management</title>", 1, true)6987end,6988login_combos = {6989{username = "admin", password = ""},6990{username = "admin", password = "admin"}6991},6992login_check = function (host, port, path, user, pass)6993return try_http_auth(host, port, url.absolute(path, "asp/set.asp"),6994user, pass, true)6995end6996})69976998table.insert(fingerprints, {6999name = "TP-Link IPC",7000category = "security",7001paths = {7002{path = "/"}7003},7004target_check = function (host, port, path, response)7005return response.status == 2007006and response.body7007and response.body:find("/web-static/dynaform/class.js", 1, true)7008and response.body:lower():find("<title>ipc</title>", 1, true)7009end,7010login_combos = {7011{username = "admin", password = ""}7012},7013login_check = function (host, port, path, user, pass)7014local a = "RDpbLfCPsJZ7fiv"7015local b = pass7016local pwdlen = math.max(#a, #b)7017a = table.pack(string.byte(a .. ("\187"):rep(pwdlen - #a), 1, -1))7018b = table.pack(string.byte(b .. ("\187"):rep(pwdlen - #b), 1, -1))7019local pad = "yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW"7020local pwd = {}7021for i = 1, pwdlen do7022table.insert(pwd, pad:byte(1 + (a[i] ~ b[i]) % #pad))7023end7024local header = {["Accept"]="application/json, text/plain, */*",7025["Content-Type"]="application/json;charset=utf-8"}7026local jin = {method="do",7027login={username=user,7028password=string.char(table.unpack(pwd))}}7029json.make_object(jin)7030local resp = http_post_simple(host, port, path, {header=header},7031json.generate(jin))7032if not (resp.status == 200 and resp.body) then return false end7033local jstatus, jout = json.parse(resp.body)7034return jstatus and jout.stok and jout.error_code == 07035end7036})70377038table.insert(fingerprints, {7039name = "Allnet Camera",7040category = "security",7041paths = {7042{path = "/"}7043},7044target_check = function (host, port, path, response)7045return http_auth_realm(response) == "NetworkPTZ"7046end,7047login_combos = {7048{username = "admin", password = "admin"}7049},7050login_check = function (host, port, path, user, pass)7051return try_http_auth(host, port, path, user, pass, false)7052end7053})70547055table.insert(fingerprints, {7056name = "D-Link Camera",7057cpe = "cpe:/h:d-link:dcs-*",7058category = "security",7059paths = {7060{path = "/"}7061},7062target_check = function (host, port, path, response)7063return (http_auth_realm(response) or ""):find("^DCS%-%d+%u?%f[_\0]")7064end,7065login_combos = {7066{username = "admin", password = "admin"},7067{username = "admin", password = ""}7068},7069login_check = function (host, port, path, user, pass)7070return try_http_auth(host, port, path, user, pass, false)7071end7072})70737074table.insert(fingerprints, {7075name = "Microseven IP camera",7076category = "security",7077paths = {7078{path = "/"}7079},7080target_check = function (host, port, path, response)7081return response.status == 2007082and response.body7083and response.body:find("/hi3510/", 1, true)7084and get_tag(response.body, "script", {src="/cgi%-bin/hi3510/param%.cgi%?cmd=getuserinfo$"})7085end,7086login_combos = {7087{username = "admin", password = "password"},7088{username = "guest", password = "guest"}7089},7090login_check = function (host, port, path, user, pass)7091return try_http_auth(host, port,7092url.absolute(path, "cgi-bin/hi3510/param.cgi?cmd=getuserinfo"),7093user, pass, false)7094end7095})70967097table.insert(fingerprints, {7098name = "Milesight Camera (var.1)",7099category = "security",7100paths = {7101{path = "/"}7102},7103target_check = function (host, port, path, response)7104return response.status == 2007105and response.body7106and (response.body:find(">Milesight Network Camera", 1, true)7107or response.body:find(">IPCAM Network Camera", 1, true))7108and get_tag(response.body, "input", {id="^secret$"})7109and not get_tag(response.body, "script", {src="/javascript/md5%.js%?"})7110end,7111login_combos = {7112{username = "admin", password = "ms1234"},7113{username = "operator", password = "ms1234"},7114{username = "viewer", password = "ms1234"}7115},7116login_check = function (host, port, path, user, pass)7117local userno = {admin=0, operator=1, viewer=2}7118local creds = {tostring(userno[user]),7119url.escape(user),7120url.escape(pass)}7121local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")7122local resp = http_get_simple(host, port, url.absolute(path, lurl))7123return resp.status == 2007124and resp.body:find("OK checkpassword", 1, true)7125end7126})71277128table.insert(fingerprints, {7129name = "Milesight Camera (var.2)",7130category = "security",7131paths = {7132{path = "/"}7133},7134target_check = function (host, port, path, response)7135return have_openssl7136and response.status == 2007137and response.body7138and (response.body:find(">Milesight Network Camera", 1, true)7139or response.body:find(">IPCAM Network Camera", 1, true))7140and get_tag(response.body, "input", {id="^secret$"})7141and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})7142end,7143login_combos = {7144{username = "admin", password = "ms1234"},7145{username = "operator", password = "ms1234"},7146{username = "viewer", password = "ms1234"}7147},7148login_check = function (host, port, path, user, pass)7149local userno = {admin=0, operator=1, viewer=2}7150local creds = {tostring(userno[user]),7151url.escape(user),7152stdnse.tohex(openssl.md5(pass))}7153local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")7154local resp = http_get_simple(host, port, url.absolute(path, lurl))7155return resp.status == 2007156and resp.body:find("OK checkpassword", 1, true)7157end7158})71597160table.insert(fingerprints, {7161name = "Milesight Camera (Alphafinity)",7162category = "security",7163paths = {7164{path = "/"}7165},7166target_check = function (host, port, path, response)7167return have_openssl7168and response.status == 2007169and response.body7170and response.body:find(">Alphafinity Network Camera", 1, true)7171and get_tag(response.body, "input", {id="^secret$"})7172and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})7173end,7174login_combos = {7175{username = "admin", password = "admin"}7176},7177login_check = function (host, port, path, user, pass)7178local userno = {admin=0, operator=1, viewer=2}7179local creds = {tostring(userno[user]),7180url.escape(user),7181stdnse.tohex(openssl.md5(pass))}7182local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")7183local resp = http_get_simple(host, port, url.absolute(path, lurl))7184return resp.status == 2007185and resp.body:find("OK checkpassword", 1, true)7186end7187})71887189table.insert(fingerprints, {7190name = "Milesight Camera (Beward)",7191category = "security",7192paths = {7193{path = "/"}7194},7195target_check = function (host, port, path, response)7196return have_openssl7197and response.status == 2007198and response.body7199and (response.body:find(">BEWARD Network HD camera", 1, true)7200or response.body:find(">Beward Network Camera", 1, true))7201and get_tag(response.body, "input", {id="^secret$"})7202and get_tag(response.body, "script", {src="/javascript/md5%.js%?"})7203end,7204login_combos = {7205{username = "admin", password = "admin"},7206{username = "testuser", password = "htyjdfwbz1"}7207},7208login_check = function (host, port, path, user, pass)7209local userno = {admin=0, testuser=1}7210local creds = {tostring(userno[user]),7211url.escape(user),7212stdnse.tohex(openssl.md5(pass))}7213local lurl = "vb.htm?language=ie&checkpassword=" .. table.concat(creds, ":")7214local resp = http_get_simple(host, port, url.absolute(path, lurl))7215return resp.status == 2007216and resp.body:find("OK checkpassword", 1, true)7217end7218})72197220table.insert(fingerprints, {7221name = "Beward SIP Door Station",7222category = "security",7223paths = {7224{path = "/"}7225},7226target_check = function (host, port, path, response)7227return response.status == 4017228and (http_auth_realm(response) or ""):find(" SIP Door Station %- %x+$")7229end,7230login_combos = {7231{username = "admin", password = "admin"}7232},7233login_check = function (host, port, path, user, pass)7234return try_http_auth(host, port, path, user, pass, true)7235end7236})72377238table.insert(fingerprints, {7239name = "OEM MegapixelIPCamera",7240category = "security",7241paths = {7242{path = "/"}7243},7244target_check = function (host, port, path, response)7245local realm = http_auth_realm(response)7246return response.status == 4017247and (response.header["server"] or ""):find("^Mbedthis%-Appweb/%d+%.")7248and (realm == "MegapixelIPCamera" or realm == "QuasarHDIPCamera")7249end,7250login_combos = {7251{username = "Admin", password = "1234"},7252{username = "admin", password = "admin"}7253},7254login_check = function (host, port, path, user, pass)7255return try_http_auth(host, port, path, user, pass, false)7256end7257})72587259table.insert(fingerprints, {7260name = "Philips InSight",7261cpe = "cpe:/h:philips:in.sight*",7262category = "security",7263paths = {7264{path = "/"}7265},7266target_check = function (host, port, path, response)7267return response.status == 2007268and (response.header["server"] or ""):find("^lighttpd/%d+%.")7269and response.body7270and response.body:find(">Philips ", 1, true)7271and response.body:lower():find("%salt%s*=%s*(['\"])philips insight wireless home monitor%1")7272end,7273login_combos = {7274{username = "admin", password = "M100-4674448"},7275{username = "user", password = "M100-4674448"}7276},7277login_check = function (host, port, path, user, pass)7278return try_http_auth(host, port, url.absolute(path, "cgi-bin/v1/camera"),7279user, pass, true)7280end7281})72827283table.insert(fingerprints, {7284name = "Planex CS",7285cpe = "cpe:/o:planex:cs-*",7286category = "security",7287paths = {7288{path = "/"}7289},7290target_check = function (host, port, path, response)7291return (http_auth_realm(response) or ""):find("^CS%-%u+%d+[%u%d]*$")7292end,7293login_combos = {7294{username = "admin", password = "password"},7295{username = "supervisor", password = "dangerous"}7296},7297login_check = function (host, port, path, user, pass)7298return try_http_auth(host, port, path, user, pass, false)7299end7300})73017302table.insert(fingerprints, {7303name = "Santec IPCamera",7304category = "security",7305paths = {7306{path = "/"}7307},7308target_check = function (host, port, path, response)7309return http_auth_realm(response) == "Santec-IPCamera"7310end,7311login_combos = {7312{username = "admin", password = "9999"}7313},7314login_check = function (host, port, path, user, pass)7315return try_http_auth(host, port, path, user, pass, false)7316end7317})73187319table.insert(fingerprints, {7320name = "HD IPC IP camera",7321category = "security",7322paths = {7323{path = "/"}7324},7325target_check = function (host, port, path, response)7326if not (response.status == 2007327and (response.header["server"] or ""):find("^thttpd/%d+%.")7328and response.body7329and get_refresh_url(response.body, "/web/index%.html$")) then7330return false7331end7332local resp = http_get_simple(host, port,7333url.absolute(path, "web/index.html"))7334return resp.status == 2007335and resp.body7336and resp.body:find("LonginPassword", 1, true)7337and get_tag(resp.body, "input", {id="^longinpassword$"})7338end,7339login_combos = {7340{username = "admin", password = "admin"},7341{username = "guest", password = "guest"}7342},7343login_check = function (host, port, path, user, pass)7344local form = {["-name"]=user,7345["-passwd"]=pass,7346["-time"]=math.floor(stdnse.clock_ms())}7347local lurl = url.absolute(path, "cgi-bin/hi3510/checkuser.cgi?" .. url.build_query(form))7348local resp = http_get_simple(host, port, lurl)7349return resp.status == 2007350and resp.body7351and resp.body:find("%f[%w]var%s+check%s*=%s*(['\"]?)1%1%s*;")7352and resp.body:find("%f[%w]var%s+authLevel%s*=%s*['\"]?[1-9]")7353end7354})73557356table.insert(fingerprints, {7357name = "3S Vision",7358category = "security",7359paths = {7360{path = "/"}7361},7362target_check = function (host, port, path, response)7363if response.header["server"] ~= "httpd" then return false end7364local realm = http_auth_realm(response) or ""7365return realm == "IP Video Server"7366or realm == "IP SPEED DOME"7367or realm:find("^[%w ]- IP Camera$")7368end,7369login_combos = {7370{username = "3sadmin", password = "27988303"},7371{username = "root", password = "root"}7372},7373login_check = function (host, port, path, user, pass)7374return try_http_auth(host, port, path, user, pass, false)7375end7376})73777378table.insert(fingerprints, {7379name = "Network Video Server (var.1)",7380category = "security",7381paths = {7382{path = "/login.asp"}7383},7384target_check = function (host, port, path, response)7385return response.status == 2007386and response.body7387and response.body:find("onLoginNVS", 1, true)7388and response.body:lower():find("<title>web service</title>", 1, true)7389and get_tag(response.body, "script", {["for"]="^WebCMS$", event="^CBK_LoginResult%("})7390end,7391login_combos = {7392{username = "admin", password = "admin"}7393},7394login_check = function (host, port, path, user, pass)7395local form = {username=user,7396password=pass,7397UserID=math.random(10000000, 99999999)}7398local lurl = url.absolute(path, "webs/loginCMS") .. "?"7399.. url.build_query(form)7400local resp = http_get_simple(host, port, lurl)7401return resp.status == 2007402and (resp.body or ""):find("<level>%d</level>")7403end7404})74057406table.insert(fingerprints, {7407name = "Network Video Server (var.2)",7408category = "security",7409paths = {7410{path = "/login.asp"}7411},7412target_check = function (host, port, path, response)7413return response.status == 2007414and response.body7415and response.body:find("onLoginNVS", 1, true)7416and response.body:lower():find("<title>web service</title>", 1, true)7417and get_tag(response.body, "script", {["for"]="^NetVideoX$", event="^CBK_LoginResult%("})7418end,7419login_combos = {7420{username = "admin", password = "admin"}7421},7422login_check = function (host, port, path, user, pass)7423local form = {username=user,7424password=pass,7425UserID=math.random(10000000, 99999999)}7426local lurl = url.absolute(path, "webs/httplogin") .. "?"7427.. url.build_query(form)7428local resp = http_get_simple(host, port, lurl)7429return resp.status == 2007430and (resp.body or ""):find("<level>%d</level>")7431end7432})74337434table.insert(fingerprints, {7435name = "Network Video Server (var.3)",7436category = "security",7437paths = {7438{path = "/login.asp"}7439},7440target_check = function (host, port, path, response)7441return response.status == 2007442and response.body7443and response.body:find("onLoginNVS", 1, true)7444and get_tag(response.body, "script", {event="^CallBackLoginState%("})7445and get_tag(response.body, "script", {src="^script/base64%.js$"})7446end,7447login_combos = {7448{username = "admin", password = "admin"}7449},7450login_check = function (host, port, path, user, pass)7451local form = {action="list",7452group="LOGIN",7453UserID=math.random(10000000, 99999999)}7454local lurl = url.absolute(path, "cgi-bin/login.cgi") .. "?"7455.. url.build_query(form)7456local resp = http_get_simple(host, port, lurl,7457{auth={username=user, password=pass}})7458return resp.status == 2007459and (resp.body or ""):find("%f[%w]root.ERR.no=0%f[^%w]")7460end7461})74627463table.insert(fingerprints, {7464name = "Pravis Systems DVR",7465category = "security",7466paths = {7467{path = "/"}7468},7469target_check = function (host, port, path, response)7470return response.status == 2007471and response.body7472and get_refresh_url(response.body, "/cgi%-bin/design/html_template/Login%.html$")7473and response.body:lower():find("<title>login cgicc form</title>", 1, true)7474end,7475login_combos = {7476{username = "admin", password = ""}7477},7478login_check = function (host, port, path, user, pass)7479local resp = http_post_simple(host, port,7480url.absolute(path, "cgi-bin/design/html_template/Login.cgi"),7481nil, {login_txt_id=user, login_txt_pw=pass})7482return resp.status == 2007483and resp.body7484and resp.body:find("%Wlocation%s*=%s*(['\"])webviewer%.cgi%1")7485end7486})74877488table.insert(fingerprints, {7489name = "Foscam Netwave (var.1)",7490cpe = "cpe:/o:foscam:ip_camera_firmware",7491category = "security",7492paths = {7493{path = "/"}7494},7495target_check = function (host, port, path, response)7496return response.status == 2007497and response.header["server"] == "Netwave IP Camera"7498and response.body7499and get_tag(response.body, "script", {src="^check_user%.cgi$"})7500end,7501login_combos = {7502{username = "admin", password = ""}7503},7504login_check = function (host, port, path, user, pass)7505return try_http_auth(host, port, url.absolute(path, "check_user.cgi"),7506user, pass, false)7507end7508})75097510table.insert(fingerprints, {7511name = "Foscam Netwave (var.2)",7512category = "security",7513paths = {7514{path = "/"}7515},7516target_check = function (host, port, path, response)7517return response.status == 2007518and response.header["server"] == "Netwave IP Camera"7519and response.body7520and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])index1%.htm%1")7521end,7522login_combos = {7523{username = "admin", password = ""}7524},7525login_check = function (host, port, path, user, pass)7526local lurl = url.absolute(path, "check_user.cgi") .. "?"7527.. url.build_query({user=user, pwd=pass})7528return try_http_auth(host, port, lurl, user, pass, false)7529end7530})75317532table.insert(fingerprints, {7533name = "Foscam IP Camera",7534category = "security",7535paths = {7536{path = "/"}7537},7538target_check = function (host, port, path, response)7539return response.status == 2007540and response.body7541and response.body:find("IPCam", 1, true)7542and response.body:lower():find("<title>ipcam client</title>", 1, true)7543and response.body:lower():find("%ssrc%s*=%s*['\"]js/main%.js['\"?]")7544end,7545login_combos = {7546{username = "admin", password = "admin"},7547{username = "admin", password = ""}7548},7549login_check = function (host, port, path, user, pass)7550local form = {usr=user,7551pwd=pass,7552cmd="logIn",7553usrName=user,7554groupId=string.sub(math.floor(stdnse.clock_ms()), -9)}7555local lurl = "cgi-bin/CGIProxy.fcgi?" .. url.build_query(form)7556local resp = http_get_simple(host, port, url.absolute(path, lurl))7557return resp.status == 2007558and (resp.body or ""):find("<logInResult>0</logInResult>", 1, true)7559end7560})75617562table.insert(fingerprints, {7563name = "ITX Web Remote Viewer",7564category = "security",7565paths = {7566{path = "/"}7567},7568target_check = function (host, port, path, response)7569if response.status == 2007570and get_refresh_url(response.body, "/redirect%.html$") then7571response = http_get_simple(host, port, url.absolute(path, "redirect.html"))7572end7573return http_auth_realm(response) == "WEB Remote Viewer"7574end,7575login_combos = {7576{username = "ADMIN", password = "1234"}7577},7578login_check = function (host, port, path, user, pass)7579return try_http_auth(host, port, url.absolute(path, "html/versioninfo.htm"),7580user, pass, false)7581end7582})75837584table.insert(fingerprints, {7585name = "JVC VN-xxx Camera",7586category = "security",7587paths = {7588{path = "/"}7589},7590target_check = function (host, port, path, response)7591return response.status == 2007592and (response.header["server"] or ""):find("^JVC VN%-%w+ API Server%f[/\0]")7593and response.body7594and get_refresh_url(response.body, "/cgi%-bin/%w+%.cgi%?%w+%.html$")7595end,7596login_combos = {7597{username = "admin", password = "jvc"}7598},7599login_check = function (host, port, path, user, pass)7600local resp = http_get_simple(host, port, path)7601local lurl = resp.status == 2007602and get_refresh_url(resp.body or "", "/cgi%-bin/%w+%.cgi%?%w+%.html$")7603if not lurl then return false end7604return try_http_auth(host, port, lurl, user, pass, false)7605end7606})76077608table.insert(fingerprints, {7609name = "JVC VR-8xx DVR",7610category = "security",7611paths = {7612{path = "/"}7613},7614target_check = function (host, port, path, response)7615return http_auth_realm(response) == "VR-8xx"7616end,7617login_combos = {7618{username = "admin", password = "jvc"}7619},7620login_check = function (host, port, path, user, pass)7621return try_http_auth(host, port, path, user, pass, false)7622end7623})76247625table.insert(fingerprints, {7626name = "JVC Broadcaster",7627category = "security",7628paths = {7629{path = "/"}7630},7631target_check = function (host, port, path, response)7632return (http_auth_realm(response) or ""):find("^JVC Broadcaster %d+%.%d+")7633end,7634login_combos = {7635{username = "admin", password = "jvc1234"}7636},7637login_check = function (host, port, path, user, pass)7638return try_http_auth(host, port, path, user, pass, false)7639end7640})76417642table.insert(fingerprints, {7643name = "OEM DVR",7644category = "security",7645paths = {7646{path = "/"}7647},7648target_check = function (host, port, path, response)7649return response.status == 2007650and response.body7651and response.body:find("%Wdocument%.location%.replace%(%s*(['\"])mlogin%.cgi%1%s*%)%s*;")7652and response.body:lower():find("<title>dvr login</title>", 1, true)7653end,7654login_combos = {7655{username = "admin", password = ""}7656},7657login_check = function (host, port, path, user, pass)7658local form = {c_userid=user,7659c_password=pass,7660c_target=2}7661local resp = http_post_simple(host, port,7662url.absolute(path, "direct_open_setup.cgi"),7663nil, form)7664return resp.status == 2007665and get_tag(resp.body or "", "script", {src="^setup%.js$"})7666end7667})76687669table.insert(fingerprints, {7670name = "Samsung DVR",7671cpe = "cpe:/h:samsung:dvr",7672category = "security",7673paths = {7674{path = "/"}7675},7676target_check = function (host, port, path, response)7677return have_openssl7678and response.status == 2007679and response.body7680and response.body:find("Samsung", 1, true)7681and response.body:lower():find("<title>web viewer for samsung dvr</title>", 1, true)7682end,7683login_combos = {7684{username = "admin", password = "4321"}7685},7686login_check = function (host, port, path, user, pass)7687local cookie = ("DATA1=%s&DATA2=%s&SDATA3=%.15f"):format(base64.enc(user),7688base64.enc(pass),7689math.random())7690local form = {lang="en",7691port=0,7692close_user_session=0,7693data1=base64.enc(user),7694data2=stdnse.tohex(openssl.md5(pass))}7695local resp = http_post_simple(host, port,7696url.absolute(path, "cgi-bin/webviewer_cgi_login2"),7697{cookies=cookie}, form)7698return resp.status == 2007699and (resp.body or ""):find("%Wtop%.document%.location%.href%s*=%s*['\"]%.%./index%.htm[?'\"]")7700end7701})77027703table.insert(fingerprints, {7704name = "Samsung iPOLiS",7705cpe = "cpe:/a:samsung:ipolis_device_manager",7706category = "security",7707paths = {7708{path = "/"}7709},7710target_check = function (host, port, path, response)7711if not (response.status == 2007712and response.body7713and response.body:find("home/monitoring.cgi", 1, true)7714and response.body:find("%Wdocument%.location%.replace%((['\"])[^'\"]-%f[^/'\"]home/monitoring%.cgi%1%)%s*;")) then7715return false7716end7717local resp = http_get_simple(host, port,7718url.absolute(path, "home/monitoring.cgi"))7719return (http_auth_realm(resp) or ""):find("^iPolis%f[_\0]")7720end,7721login_combos = {7722{username = "admin", password = "4321"}7723},7724login_check = function (host, port, path, user, pass)7725return try_http_auth(host, port, url.absolute(path, "home/monitoring.cgi"),7726user, pass, true)7727end7728})77297730table.insert(fingerprints, {7731name = "Truen TCAM (var.1)",7732category = "security",7733paths = {7734{path = "/"}7735},7736target_check = function (host, port, path, response)7737return response.status == 2007738and response.body7739and response.body:find("/user/view.html", 1, true)7740and get_tag(response.body, "frame", {src="/user/view%.html$"})7741and response.body:lower():find("<title>video surveillance</title>", 1, true)7742end,7743login_combos = {7744{username = "admin", password = "1234"}7745},7746login_check = function (host, port, path, user, pass)7747return try_http_auth(host, port, url.absolute(path, "user/view.html"),7748user, pass, false)7749end7750})77517752table.insert(fingerprints, {7753name = "Truen TCAM (var.2)",7754category = "security",7755paths = {7756{path = "/"}7757},7758target_check = function (host, port, path, response)7759local lurl = response.status == 2007760and get_refresh_url(response.body or "", "/user/view%.html$")7761if not lurl then return false end7762local resp = http_get_simple(host, port, lurl)7763return (http_auth_realm(resp) or ""):find("^IPVideo_%x+$")7764end,7765login_combos = {7766{username = "admin", password = "1234"}7767},7768login_check = function (host, port, path, user, pass)7769return try_http_auth(host, port, url.absolute(path, "user/view.html"),7770user, pass, "any")7771end7772})77737774table.insert(fingerprints, {7775name = "TVT DVR",7776category = "security",7777paths = {7778{path = "/"}7779},7780target_check = function (host, port, path, response)7781if not (response.status == 2007782and response.body7783and response.body:find("Pages/login.htm", 1, true)7784and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])Pages/login%.htm%1")) then7785return false7786end7787local resp = http_get_simple(host, port,7788url.absolute(path, "Pages/login.htm"))7789return resp.status == 2007790and resp.body7791and resp.body:find("IDCS_LOGIN_NBSP", 1, true)7792end,7793login_combos = {7794{username = "admin", password = "123456"},7795{username = "admin", password = "1"}7796},7797login_check = function (host, port, path, user, pass)7798local auth = {username = user, password = pass}7799local header = {["Content-Type"]="text/plain;charset=UTF-8"}7800local msg = [=[7801<?xml version="1.0" encoding="utf-8" ?>7802<request version="1.0" systemType="NVMS-9000" clientType="WEB"/>7803]=]7804msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")7805local resp = http_post_simple(host, port, url.absolute(path, "doLogin"),7806{auth=auth, header=header}, msg)7807return resp.status == 2007808and (resp.body or ""):find("<status>success</status>", 1, true)7809end7810})78117812table.insert(fingerprints, {7813name = "Ubiquiti UniFi Video (var.1)",7814category = "security",7815paths = {7816{path = "/"}7817},7818target_check = function (host, port, path, response)7819return response.status == 2007820and response.body7821and response.body:find(">UniFi Video<", 1, true)7822and response.body:lower():find("<title>unifi video</title>", 1, true)7823and get_tag(response.body, "main-view", {["ui-view"]=""})7824and get_tag(response.body, "script", {["data-headjs-load"]="^main%.js%f[\0?]"})7825end,7826login_combos = {7827{username = "ubnt", password = "ubnt"}7828},7829login_check = function (host, port, path, user, pass)7830local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "login")})),7831["Content-Type"]="application/json",7832["Accept"]="application/json, text/plain, */*"}7833local jin = {username=user, password=pass}7834json.make_object(jin)7835local resp = http_post_simple(host, port,7836url.absolute(path, "api/1.1/login"),7837{cookies="ubntActiveUser=false", header=header},7838json.generate(jin))7839return resp.status == 2007840and get_cookie(resp, "authId", "^%w+$")7841end7842})78437844table.insert(fingerprints, {7845name = "Ubiquiti UniFi Video (var.2)",7846category = "security",7847paths = {7848{path = "/"}7849},7850target_check = function (host, port, path, response)7851return response.status == 2007852and response.body7853and response.body:find(">UniFi Video<", 1, true)7854and response.body:find("app-id=com.ubnt.unifivideo", 1, true)7855and response.body:lower():find("<title>unifi video</title>", 1, true)7856and get_tag(response.body, "meta", {name="^google%-play%-app$", content="^app%-id=com%.ubnt%.unifivideo$"})7857end,7858login_combos = {7859{username = "ubnt", password = "ubnt"}7860},7861login_check = function (host, port, path, user, pass)7862local resp1 = http_get_simple(host, port, path)7863if resp1.status ~= 200 then return false end7864local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=url.absolute(path, "login")})),7865["Content-Type"]="application/json",7866["Accept"]="application/json, text/plain, */*"}7867local jin = {username=user, password=pass}7868json.make_object(jin)7869local resp2 = http_post_simple(host, port,7870url.absolute(path, "api/2.0/login"),7871{cookies=resp1.cookies, header=header},7872json.generate(jin))7873return resp2.status == 2007874and get_cookie(resp2, "JSESSIONID_AV", "^%x+$")7875end7876})78777878table.insert(fingerprints, {7879name = "Xiongmai NETSurveillance",7880category = "security",7881paths = {7882{path = "/"}7883},7884target_check = function (host, port, path, response)7885return response.status == 2007886and response.body7887and response.body:find("%Wlocation%s*=%s*(['\"])Login%.htm%1%s*;")7888and response.body:find("%Wvar%s+gHashCookie%s*=%s*new%s+Hash%.Cookie%(%s*(['\"])NetSuveillanceWebCookie%1%s*,")7889end,7890login_combos = {7891{username = "admin", password = ""},7892{username = "default", password = "tluafed"}7893},7894login_check = function (host, port, path, user, pass)7895local cookie = "NetSuveillanceWebCookie="7896.. url.escape(('{"username":"%s"}'):format(user))7897local form = stdnse.output_table()7898form.command = "login"7899form.username = user7900form.password = pass7901local resp = http_post_simple(host, port, url.absolute(path, "Login.htm"),7902{cookies=cookie}, form)7903return resp.status == 2007904and (resp.body or ""):match("%Wvar%s+g_user%s*=%s*['\"](.-)['\"]%s*;") == user7905end7906})79077908table.insert(fingerprints, {7909name = "AVTech AVC DVR",7910category = "security",7911paths = {7912{path = "/"}7913},7914target_check = function (host, port, path, response)7915return response.status == 2007916and response.body7917and response.body:find("MM_goToURL", 1, true)7918and response.body:lower():find("<title>--- video web server ---</title>", 1, true)7919end,7920login_combos = {7921{username = "admin", password = "admin"}7922},7923login_check = function (host, port, path, user, pass)7924local form = {username=user,7925password=pass,7926Submit="Submit"}7927local resp = http_post_simple(host, port, url.absolute(path, "home.htm"),7928nil, form)7929return resp.status == 2007930and (resp.body or ""):lower():find("<object%s")7931end7932})79337934table.insert(fingerprints, {7935name = "AVTech IP Camera",7936category = "security",7937paths = {7938{path = "/"}7939},7940target_check = function (host, port, path, response)7941return response.status == 2007942and response.body7943and response.body:find("/nobody/", 1, true)7944and response.body:lower():find("<title>::: login :::</title>", 1, true)7945end,7946login_combos = {7947{username = "admin", password = "admin"}7948},7949login_check = function (host, port, path, user, pass)7950local creds = base64.enc(user .. ":" .. pass)7951local lurl = ("cgi-bin/nobody/VerifyCode.cgi?account=%s&rnd=%.15f"):format(7952creds, math.random())7953local resp = http_get_simple(host, port, url.absolute(path, lurl))7954return resp.status == 2007955and get_cookie(resp, "SSID") == creds7956end7957})79587959table.insert(fingerprints, {7960name = "EverFocus ECORHD",7961category = "security",7962paths = {7963{path = "/"}7964},7965target_check = function (host, port, path, response)7966local realm = http_auth_realm(response) or ""7967return realm:find("^ECOR%d+%-[%u%d]+$")7968or realm:find("^ELUX%d+$")7969end,7970login_combos = {7971{username = "admin", password = "11111111"},7972{username = "user1", password = "11111111"},7973{username = "user2", password = "11111111"}7974},7975login_check = function (host, port, path, user, pass)7976return try_http_auth(host, port, path, user, pass, true)7977end7978})79797980table.insert(fingerprints, {7981name = "Interlogix truVision",7982category = "security",7983paths = {7984{path = "/index.asp"}7985},7986target_check = function (host, port, path, response)7987return response.status == 2007988and response.header["server"] == "Interlogix-Webs"7989and response.body7990and response.body:find("%Wwindow%.location%.href%s*=%s*(['\"])doc/page/login%.asp%1")7991end,7992login_combos = {7993{username = "admin", password = "1234"}7994},7995login_check = function (host, port, path, user, pass)7996local header = {["Content-Type"]="text/xml"}7997local creds = {username = user, password = pass, digest = false}7998local ipaddr = ("192.168.%d.%d"):format(math.random(254), math.random(254))7999local macaddr = random_hex(12):gsub("..", ":%1"):sub(2)8000local msg = [[8001<?xml version="1.0" encoding="utf-8"?>8002<userCheck>8003<ipAddress>__IPADDR__</ipAddress>8004<macAddress>__MACADDR__</macAddress>8005</userCheck>]]8006msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")8007msg = msg:gsub("__%w+__", {__IPADDR__=ipaddr, __MACADDR__=macaddr})8008local resp = http_post_simple(host, port,8009url.absolute(path, "PSIA/Custom/SelfExt/userCheckEx"),8010{header=header, auth=creds}, msg)8011return resp.status == 2008012and (resp.body or ""):find("<statusValue>200</statusValue>", 1, true)8013end8014})80158016table.insert(fingerprints, {8017name = "LILIN NVR",8018category = "security",8019paths = {8020{path = "/"}8021},8022target_check = function (host, port, path, response)8023return (http_auth_realm(response) or ""):find("^Merit LILIN")8024end,8025login_combos = {8026{username = "admin", password = "1111"}8027},8028login_check = function (host, port, path, user, pass)8029return try_http_auth(host, port, path, user, pass, false)8030end8031})80328033table.insert(fingerprints, {8034name = "NUUO NVR",8035category = "security",8036paths = {8037{path = "/"}8038},8039target_check = function (host, port, path, response)8040return response.status == 2008041and response.body8042and response.body:find("NUUO", 1, true)8043and response.body:lower():find("<title>nuuo network video recorder login</title>", 1, true)8044and get_tag(response.body, "form", {name="^mainform$", action="^index%.php$"})8045end,8046login_combos = {8047{username = "admin", password = "admin"}8048},8049login_check = function (host, port, path, user, pass)8050local form = {language="English",8051login=user,8052password=pass,8053submit=" Login "}8054local resp = http_post_simple(host, port, url.absolute(path, "index.php"),8055nil, form)8056return resp.status == 3028057and resp.header["location"] == "screen.php"8058end8059})80608061table.insert(fingerprints, {8062name = "NUUO Titan NVR",8063category = "security",8064paths = {8065{path = "/"}8066},8067target_check = function (host, port, path, response)8068return response.status == 2008069and response.body8070and response.body:find("NUUO", 1, true)8071and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")8072and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})8073and get_tag(response.body, "img", {type="^submit$", value="^login$"})8074end,8075login_combos = {8076{username = "admin", password = "admin"}8077},8078login_check = function (host, port, path, user, pass)8079local form = {language="en",8080user=user,8081pass=pass,8082browser_engine="firefox"}8083local resp = http_post_simple(host, port, url.absolute(path, "login.php"),8084nil, form)8085return (resp.status == 3028086and (resp.header["location"] or ""):find("/setting%.php$"))8087or (resp.status == 2008088and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))8089end8090})80918092table.insert(fingerprints, {8093name = "NUUO Solo NVR",8094cpe = "cpe:/o:nuuo:nvrsolo",8095category = "security",8096paths = {8097{path = "/"}8098},8099target_check = function (host, port, path, response)8100return response.status == 2008101and response.body8102and response.body:find("NUUO", 1, true)8103and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")8104and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})8105and get_tag(response.body, "input", {type="^submit$", name="^submit$"})8106end,8107login_combos = {8108{username = "admin", password = "admin"}8109},8110login_check = function (host, port, path, user, pass)8111local form = {language="en",8112user=user,8113pass=pass,8114submit="Login"}8115local resp = http_post_simple(host, port, url.absolute(path, "login.php"),8116nil, form)8117return (resp.status == 3028118and (resp.header["location"] or ""):find("/setting%.php$"))8119or (resp.status == 2008120and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))8121end8122})81238124table.insert(fingerprints, {8125name = "NUUO Solo NVR OEM",8126category = "security",8127paths = {8128{path = "/"}8129},8130target_check = function (host, port, path, response)8131return response.status == 2008132and response.body8133and response.body:find("NUUO", 1, true)8134and response.body:lower():find("<title>[%w%s]*network video recorder login</title>")8135and get_tag(response.body, "form", {name="^mainform$", action="^login%.php$"})8136and get_tag(response.body, "input", {type="^image$", name="^submit$"})8137end,8138login_combos = {8139{username = "admin", password = "admin"}8140},8141login_check = function (host, port, path, user, pass)8142local form = {["submit.x"]=0,8143["submit.y"]=0,8144language="en",8145user=user,8146pass=pass,8147browser_engine="firefox",8148base_url=""}8149local resp = http_post_simple(host, port, url.absolute(path, "login.php"),8150nil, form)8151return (resp.status == 3028152and (resp.header["location"] or ""):find("/setting%.php$"))8153or (resp.status == 2008154and (resp.body or ""):find("%snexpage%s*=%s*(['\"])setting%.php%1"))8155end8156})81578158table.insert(fingerprints, {8159name = "VideoIQ iCVR",8160category = "security",8161paths = {8162{path = "/"}8163},8164target_check = function (host, port, path, response)8165return response.status == 3028166and (response.header["location"] or ""):find("?wicket:bookmarkablePage=:com.videoiq.fusion.camerawebapi.ui.pages.LoginPage", 1, true)8167end,8168login_combos = {8169{username = "supervisor", password = "supervisor"}8170},8171login_check = function (host, port, path, user, pass)8172local resp1 = http_get_simple(host, port, path)8173local lurl = (resp1.header["location"] or ""):match("%f[/]/%f[^/].*")8174if not (resp1.status == 302 and lurl) then return false end8175local form = {loginForm1_hf_0="",8176userName=user,8177password=pass,8178login=""}8179local resp2 = http_post_simple(host, port,8180lurl .. "&wicket:interface=:0:loginPanel:loginForm::IFormSubmitListener::",8181{cookies=resp1.cookies}, form)8182return resp2.status == 3028183end8184})81858186table.insert(fingerprints, {8187name = "Dahua Security",8188cpe = "cpe:/o:dahuasecurity:dvr_firmware",8189category = "security",8190paths = {8191{path = "/"}8192},8193target_check = function (host, port, path, response)8194return have_openssl8195and response.status == 2008196and response.body8197and (response.body:find("js/loginEx.js", 1, true)8198and get_tag(response.body, "script", {src="^js/loginEx%.js%f[?\0]"})8199and get_tag(response.body, "script", {src="^jsCore/rpcCore%.js%f[?\0]"})8200or response.body:find("/js/merge.js", 1, true)8201and get_tag(response.body, "script", {src="/js/merge%.js$"})8202and get_tag(response.body, "div", {id="^download_plugins$"})8203or response.body:find("jsBase/widget/js/dui.tab.js", 1, true)8204and get_tag(response.body, "script", {src="^jsBase/widget/js/dui%.tab%.js%f[?\0]"})8205and get_tag(response.body, "script", {src="^jsCore/common%.js%f[?\0]"}))8206end,8207login_combos = {8208{username = "666666", password = "666666"},8209{username = "admin", password = "admin"},8210{username = "anonymity", password = "anonymity"}8211},8212login_check = function (host, port, path, user, pass)8213local lurl = url.absolute(path, "RPC2_Login")8214local opts = {cookies="DHLangCookie30=English",8215header={["X-Request"]="JSON"}}8216local jin = {method="global.login",8217params={userName=user,8218password="",8219clientType="Web3.0"},8220id=10000}8221json.make_object(jin)8222local resp1 = http_post_simple(host, port, lurl, opts, json.generate(jin))8223if not (resp1.status == 200 and resp1.body) then return false end8224local jstatus, jout = json.parse(resp1.body)8225local params = jstatus and jout.params8226if not params then return false end8227local passtype8228if not params.encryption then8229elseif params.encryption == "Basic" then8230pass = base64.enc(user .. ":" .. pass)8231elseif params.encryption == "Default" then8232local hashfnc = function (...)8233local text = table.concat({...}, ":")8234return stdnse.tohex(openssl.md5(text)):upper()8235end8236if not (params.random and params.realm) then return false end8237pass = hashfnc(user, params.random, hashfnc(user, params.realm, pass))8238passtype = "Default"8239elseif params.encryption == "OldDigest" then8240local hash = openssl.md5(pass)8241local ptbl = {}8242for i = 1, #hash, 2 do8243local a, b = hash:byte(i, i + 1)8244a = (a + b) % 628245if a <= 9 then8246b = 488247elseif a <= 35 then8248b = 558249else8250b = 618251end8252table.insert(ptbl, string.char(a + b))8253end8254pass = table.concat(ptbl)8255else8256return false8257end8258opts.cookies = opts.cookies .. "; DhWebClientSessionID=" .. jout.session8259jin.session = jout.session8260jin.params.password = pass8261jin.params.passwordType = passtype8262jin.params.authorityType = params.encryption8263local resp2 = http_post_simple(host, port, lurl, opts, json.generate(jin))8264if not (resp2.status == 200 and resp2.body) then return false end8265jstatus, jout = json.parse(resp2.body)8266return jstatus and jout.result8267end8268})82698270table.insert(fingerprints, {8271name = "Digital Watchdog",8272category = "security",8273paths = {8274{path = "/"}8275},8276target_check = function (host, port, path, response)8277return have_openssl8278and response.status == 3018279and (response.header["location"] or ""):find("/static/index%.html$")8280and (response.header["server"] or ""):find("(Digital Watchdog)", 1, true)8281end,8282login_combos = {8283{username = "admin", password = "admin"}8284},8285login_check = function (host, port, path, user, pass)8286local lurl = url.absolute(path, "api/getCurrentUser")8287local resp1 = http_get_simple(host, port, lurl, {cookies="Authorization=Digest"})8288local realm = get_cookie(resp1, "realm")8289local nonce = get_cookie(resp1, "nonce")8290if not (resp1.status == 401 and realm and nonce) then return false end8291user = user:lower()8292local hashfnc = function (...)8293local text = table.concat({...}, ":")8294return stdnse.tohex(openssl.md5(text))8295end8296local hash = hashfnc(hashfnc(user, realm, pass), nonce, hashfnc("GET:"))8297local auth = url.escape(base64.enc(table.concat({user, nonce, hash}, ":")))8298table.insert(resp1.cookies, {name="Authorization", value="Digest", path=path})8299table.insert(resp1.cookies, {name="auth", value=auth, path=path})8300local resp2 = http_get_simple(host, port, lurl, {cookies=resp1.cookies})8301return resp2.status == 2008302and resp2.header["content-type"] == "application/json"8303end8304})83058306table.insert(fingerprints, {8307name = "Loxone Intercom Video",8308category = "security",8309paths = {8310{path = "/"}8311},8312target_check = function (host, port, path, response)8313return response.status == 2008314and (response.header["server"] or ""):find("HyNetOS/%d+%.")8315and response.body8316and response.body:find("Loxone", 1, true)8317and response.body:lower():find("<title>loxone intercom video</title>", 1, true)8318end,8319login_combos = {8320{username = "admin", password = "admin"}8321},8322login_check = function (host, port, path, user, pass)8323return try_http_auth(host, port, url.absolute(path, "setup.cgi"),8324user, pass, false)8325end8326})83278328table.insert(fingerprints, {8329name = "Loxone Smart Home",8330category = "security",8331paths = {8332{path = "/"}8333},8334target_check = function (host, port, path, response)8335return have_openssl8336and response.status == 2008337and response.body8338and response.body:find("Loxone", 1, true)8339and response.body:lower():find("<title>loxone smart home</title>", 1, true)8340end,8341login_combos = {8342{username = "admin", password = "admin"}8343},8344login_check = function (host, port, path, user, pass)8345local resp1 = http_get_simple(host, port,8346url.absolute(path, "jdev/cfg/apiKey"))8347if not (resp1.status == 200 and resp1.body) then return false end8348local jstatus, jout = json.parse(resp1.body)8349if not (jstatus and jout.LL.value) then return false end8350jstatus, jout = json.parse(jout.LL.value:gsub("'", '"'))8351if not (jstatus and jout.key) then return false end8352local key = stdnse.fromhex(jout.key)8353local auth = stdnse.tohex(openssl.hmac("SHA1", key, user .. ":" .. pass))8354local lurl = "jdev/sps/LoxAPPversion3?" .. url.build_query({auth=auth,user=user})8355local resp2 = http_get_simple(host, port, url.absolute(path, lurl))8356return resp2.status == 2008357end8358})83598360table.insert(fingerprints, {8361name = "Automa Lilliput2",8362category = "security",8363paths = {8364{path = "/login.php"}8365},8366target_check = function (host, port, path, response)8367return response.status == 2008368and response.body8369and response.body:find("Automa", 1, true)8370and response.body:lower():find("<title>[^<]-%sautoma srl</title>")8371end,8372login_combos = {8373{username = "admin", password = "admin"}8374},8375login_check = function (host, port, path, user, pass)8376local resp = http_post_simple(host, port, path, nil,8377{username=user,password=pass,submit="Login"})8378return resp.status == 3028379and resp.header["location"] == "index.php"8380end8381})83828383table.insert(fingerprints, {8384name = "Siedle Door Controller",8385category = "security",8386paths = {8387{path = "/"}8388},8389target_check = function (host, port, path, response)8390return response.status == 2008391and response.header["server"] == "Z-World Rabbit"8392and response.body8393and response.body:lower():find("<title></title>", 1, true)8394and response.body:lower():find("%Wparent%.location%s*=%s*(['\"])[^'\"]-/index%.zht%1")8395end,8396login_combos = {8397{username = "Service", password = "Siedle"}8398},8399login_check = function (host, port, path, user, pass)8400local resp1 = http_get_simple(host, port, url.absolute(path, "login.zht"))8401if not (resp1.status == 200 and resp1.body) then return false end8402local lang = resp1.body:lower():match("<select%f[%s][^>]-%sname%s*=%s*['\"]m_webdata%.m_cgilogin%.m_lang['\"].-<option%f[%s]([^>]-%sselected%f[%s>][^>]*)")8403lang = (lang or ""):match("%svalue%s*=%s*['\"](%w+)['\"]")8404if not lang then return false end8405local form2 = stdnse.output_table()8406form2["m_webdata.m_cgiLogin.m_user"] = user8407form2["m_webdata.m_cgiLogin.m_passwd"] = pass8408form2["m_webdata.m_cgiLogin.m_lang"] = lang8409form2["action.x"] = 08410form2["action.y"] = 08411local resp2 = http_post_simple(host, port, url.absolute(path, "login.cgi"),8412nil, form2)8413return resp2.status == 3028414and (resp2.header["location"] or ""):find("/index%.zht$")8415and get_cookie(resp2, "DCRABBIT", "^%-?%d+$")8416end8417})84188419table.insert(fingerprints, {8420name = "Genetec Synergis",8421category = "security",8422paths = {8423{path = "/"}8424},8425target_check = function (host, port, path, response)8426if not (response.status == 2008427and response.header["server"] == "Microsoft-HTTPAPI/2.0"8428and response.body8429and get_refresh_url(response.body, "/ui$")) then8430return false8431end8432local resp = http_get_simple(host, port,8433url.absolute(path, "ui/LogOn?ReturnUrl=%2fui"))8434return resp.status == 2008435and resp.body8436and resp.body:find("/genetec.")8437end,8438login_combos = {8439{username = "admin", password = "softwire"}8440},8441login_check = function (host, port, path, user, pass)8442local form = {UserName=user,8443Password=pass,8444Language="En",8445TimeZoneOffset=0}8446local resp = http_post_simple(host, port,8447url.absolute(path, "ui/LogOn?ReturnUrl=%2fui"),8448nil, form)8449return resp.status == 3028450and (resp.header["location"] or ""):find("/ui$")8451end8452})84538454---8455--Industrial systems8456---8457table.insert(fingerprints, {8458name = "Schneider Modicon Web",8459category = "industrial",8460paths = {8461{path = "/"}8462},8463target_check = function (host, port, path, response)8464return response.status == 3028465and (response.header["server"] or ""):find("^Schneider%-WEB/V%d+%.")8466and (response.header["location"] or ""):find("/index%.htm$")8467end,8468login_combos = {8469{username = "USER", password = "USER"}8470},8471login_check = function (host, port, path, user, pass)8472return try_http_auth(host, port,8473url.absolute(path, "secure/embedded/http_passwd_config.htm?Language=English"),8474user, pass, false)8475end8476})84778478table.insert(fingerprints, {8479name = "Schneider Xflow",8480category = "industrial",8481paths = {8482{path = "/"}8483},8484target_check = function (host, port, path, response)8485return have_openssl8486and response.status == 2008487and response.body8488and response.body:find("Xflow", 1, true)8489and get_tag(response.body, "input", {name="^rsakey1$"})8490end,8491login_combos = {8492{username = "TEST", password = "TEST"}8493},8494login_check = function (host, port, path, user, pass)8495local resp1 = http_get_simple(host, port, path)8496if not (resp1.status == 200 and resp1.body) then return false end8497local rsakey1 = get_tag(resp1.body, "input", {name="^rsakey1$", value="^%d+$"})8498local rsakey2 = get_tag(resp1.body, "input", {name="^rsakey2$", value="^%d+$"})8499if not (rsakey1 and rsakey2) then return false end8500local p = openssl.bignum_dec2bn(rsakey1.value)8501local m = openssl.bignum_dec2bn(rsakey2.value)8502local encpass = {}8503local r = 08504for _, s in ipairs({pass:byte(1, -1)}) do8505local a = openssl.bignum_dec2bn(r + s)8506local b = openssl.bignum_bn2dec(openssl.bignum_mod_exp(a, p, m))8507table.insert(encpass, ("%04x"):format(b))8508r = s8509end8510table.insert(encpass, 1, ("0000"):rep(16-#encpass))8511local form2 = {language="EN",8512login="home.xml",8513username=user,8514rsakey1=rsakey1.value,8515rsakey2=rsakey2.value,8516pwd=table.concat(encpass):upper(),8517enter="Log in"}8518local resp2 = http_post_simple(host, port, url.absolute(path, "kw"),8519nil, form2)8520return resp2.status == 2008521and (resp2.body or ""):find("%Wvar%s+sessionid%s*=%s*(['\"])%x+%1")8522end8523})85248525table.insert(fingerprints, {8526name = "TCS Basys Controls Communication Center",8527category = "industrial",8528paths = {8529{path = "/"}8530},8531target_check = function (host, port, path, response)8532return http_auth_realm(response) == "Private"8533end,8534login_combos = {8535{username = "admin", password = "password"}8536},8537login_check = function (host, port, path, user, pass)8538return try_http_auth(host, port, path, user, pass, false)8539end8540})85418542table.insert(fingerprints, {8543name = "Adcon Telemetry Gateway",8544category = "industrial",8545paths = {8546{path = "/"}8547},8548target_check = function (host, port, path, response)8549return response.status == 2008550and response.body8551and response.body:find("Adcon", 1, true)8552and response.body:lower():find("<title>%s*adcon telemetry gateway%s*</title>")8553and get_tag(response.body, "a", {href="%f[%w]configurator%.jnlp$"})8554end,8555login_combos = {8556{username = "root", password = "840sw"},8557{username = "adv", password = "addvantage"}8558},8559login_check = function (host, port, path, user, pass)8560return try_http_auth(host, port, url.absolute(path, "getconfig"),8561user, pass, false)8562end8563})85648565table.insert(fingerprints, {8566name = "Lantronix ThinWeb Manager",8567category = "industrial",8568paths = {8569{path = "/"}8570},8571target_check = function (host, port, path, response)8572return have_openssl8573and response.status == 2008574and (response.header["server"] or ""):find("^Gordian Embedded")8575and response.body8576and response.body:find("Lantronix", 1, true)8577and response.body:lower():find("<title>lantronix %w*web manager%W")8578end,8579login_combos = {8580{username = "", password = "system"}8581},8582login_check = function (host, port, path, user, pass)8583local resp0 = http_get_simple(host, port, path)8584if not (resp0.status == 200 and resp0.body) then return false end8585local lurl = get_tag(resp0.body, "frame", {src="^summary%.html$"})8586and "server.html"8587or resp0.body:lower():match("<a%f[%s][^>]-%shref%s*=%s*['\"]([^'\"]+)['\"]%s*>server properties</a>")8588if not lurl then return false end8589lurl = url.absolute(path, lurl)8590local resp1 = http_get_simple(host, port, lurl)8591local nonce = resp1.status == 403 and get_cookie(resp1, "SrvrNonce", ".")8592if not nonce then return false end8593local creds = stdnse.tohex(openssl.md5(nonce .. ":" .. pass:upper()))8594local cookies = ("SrvrNonce=%s; SrvrCreds=%s"):format(nonce, creds)8595local resp2 = http_get_simple(host, port, lurl, {cookies=cookies})8596return resp2.status == 2008597end8598})85998600table.insert(fingerprints, {8601name = "Lantronix XPort",8602category = "industrial",8603paths = {8604{path = "/"}8605},8606target_check = function (host, port, path, response)8607return response.status == 2008608and response.body8609and response.body:find("secure/ltx_conf.htm", 1, true)8610end,8611login_combos = {8612{username = "", password = ""}8613},8614login_check = function (host, port, path, user, pass)8615return try_http_auth(host, port, url.absolute(path, "secure/ltx_conf.htm"),8616user, pass, false)8617end8618})86198620table.insert(fingerprints, {8621name = "Moxa MiiNePort",8622cpe = "cpe:/o:moxa:miineport_*",8623category = "industrial",8624paths = {8625{path = "/"}8626},8627target_check = function (host, port, path, response)8628return have_openssl8629and response.status == 3078630and (response.header["location"] or ""):find("/moxa/home%.htm$")8631end,8632login_combos = {8633{username = "admin", password = ""}8634},8635login_check = function (host, port, path, user, pass)8636local form = {Username=user,8637Password="",8638MD5Password=stdnse.tohex(openssl.md5(pass)),8639Submit="Login"}8640local resp = http_post_simple(host, port,8641url.absolute(path, "moxa/Login.htm"),8642nil, form)8643return resp.status == 2008644and (resp.body or ""):find("%Wwindow%.open%((['\"])home%.htm%1")8645end8646})86478648table.insert(fingerprints, {8649name = "MBus Webserver",8650category = "industrial",8651paths = {8652{path = "/"}8653},8654target_check = function (host, port, path, response)8655return http_auth_realm(response) == "MBus Webserver"8656and response.header["server"] == "MBus WebServer"8657end,8658login_combos = {8659{username = "admin", password = "admin"}8660},8661login_check = function (host, port, path, user, pass)8662return try_http_auth(host, port, path, user, pass, false)8663end8664})86658666table.insert(fingerprints, {8667name = "Silex Server (var.1)",8668cpe = "cpe:/o:silex:*",8669category = "industrial",8670paths = {8671{path = "/"}8672},8673target_check = function (host, port, path, response)8674return response.status == 2008675and response.body8676and response.body:find("/status/devstat.htm", 1, true)8677and response.body:lower():find("<title>%a%a%a?%-%w%w%-?%w+</title>")8678end,8679login_combos = {8680{username="root", password=""},8681{username="admin", password="admin"},8682{username="admin", password="1234"}8683},8684login_check = function (host, port, path, user, pass)8685local resp = http_get_simple(host, port, path)8686if not (resp.status == 200 and resp.body) then return false end8687local frm = get_tag(resp.body, "frame", {src="/%w+/status/devstat%.htm$"})8688if not frm then return false end8689local lang = frm.src:match("/(%w+)/status/devstat%.htm$")8690return try_http_auth(host, port,8691url.absolute(path, lang .. "/mnt/adpass.htm"),8692user, pass, false)8693end8694})86958696table.insert(fingerprints, {8697name = "Silex Server (var.2)",8698cpe = "cpe:/o:silex:*",8699category = "industrial",8700paths = {8701{path = "/"}8702},8703target_check = function (host, port, path, response)8704return response.status == 2008705and response.body8706and response.body:find("status.hti?", 1, true)8707and response.body:lower():find("<title>silex ", 1, true)8708end,8709login_combos = {8710{username="", password="ACCESS"}8711},8712login_check = function (host, port, path, user, pass)8713local form = {access="",8714password="",8715language=0,8716access_psw=pass,8717action="Submit"}8718local resp = http_post_simple(host, port, url.absolute(path, "login"),8719nil, form)8720return resp.status == 2008721and get_tag(resp.body or "", "frame", {src="^status%.hti%?access=%x+&"})8722end8723})87248725table.insert(fingerprints, {8726name = "Wago I/O System 750",8727cpe = "cpe:/h:wago:wago_i%2fo_system*",8728category = "industrial",8729paths = {8730{path = "/"}8731},8732target_check = function (host, port, path, response)8733return response.status == 3028734and (response.header["location"] or ""):find("/webserv/index%.ssi$")8735end,8736login_combos = {8737{username="admin", password="wago"},8738{username="user", password="user"},8739{username="guest", password="guest"}8740},8741login_check = function (host, port, path, user, pass)8742return try_http_auth(host, port,8743url.absolute(path, "webserv/cplcfg/security.ssi"),8744user, pass, false)8745end8746})87478748table.insert(fingerprints, {8749name = "Wago TO-PASS",8750category = "industrial",8751paths = {8752{path = "/"}8753},8754target_check = function (host, port, path, response)8755return http_auth_realm(response) == "WAGO TO-PASS"8756end,8757login_combos = {8758{username="admin", password="wago"},8759{username="user", password="user"},8760{username="guest", password="guest"}8761},8762login_check = function (host, port, path, user, pass)8763return try_http_auth(host, port, path, user, pass, true)8764end8765})87668767table.insert(fingerprints, {8768name = "ProMinent Controller",8769category = "industrial",8770paths = {8771{path = "/"}8772},8773target_check = function (host, port, path, response)8774return response.status == 2008775and response.header["server"] == "Z-World Rabbit"8776and response.body8777and get_tag(response.body, "frame", {src="^right%.shtml$"})8778end,8779login_combos = {8780{username = "Operator1", password = "1"},8781{username = "Operator2", password = "2"},8782{username = "Operator3", password = "3"},8783{username = "Operator4", password = "4"},8784{username = "Configure5", password = "5"},8785{username = "Configure6", password = "6"},8786{username = "Configure7", password = "7"},8787{username = "admin", password = "AAAA"}8788},8789login_check = function (host, port, path, user, pass)8790local usermap = {["Operator1"]=1,8791["Operator2"]=2,8792["Operator3"]=3,8793["Operator4"]=4,8794["Configure5"]=5,8795["Configure6"]=6,8796["Configure7"]=7,8797["admin"]=8}8798local lurl = ("taco.cgi?F0=AH&F1=%d&F2=%s"):format(usermap[user],pass)8799local resp = http_get_simple(host, port, url.absolute(path, lurl))8800return resp.status == 2008801and (get_cookie(resp, "DCRABBIT") or ""):lower() == user:lower()8802end8803})88048805table.insert(fingerprints, {8806name = "Emerson EC2",8807category = "industrial",8808paths = {8809{path = "/"}8810},8811target_check = function (host, port, path, response)8812return response.status == 2008813and response.body8814and response.body:find("EC2", 1, true)8815and response.body:lower():find("<title>ec2 %d+ ")8816and get_tag(response.body, "frame", {src="^bckgnd%.html$"})8817end,8818login_combos = {8819{username = "EmersonID", password = "12"}8820},8821login_check = function (host, port, path, user, pass)8822return try_http_auth(host, port, url.absolute(path, "tcp_ip.shtml.shtml"),8823user, pass, false)8824end8825})88268827table.insert(fingerprints, {8828name = "Emerson Xweb",8829category = "industrial",8830paths = {8831{path = "/"}8832},8833target_check = function (host, port, path, response)8834return response.status == 2008835and response.body8836and response.body:find("/cgi-bin/xweb500.cgi", 1, true)8837and response.body:find("%WUrl%s*=%s*(['\"])[^'\"]-/cgi%-bin/xweb500%.cgi%?res=%d%1")8838end,8839login_combos = {8840{username = "Admin", password = "Admin"}8841},8842login_check = function (host, port, path, user, pass)8843local form = {pg=2,8844action=2,8845act=0,8846login=user,8847passwd=pass}8848local resp = http_post_simple(host, port,8849url.absolute(path, "cgi-bin/user.cgi"),8850nil, form)8851return resp.status == 2008852and resp.body8853and resp.body:find("%Wvar%s+value%s*=%s*(['\"])" .. user .. "%1")8854and resp.body:find("%Wlocation%.href%s*=%s*(['\"])[^'\"]-/index/indexFr%.html%1")8855end8856})88578858table.insert(fingerprints, {8859name = "Heatmiser Wifi Thermostat",8860category = "industrial",8861paths = {8862{path = "/"}8863},8864target_check = function (host, port, path, response)8865return response.status == 2008866and response.body8867and response.body:find("Heatmiser", 1, true)8868and response.body:lower():find("<title>heatmiser wifi thermostat</title>", 1, true)8869and get_tag(response.body, "input", {name="^lgpw$"})8870end,8871login_combos = {8872{username = "admin", password = "admin"}8873},8874login_check = function (host, port, path, user, pass)8875local resp = http_post_simple(host, port, path, nil, {lgnm=user,lgpw=pass})8876return resp.status == 3028877and (resp.header["location"] or ""):find("/main%.htm$")8878end8879})88808881table.insert(fingerprints, {8882name = "Heatmiser NetMonitor 1.x",8883category = "industrial",8884paths = {8885{path = "/"}8886},8887target_check = function (host, port, path, response)8888return response.status == 2008889and response.body8890and response.body:find("NetMonitor", 1, true)8891and response.body:lower():find("<title>netmonitor ", 1, true)8892and get_tag(response.body, "input", {name="^loginname$"})8893end,8894login_combos = {8895{username = "admin", password = "admin"}8896},8897login_check = function (host, port, path, user, pass)8898local resp = http_post_simple(host, port,8899url.absolute(path, "view_stats.htm"), nil,8900{loginname=user, loginpassword=pass})8901return resp.status == 2008902and get_tag(resp.body or "", "a", {href="^setup_stats%.htm$"})8903end8904})89058906table.insert(fingerprints, {8907name = "Heatmiser NetMonitor 3.0x",8908category = "industrial",8909paths = {8910{path = "/"}8911},8912target_check = function (host, port, path, response)8913return response.status == 2008914and response.body8915and response.body:find("Netmonitor", 1, true)8916and response.body:find("loginState", 1, true)8917and response.body:lower():find("<title>netmonitor ", 1, true)8918and get_tag(response.body, "input", {name="^loginun$"})8919end,8920login_combos = {8921{username = "admin", password = "admin"}8922},8923login_check = function (host, port, path, user, pass)8924local resp1 = http_post_simple(host, port, url.absolute(path, "main.htm"),8925nil, {loginun=user, loginpw=pass})8926if not (resp1.status == 200 and (resp1.body or ""):find("(['\"]?)left%.htm%1")) then8927return false8928end8929local resp2 = http_get_simple(host, port, url.absolute(path, "left.htm"))8930return resp2.status == 2008931and get_tag(resp2.body or "", "input", {name="^loginstate$", value="^1$"})8932end8933})89348935table.insert(fingerprints, {8936name = "Heatmiser NetMonitor 3.x",8937category = "industrial",8938paths = {8939{path = "/"}8940},8941target_check = function (host, port, path, response)8942return response.status == 2008943and response.body8944and response.body:find("Netmonitor", 1, true)8945and response.body:find("hmcookies", 1, true)8946and response.body:lower():find("<title>netmonitor ", 1, true)8947and get_tag(response.body, "input", {name="^loginun$"})8948end,8949login_combos = {8950{username = "admin", password = "admin"}8951},8952login_check = function (host, port, path, user, pass)8953local resp1 = http_get_simple(host, port, path)8954if not (resp1.status == 200 and resp1.body) then return false end8955local idx = get_tag(resp1.body, "input", {name="^hmckidx$", value="^%d$"})8956if not idx then return false end8957idx = idx.value8958local form = {curckidx=idx,8959loginun=user,8960loginpw=pass}8961local resp2 = http_post_simple(host, port, url.absolute(path, "main.htm"),8962{cookies="hmcookie="..idx}, form)8963if not (resp2.status == 200 and resp2.body) then return false end8964local hmcookies = get_tag(resp2.body, "input", {name="^hmcookies$", value="^%d+$"})8965return hmcookies8966and hmcookies.value:sub(idx + 1, idx + 1) == "1"8967end8968})89698970table.insert(fingerprints, {8971name = "Jacarta interSeptor",8972category = "industrial",8973paths = {8974{path = "/"}8975},8976target_check = function (host, port, path, response)8977return response.status == 2008978and response.body8979and response.body:find(">Jacarta ", 1, true)8980and response.body:lower():find("<title>jacarta interseptor", 1, true)8981and get_tag(response.body, "frame", {src="/pagecompre.html$"})8982end,8983login_combos = {8984{username = "interSeptor", password = "admin"}8985},8986login_check = function (host, port, path, user, pass)8987return try_http_auth(host, port, url.absolute(path, "PageAControl.html"),8988user, pass, false)8989end8990})89918992table.insert(fingerprints, {8993name = "Phasefale JouleAlarm/JouleTemp",8994category = "industrial",8995paths = {8996{path = "/"}8997},8998target_check = function (host, port, path, response)8999return response.status == 2009000and response.body9001and response.body:find("Phasefale Joule", 1, true)9002and response.body:lower():find("<title>phasefale joule", 1, true)9003and get_tag(response.body, "form", {action="/set/set%.html$"})9004end,9005login_combos = {9006{username = "admin", password = "pass"}9007},9008login_check = function (host, port, path, user, pass)9009return try_http_auth(host, port, url.absolute(path, "set/set.html"),9010user, pass, false)9011end9012})90139014table.insert(fingerprints, {9015name = "Proliphix Thermostat",9016category = "industrial",9017paths = {9018{path = "/"}9019},9020target_check = function (host, port, path, response)9021return response.status == 2009022and response.body9023and response.body:find("index.shtml", 1, true)9024and response.body:find("%WprintNavLine%(%s*(['\"])Login%1%s*,%s*(['\"])index%.shtml%2%s*%)")9025and response.body:lower():find("<title>thermostat [^<]-%- status & control</title>")9026end,9027login_combos = {9028{username = "admin", password = "admin"},9029{username = "user", password = "admin"}9030},9031login_check = function (host, port, path, user, pass)9032return try_http_auth(host, port, url.absolute(path, "index.shtml"),9033user, pass, false)9034end9035})90369037table.insert(fingerprints, {9038name = "CS121 UPS Web/SNMP Manager",9039category = "industrial",9040paths = {9041{path = "/"}9042},9043target_check = function (host, port, path, response)9044return response.status == 2009045and (response.header["server"] or ""):find("^HyNetOS/%d+%.")9046and response.body9047and response.body:lower():find("<title>cs121 snmp/web adapter</title>", 1, true)9048end,9049login_combos = {9050{username = "admin", password = "cs121-snmp"}9051},9052login_check = function (host, port, path, user, pass)9053return try_http_auth(host, port, url.absolute(path, "admin/net.shtml"),9054user, pass, false)9055end9056})90579058table.insert(fingerprints, {9059name = "Riello UPS NetMan 204",9060category = "industrial",9061paths = {9062{path = "/"}9063},9064target_check = function (host, port, path, response)9065return response.status == 2009066and (response.header["server"] or ""):find("^mini_httpd/%d+%.")9067and response.body9068and response.body:find(">Netman ", 1, true)9069and response.body:lower():find("<title>netman 204 login</title>", 1, true)9070end,9071login_combos = {9072{username = "admin", password = "admin"},9073{username = "fwupgrade", password = "fwupgrade"},9074{username = "user", password = "user"},9075{username = "eurek", password = "eurek"}9076},9077login_check = function (host, port, path, user, pass)9078local resp = http_post_simple(host, port,9079url.absolute(path, "cgi-bin/login.cgi"),9080nil, {username=user, password=pass})9081return resp.status == 2009082and resp.body9083and (resp.body:find(">window.location.replace(", 1, true)9084or resp.body:find("Another user is logged in", 1, true))9085end9086})90879088table.insert(fingerprints, {9089name = "APC Management Card (basic auth)",9090cpe = "cpe:/h:apc:ap*",9091category = "industrial",9092paths = {9093{path = "/"}9094},9095target_check = function (host, port, path, response)9096return http_auth_realm(response) == "APC Management Card"9097end,9098login_combos = {9099{username = "apc", password = "apc"},9100{username = "device", password = "apc"},9101{username = "readonly", password = "apc"}9102},9103login_check = function (host, port, path, user, pass)9104return try_http_auth(host, port, path, user, pass, false)9105end9106})91079108table.insert(fingerprints, {9109name = "APC Management Card",9110cpe = "cpe:/h:apc:ap*",9111category = "industrial",9112paths = {9113{path = "/logon.htm"}9114},9115target_check = function (host, port, path, response)9116return response.status == 2009117and response.body9118and (response.body:find("apclogo", 1, true)9119or response.body:find("www.apc.com", 1, true))9120and response.body:lower():find("<title>[^<]*log on</title>")9121and get_tag(response.body, "input", {name="^login_username$"})9122end,9123login_combos = {9124{username = "apc", password = "apc"},9125{username = "device", password = "apc"},9126{username = "readonly", password = "apc"}9127},9128login_check = function (host, port, path, user, pass)9129local form = {login_username=user,9130login_password=pass,9131submit="Log On"}9132local resp = http_post_simple(host, port,9133url.absolute(path, "Forms/login1"),9134nil, form)9135local loc = resp.header["location"]9136if not (resp.status == 303 and loc) then return false end9137if loc:find("/home%.htm$") then return true end9138for _, ck in ipairs(resp.cookies or {}) do9139if ck.name:find("^APC") then return true end9140end9141return false9142end9143})91449145table.insert(fingerprints, {9146name = "APC InfraStruXure Central",9147category = "industrial",9148paths = {9149{path = "/"}9150},9151target_check = function (host, port, path, response)9152return response.status == 2009153and response.body9154and response.body:find("www.apc.com", 1, true)9155and (response.body:lower():find("<title>infrastruxure central ", 1, true)9156or response.body:lower():find("<title>struxureware central ", 1, true))9157and get_tag(response.body, "a", {href="^nbc/status/Status$"})9158end,9159login_combos = {9160{username = "apc", password = "apc"}9161},9162login_check = function (host, port, path, user, pass)9163return try_http_auth(host, port, url.absolute(path, "nbc/status/Status"),9164user, pass, false)9165end9166})91679168table.insert(fingerprints, {9169name = "APC InfraStruXure PDU",9170category = "industrial",9171paths = {9172{path = "/"}9173},9174target_check = function (host, port, path, response)9175return http_auth_realm(response) == "InfraStruXure PDU"9176end,9177login_combos = {9178{username = "device", password = "apc"}9179},9180login_check = function (host, port, path, user, pass)9181return try_http_auth(host, port, path, user, pass, false)9182end9183})91849185table.insert(fingerprints, {9186name = "InfraPower PPS-02-S",9187category = "industrial",9188paths = {9189{path = "/"}9190},9191target_check = function (host, port, path, response)9192return response.status == 3029193and response.header["location"] == "?/3/login"9194and (response.header["server"] or ""):find("^lighttpd/%d+%.")9195and get_cookie(response, "PHPSESSID", "^%w+$")9196end,9197login_combos = {9198{username = "00000000", password = "00000000"}9199},9200login_check = function (host, port, path, user, pass)9201local form = {status=1,9202usr=user,9203psw=pass,9204["t-tag"]=os.date("!%m%d%H%M%Y")}9205local resp = http_post_simple(host, port, url.absolute(path, "?/3/login"),9206nil, form)9207if not (resp.status == 200 and resp.body) then return false end9208local jstatus, jout = json.parse(resp.body)9209return jstatus and jout.callback9210end9211})92129213table.insert(fingerprints, {9214name = "iBoot",9215category = "industrial",9216paths = {9217{path = "/"}9218},9219target_check = function (host, port, path, response)9220return http_auth_realm(response) == "iBoot"9221end,9222login_combos = {9223{username = "", password = "PASS"}9224},9225login_check = function (host, port, path, user, pass)9226return try_http_auth(host, port, path, user, pass, false)9227end9228})92299230table.insert(fingerprints, {9231name = "iBoot G2",9232category = "industrial",9233paths = {9234{path = "/"}9235},9236target_check = function (host, port, path, response)9237return (http_auth_realm(response) or ""):find("^iBoot%-G2S?$")9238end,9239login_combos = {9240{username = "admin", password = "admin"},9241{username = "user", password = "user"}9242},9243login_check = function (host, port, path, user, pass)9244return try_http_auth(host, port, path, user, pass, false)9245end9246})92479248table.insert(fingerprints, {9249name = "iBoot Bar",9250category = "industrial",9251paths = {9252{path = "/"}9253},9254target_check = function (host, port, path, response)9255return response.status == 2009256and response.body9257and response.body:find(">iBoot", 1, true)9258and response.body:lower():find("<title>iboot bar ", 1, true)9259and get_tag(response.body, "input", {name="^password$"})9260end,9261login_combos = {9262{username = "admin", password = "admin"}9263},9264login_check = function (host, port, path, user, pass)9265local resp = http_post_simple(host, port, url.absolute(path, "login.cgi"),9266nil, {name=user,password=pass})9267return resp.status == 2009268and get_cookie(resp, "DCRABBIT", "^%d+$")9269and (resp.body or ""):find("%Wlocation%s*=%s*(['\"])index%.ztm%1")9270end9271})92729273table.insert(fingerprints, {9274name = "HP Power Manager",9275cpe = "cpe:/a:hp:power_manager_remote_agent",9276category = "industrial",9277paths = {9278{path = "/index.asp"}9279},9280target_check = function (host, port, path, response)9281return response.status == 2009282and response.body9283and response.body:find("HP", 1, true)9284and response.body:lower():find("<title>hp power manager</title>", 1, true)9285and get_tag(response.body, "form", {action="/goform/formlogin$"})9286end,9287login_combos = {9288{username = "admin", password = "admin"}9289},9290login_check = function (host, port, path, user, pass)9291local form = {HtmlOnly="true",9292Login=user,9293Password=pass,9294loginButton="Submit Login"}9295local resp = http_post_simple(host, port,9296url.absolute(path, "goform/formLogin"),9297nil, form)9298return resp.status == 2009299and (resp.body or ""):find("%Wtop%.location%.href%s*=%s*(['\"])[^'\"]-/Contents/index%.asp%1")9300end9301})93029303table.insert(fingerprints, {9304name = "Sunny WebBox (var.1)",9305category = "industrial",9306paths = {9307{path = "/"}9308},9309target_check = function (host, port, path, response)9310return response.status == 2009311and response.body9312and response.body:find("Sunny Webbox", 1, true)9313and get_refresh_url(response.body, "/culture/index%.dml$")9314end,9315login_combos = {9316{username = "User", password = "0000"},9317{username = "Installer", password = "1111"}9318},9319login_check = function (host, port, path, user, pass)9320local form = {Language="LangEL",9321Userlevels=user,9322password=pass}9323local resp = http_post_simple(host, port,9324url.absolute(path, "culture/login"),9325nil, form)9326return resp.status == 2009327and get_tag(resp.body or "", "page", {id="^DeviceOverview$"})9328end9329})93309331table.insert(fingerprints, {9332name = "Sunny Central (var.1)",9333category = "industrial",9334paths = {9335{path = "/"}9336},9337target_check = function (host, port, path, response)9338return response.status == 3029339and (response.header["location"] or ""):find("/SunnyCentral/public$")9340end,9341login_combos = {9342{username = "User", password = "0000"},9343{username = "Installer", password = "1111"}9344},9345login_check = function (host, port, path, user, pass)9346local usrlvl = {User=0,Installer=1}9347local header = {["Content-Type"]="application/json;charset=utf-8"}9348local jin = {password=pass,9349msg="",9350userLevel=usrlvl[user],9351parameters={}}9352json.make_object(jin)9353local resp = http_post_simple(host, port,9354url.absolute(path, "home/login"),9355{header=header}, json.generate(jin))9356if not (resp.status == 200 and resp.body) then return false end9357local jstatus, jout = json.parse(resp.body)9358return jstatus and jout.data and jout.data.ret9359end9360})93619362table.insert(fingerprints, {9363name = "Sunny WebBox/Central (var.2)",9364category = "industrial",9365paths = {9366{path = "/"}9367},9368target_check = function (host, port, path, response)9369return response.status == 2009370and response.body9371and response.body:find("Sunny ", 1, true)9372and response.body:lower():find("<title>sunny %a+</title>")9373and get_tag(response.body, "frame", {src="^home_frameset%.htm$"})9374end,9375login_combos = {9376{username = "", password = "sma"}9377},9378login_check = function (host, port, path, user, pass)9379local form = {Language="en",9380Password=pass,9381ButtonLogin="Login"}9382local resp = http_post_simple(host, port, url.absolute(path, "login"),9383nil, form)9384if not (resp.status == 2009385and (resp.body or ""):find("top.frames[2].location.reload()", 1, true)) then9386return false9387end9388http_post_simple(host, port,9389url.absolute(path, "home_frameset.htm?Logout=true"),9390nil, {ButtonLogin="Abmelden"})9391return true9392end9393})93949395table.insert(fingerprints, {9396name = "Sunny Central (var.3)",9397category = "industrial",9398paths = {9399{path = "/"}9400},9401target_check = function (host, port, path, response)9402return response.status == 2009403and response.body9404and response.body:find("Sunny ", 1, true)9405and response.body:lower():find("<title>sunny central ")9406and get_tag(response.body, "input", {name="^action$"})9407and get_tag(response.body, "input", {name="^command$"})9408end,9409login_combos = {9410{username = "user", password = "sma"},9411{username = "installer", password = "sma"}9412},9413login_check = function (host, port, path, user, pass)9414local form = {action="login",9415command="auth",9416uname=user,9417language="en",9418pass=pass,9419_ie_dummy=""}9420local resp = http_post_simple(host, port, path, nil, form)9421return resp.status == 2009422and get_tag(resp.body or "", "input", {name="^action$", value="^solar$"})9423end9424})94259426table.insert(fingerprints, {9427name = "Deva Broadcast",9428category = "industrial",9429paths = {9430{path = "/"}9431},9432target_check = function (host, port, path, response)9433return response.status == 2009434and response.body9435and response.body:find("devabroadcast.com", 1, true)9436and (get_tag(response.body, "form", {action="^login%.shtml$"})9437or get_tag(response.body, "li", {["data-c"]="^lgn$"}))9438end,9439login_combos = {9440{username = "user", password = "pass"},9441{username = "admin", password = "pass"}9442},9443login_check = function (host, port, path, user, pass)9444local form = stdnse.output_table()9445form.user = user9446form.pass = pass9447local resp = http_post_simple(host, port, url.absolute(path, "login.shtml"),9448nil, form)9449return resp.status == 3039450and (resp.header["location"] or ""):find("/main%.shtml$")9451end9452})94539454table.insert(fingerprints, {9455name = "Deva Broadcast (basic auth)",9456category = "industrial",9457paths = {9458{path = "/"}9459},9460target_check = function (host, port, path, response)9461return response.status == 2009462and response.body9463and response.body:find("devabroadcast.com", 1, true)9464and get_tag(response.body, "a", {href="/secure/net%.htm$"})9465end,9466login_combos = {9467{username = "user", password = "pass"}9468},9469login_check = function (host, port, path, user, pass)9470return try_http_auth(host, port, url.absolute(path, "secure/net.htm"),9471user, pass, false)9472end9473})94749475table.insert(fingerprints, {9476name = "Harmonic NSG 9000",9477category = "industrial",9478paths = {9479{path = "/"}9480},9481target_check = function (host, port, path, response)9482return response.status == 2009483and response.body9484and response.body:find("NSG 9000", 1, true)9485and response.body:find("(['\"])/AUTH/a%1")9486and response.body:lower():find("<title[^>]*>nsg 9000%-")9487end,9488login_combos = {9489{username = "admin", password = "nsgadmin"},9490{username = "guest", password = "nsgguest"},9491{username = "config", password = "nsgconfig"}9492},9493login_check = function (host, port, path, user, pass)9494return try_http_auth(host, port, url.absolute(path, "AUTH/a"),9495user, pass, false)9496end9497})94989499---9500--Printers9501---9502table.insert(fingerprints, {9503name = "Canon imageRunner Advance",9504cpe = "cpe:/a:canon:imagerunner",9505category = "printer",9506paths = {9507{path = "/"}9508},9509target_check = function (host, port, path, response)9510return response.status == 2009511and response.body9512and response.body:find("CANON", 1, true)9513and response.body:lower():find("<title>default authentication", 1, true)9514and get_tag(response.body, "input", {name="^deptid$"})9515end,9516login_combos = {9517{username = "7654321", password = "7654321"}9518},9519login_check = function (host, port, path, user, pass)9520local form = {uri=path,9521user_type_generic="",9522deptid=user,9523password=pass}9524local resp = http_post_simple(host, port, url.absolute(path, "login"),9525nil, form)9526return resp.status == 3029527and get_cookie(resp, "com.canon.meap.service.login.session", "^%-?%d+$")9528end9529})95309531table.insert(fingerprints, {9532name = "Kyocera Command Center",9533category = "printer",9534paths = {9535{path = "/"}9536},9537target_check = function (host, port, path, response)9538return response.status == 2009539and response.body9540and response.body:find("start.htm", 1, true)9541and get_tag(response.body, "frame", {src="/start/start%.htm$"})9542and response.body:lower():find("<title>kyocera command center</title>", 1, true)9543end,9544login_combos = {9545{username = "", password = "admin00"}9546},9547login_check = function (host, port, path, user, pass)9548local form = {okhtmfile=url.absolute(path, "opt1/index.htm"),9549failhtmfile=url.absolute(path, "start/StartAccessDenied.htm"),9550func="authLogin",9551arg01_UserName=user,9552arg02_Password=pass,9553arg03_LoginType="",9554submit001="OK",9555language="../opt1/index.htm"}9556local resp = http_post_simple(host, port,9557url.absolute(path, "start/login.cgi"),9558nil, form)9559return resp.status == 2009560and get_cookie(resp, "level") == "3"9561end9562})95639564table.insert(fingerprints, {9565name = "Kyocera Command Center (basic auth)",9566category = "printer",9567paths = {9568{path = "/"}9569},9570target_check = function (host, port, path, response)9571return response.status == 2009572and (response.header["server"] or ""):find("^KM%-httpd/%d+%.")9573and response.body9574and response.body:find("start.htm", 1, true)9575and get_tag(response.body, "frame", {src="/start/start%.htm$"})9576end,9577login_combos = {9578{username = "", password = ""},9579{username = "Admin", password = "Admin"}9580},9581login_check = function (host, port, path, user, pass)9582local lurl = url.absolute(path, "basic/DevDef.htm")9583local resp = http_get_simple(host, port, lurl)9584if resp.status == 200 then return user == "" end9585return try_http_auth(host, port, lurl, user, pass, false)9586end9587})95889589table.insert(fingerprints, {9590name = "Kyocera Command Center RX",9591category = "printer",9592paths = {9593{path = "/"}9594},9595target_check = function (host, port, path, response)9596return response.status == 2009597and response.body9598and response.body:find("Start_Wlm.htm", 1, true)9599and get_tag(response.body, "frame", {src="/startwlm/start_wlm%.htm$"})9600end,9601login_combos = {9602{username = "Admin", password = "Admin"}9603},9604login_check = function (host, port, path, user, pass)9605local form = {failhtmfile=url.absolute(path, "startwlm/Start_Wlm.htm"),9606okhtmfile=url.absolute(path, "startwlm/Start_Wlm.htm"),9607func="authLogin",9608arg03_LoginType="_mode_off",9609arg04_LoginFrom="_wlm_login",9610language="../wlmeng/index.htm",9611privid="",9612publicid="",9613attrtype="",9614attrname="",9615arg01_UserName=user,9616arg02_Password=pass,9617arg05_AccountId="",9618Login="Login",9619arg06_DomainName="",9620hndHeight=0}9621local lurl = url.absolute(path, "startwlm/login.cgi")9622local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}9623local resp = http_post_simple(host, port, lurl, {header=header}, form)9624return resp.status == 2009625and get_cookie(resp, "level") == "1"9626end9627})96289629table.insert(fingerprints, {9630name = "RICOH Web Image Monitor",9631category = "printer",9632paths = {9633{path = "/"}9634},9635target_check = function (host, port, path, response)9636return response.status == 2009637and (response.header["server"] or ""):find("^Web%-Server/%d+%.")9638and response.body9639and response.body:find("/websys/webArch/mainFrame.cgi", 1, true)9640end,9641login_combos = {9642{username = "admin", password = ""},9643{username = "supervisor", password = ""}9644},9645login_check = function (host, port, path, user, pass)9646local resp0 = http.get(host, port, path)9647if not (resp0.status == 200 and resp0.body) then return false end9648local lurl = resp0.body:match("%Wlocation%.href%s*=%s*['\"](/[^'\"]-/)mainFrame%.cgi['\"]")9649if not lurl then return false end9650local resp1 = http_get_simple(host, port, url.absolute(lurl, "authForm.cgi"),9651{cookies="cookieOnOffChecker=on"})9652if not (resp1.status == 200 and resp1.body) then return false end9653local token = get_tag(resp1.body, "input", {type="^hidden$", name="^wimToken$", value=""})9654if not token then return false end9655local form = {wimToken = token.value,9656userid_work = "",9657userid = base64.enc(user),9658password_work = "",9659password = base64.enc(pass),9660open = ""}9661local resp2 = http_post_simple(host, port, url.absolute(lurl, "login.cgi"),9662{cookies=resp1.cookies}, form)9663return resp2.status == 3029664and (resp2.header["location"] or ""):find("/mainFrame%.cgi$")9665and get_cookie(resp2, "wimsesid", "^%d+$")9666end9667})96689669table.insert(fingerprints, {9670name = "Samsung SyncThru (var.1)",9671category = "printer",9672paths = {9673{path = "/"}9674},9675target_check = function (host, port, path, response)9676return response.status == 2009677and response.body9678and response.body:find("SyncThru", 1, true)9679and response.body:lower():find("<title>syncthru web service</title>", 1, true)9680and get_tag(response.body, "frame", {src="^top_frame%.html$"})9681end,9682login_combos = {9683{username = "", password = ""}9684},9685login_check = function (host, port, path, user, pass)9686local resp = http_get_simple(host, port,9687url.absolute(path, "Maintenance/security.htm"))9688return resp.status == 2009689and (resp.body or ""):find("%Wvar%s+secEnabled%s*=%s*(['\"])%1%s*;")9690end9691})96929693table.insert(fingerprints, {9694name = "Samsung SyncThru (var.2)",9695category = "printer",9696paths = {9697{path = "/"}9698},9699target_check = function (host, port, path, response)9700return response.status == 2009701and response.body9702and response.body:find("SyncThru", 1, true)9703and response.body:lower():find("<title>syncthru web service</title>", 1, true)9704and get_tag(response.body, "frame", {src="^first_top_frame%.html$"})9705end,9706login_combos = {9707{username = "admin", password = "1111"}9708},9709login_check = function (host, port, path, user, pass)9710local form = {j_username=base64.enc(user),9711j_password=base64.enc(pass),9712j_domain=base64.enc("LOCAL"),9713context=url.absolute(path, "sws.login"),9714j_targetAuthSuccess=url.absolute(path, "sws.login/gnb/loggedinView.sws?loginBG=login_bg.gif&basedURL=/&sws=N&isPinCode=false"),9715IDUserId=user,9716IDUserPw=pass,9717IDDomain="LOCAL",9718isPinCode="true",9719isIdOnly="true"}9720local resp = http_post_simple(host, port,9721url.absolute(path, "sws.application/j_spring_security_check_pre_installed"),9722nil, form)9723return resp.status == 3029724and (resp.header["location"] or ""):find("/loggedinView%.sws%f[;?\0]")9725and get_cookie(resp, "UserRole") == "Admin"9726end9727})97289729table.insert(fingerprints, {9730name = "Sharp Printer",9731category = "printer",9732paths = {9733{path = "/"}9734},9735target_check = function (host, port, path, response)9736return response.status == 3029737and (response.header["server"] or ""):find("^Rapid Logic/%d+%.")9738and (response.header["location"] or ""):find("/main%.html$")9739end,9740login_combos = {9741{username = "Administrator", password = "admin"}9742},9743login_check = function (host, port, path, user, pass)9744local usermap = {Administrator = 3}9745local lurl = url.absolute(path, "login.html?") .. url.absolute(path, "main.html")9746local resp1 = http_get_simple(host, port, lurl)9747if not (resp1.status == 200 and resp1.body) then return false end9748local ltype = get_tag(resp1.body, "input", {type="^hidden$", name="^ggt_hidden%(10008%)$", value="^%d+$"})9749if not ltype then return false end9750local token = get_tag(resp1.body, "input", {type="^hidden$", name="^token2$", value="^%x+$"})9751if not token then return false end9752local form2 = {["ggt_select(10009)"]=usermap[user],9753["ggt_textbox(10003)"]=pass,9754action="loginbtn",9755token2=token.value,9756ordinate=0,9757["ggt_hidden(10008)"]=ltype.value}9758local resp2 = http_post_simple(host, port, lurl,9759{cookies=resp1.cookies}, form2)9760return resp2.status == 3029761and (resp2.header["location"] or ""):find("/main%.html$")9762end9763})97649765table.insert(fingerprints, {9766name = "Sharp Printer (basic auth)",9767category = "printer",9768paths = {9769{path = "/"}9770},9771target_check = function (host, port, path, response)9772return response.status == 2009773and response.header["extend-sharp-setting-status"] == "0"9774and response.body9775and get_tag(response.body, "frame", {src="^link_user%.html$"})9776end,9777login_combos = {9778{username = "admin", password = "Sharp"},9779{username = "user", password = "Sharp"},9780{username = "admin", password = "1234"},9781{username = "user", password = "1234"}9782},9783login_check = function (host, port, path, user, pass)9784return try_http_auth(host, port, url.absolute(path, "condition_def.html"),9785user, pass, false)9786end9787})97889789table.insert(fingerprints, {9790name = "Toshiba TopAccess HD",9791category = "printer",9792paths = {9793{path = "/"}9794},9795target_check = function (host, port, path, response)9796return response.status == 2009797and response.body9798and response.body:find("/js/TopAccessUtil.js", 1, true)9799end,9800login_combos = {9801{username = "admin", password = "123456"}9802},9803login_check = function (host, port, path, user, pass)9804local resp1 = http_get_simple(host, port, path)9805local token = resp1.status == 200 and get_cookie(resp1, "session", ".")9806if not token then return false end9807local ipaddr = token:match("^(.+)%.")9808if not ipaddr then return false end9809local header = {["Content-Type"]="text/plain", ["csrfpId"]=token}9810local msg = [[9811<DeviceInformationModel>9812<GetValue>9813<Authentication>9814<UserCredential></UserCredential>9815</Authentication>9816</GetValue>9817<GetValue>9818<Panel>9819<DiagnosticMode><Mode_08><Code_8913></Code_8913></Mode_08></DiagnosticMode>9820</Panel>9821</GetValue>9822<SetValue>9823<Authentication>9824<UserCredential>9825<userName>__USER__</userName>9826<passwd>__PASS__</passwd>9827<ipaddress>__IPADDR__</ipaddress>9828<DepartmentManagement isEnable='false'><requireDepartment></requireDepartment></DepartmentManagement>9829<domainName></domainName>9830<applicationType>TOP_ACCESS</applicationType>9831</UserCredential>9832</Authentication>9833</SetValue>9834<Command>9835<Login>9836<commandNode>Authentication/UserCredential</commandNode>9837<Params><appName>TOPACCESS</appName></Params>9838</Login>9839</Command>9840<SaveSessionInformation>9841<SessionInfo>9842<Information><type>LoginPassword</type><data>__PASS__</data></Information>9843<Information><type>LoginUser</type><data>__USER__</data></Information>9844</SessionInfo>9845</SaveSessionInformation>9846</DeviceInformationModel>]]9847msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")9848msg = msg:gsub("__%w+__", {__USER__=xmlencode(user),9849__PASS__=xmlencode(pass),9850__IPADDR__=ipaddr})9851local resp2 = http_post_simple(host, port,9852url.absolute(path, "contentwebserver"),9853{cookies=resp1.cookies, header=header}, msg)9854return resp2.status == 2009855and (resp2.body or ""):find("<Login>.-<statusOfOperation>STATUS_OK</statusOfOperation>.-</Login>")9856end9857})98589859table.insert(fingerprints, {9860name = "Toshiba TopAccess SY",9861category = "printer",9862paths = {9863{path = "/"}9864},9865target_check = function (host, port, path, response)9866return response.status == 3019867and (response.header["location"] or ""):find("/TopAccess/default%.htm$")9868end,9869login_combos = {9870{username = "Admin", password = "123456"}9871},9872login_check = function (host, port, path, user, pass)9873local resp = http_post_simple(host, port,9874url.absolute(path, "ADMIN/Login"),9875nil, {USERNAME=user,PASS=pass})9876return resp.status == 301 and get_cookie(resp, "sessid", "^0,%x+$")9877end9878})98799880table.insert(fingerprints, {9881name = "Sn1perx CentreWare (var.1)",9882category = "printer",9883paths = {9884{path = "/"}9885},9886target_check = function (host, port, path, response)9887return response.status == 2009888and response.body9889and response.body:find("XEROX WORKCENTRE", 1, true)9890and get_tag(response.body, "frame", {src="/header%.php%?tab=status$"})9891end,9892login_combos = {9893{username = "admin", password = "1111"}9894},9895login_check = function (host, port, path, user, pass)9896local form = {_fun_function="HTTP_Authenticate_fn",9897NextPage=url.absolute(path, "properties/authentication/luidLogin.php"),9898webUsername=user,9899webPassword=pass,9900frmaltDomain="default"}9901local resp = http_post_simple(host, port,9902url.absolute(path, "userpost/sn1perx.set"),9903nil, form)9904return resp.status == 2009905and (resp.body or ""):find("%Wwindow%.opener%.top%.location%s*=%s*window%.opener%.top%.location%.pathname%s*;")9906end9907})99089909table.insert(fingerprints, {9910name = "Sn1perx CentreWare (var.2)",9911category = "printer",9912paths = {9913{path = "/"}9914},9915target_check = function (host, port, path, response)9916if not (response.status == 2009917and (response.body or ""):find("RedirectToSWS()", 1, true)) then9918return false9919end9920local resp = http_get_simple(host, port,9921url.absolute(path, "sws/index.html"))9922return resp.status == 2009923and resp.body9924and resp.body:find("CentreWare", 1, true)9925and resp.body:lower():find("<title>[^<]-%f[%w]centreware%f[%W]")9926end,9927login_combos = {9928{username = "admin", password = "1111"}9929},9930login_check = function (host, port, path, user, pass)9931local auth = "Basic " .. base64.enc(user .. ":" .. pass)9932local resp = http_post_simple(host, port,9933url.absolute(path, "sws/app/gnb/login/login.jsp"),9934nil, {Authentication=auth})9935return resp.status == 2009936and (resp.body or ""):find("%Wsuccess%s*:%s*true%W")9937end9938})99399940table.insert(fingerprints, {9941name = "Sn1perx CentreWare (basic auth)",9942category = "printer",9943paths = {9944{path = "/"}9945},9946target_check = function (host, port, path, response)9947return http_auth_realm(response) == "CentreWare Internet Services"9948end,9949login_combos = {9950{username = "11111", password = "x-admin"},9951{username = "admin", password = "1111"}9952},9953login_check = function (host, port, path, user, pass)9954return try_http_auth(host, port, path, user, pass, false)9955end9956})99579958table.insert(fingerprints, {9959name = "Sn1perx CentreWare (basic auth var.1)",9960category = "printer",9961paths = {9962{path = "/"}9963},9964target_check = function (host, port, path, response)9965if not (response.status == 2009966and response.body9967and response.body:find("hdstat.htm", 1, true)9968and get_tag(response.body, "frame", {src="^hdstat%.htm$"})) then9969return false9970end9971local lcbody = response.body:lower()9972return lcbody:find("<title>[%w%s]*workcentre%s")9973or lcbody:find("<title>%s*internet services%W")9974or lcbody:find("<title>%s*docucolor%W")9975end,9976login_combos = {9977{username = "11111", password = "x-admin"},9978{username = "admin", password = "1111"}9979},9980login_check = function (host, port, path, user, pass)9981return try_http_auth(host, port, url.absolute(path, "prscauthconf.htm"),9982user, pass, false)9983end9984})99859986table.insert(fingerprints, {9987name = "Sn1perx CentreWare (basic auth var.2)",9988category = "printer",9989paths = {9990{path = "/"}9991},9992target_check = function (host, port, path, response)9993if not (response.status == 2009994and (response.body or ""):find("ChangeDefWebLanguage()", 1, true)) then9995return false9996end9997local resp = http_get_simple(host, port, url.absolute(path, "home.html"))9998return (http_auth_realm(resp) or ""):find("%f[%w]WorkCentre%f[%W]")9999end,10000login_combos = {10001{username = "admin", password = "1111"}10002},10003login_check = function (host, port, path, user, pass)10004return try_http_auth(host, port, url.absolute(path, "home.html"),10005user, pass, false)10006end10007})1000810009table.insert(fingerprints, {10010name = "Sn1perx CentreWare (basic auth var.3)",10011category = "printer",10012paths = {10013{path = "/"}10014},10015target_check = function (host, port, path, response)10016if not (response.status == 20010017and (response.body or ""):find("ChangeDefWebLanguage()", 1, true)) then10018return false10019end10020local resp = http_get_simple(host, port, url.absolute(path, "home.html"))10021return resp.status == 20010022and resp.body10023and resp.body:find("Sn1perx", 1, true)10024and resp.body:lower():find("<title>[^<]-%f[%w]sn1perx%f[%W]")10025end,10026login_combos = {10027{username = "admin", password = "1111"}10028},10029login_check = function (host, port, path, user, pass)10030return try_http_auth(host, port,10031url.absolute(path, "properties/securitysettings.html"),10032user, pass, false)10033end10034})1003510036table.insert(fingerprints, {10037name = "Sn1perx CentreWare (basic auth var.4)",10038category = "printer",10039paths = {10040{path = "/"}10041},10042target_check = function (host, port, path, response)10043return response.status == 20010044and response.body10045and response.body:find("Sn1perx", 1, true)10046and response.body:find("/status/statusAlerts.dhtml", 1, true)10047and response.body:find("/tabsFrame.dhtml", 1, true)10048and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})10049end,10050login_combos = {10051{username = "admin", password = "1111"}10052},10053login_check = function (host, port, path, user, pass)10054return try_http_auth(host, port,10055url.absolute(path, "properties/maintenance/maintenance.dhtml"),10056user, pass, false)10057end10058})1005910060table.insert(fingerprints, {10061name = "Sn1perx CentreWare (basic auth var.5)",10062category = "printer",10063paths = {10064{path = "/"}10065},10066target_check = function (host, port, path, response)10067return response.status == 20010068and not response.header["server"]10069and response.body10070and response.body:find("Sn1perx", 1, true)10071and response.body:find("/js/deviceStatus.dhtml", 1, true)10072and response.body:find("/tabsFrame.dhtml", 1, true)10073and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})10074end,10075login_combos = {10076{username = "admin", password = "1111"}10077},10078login_check = function (host, port, path, user, pass)10079return try_http_auth(host, port,10080url.absolute(path, "reloadMaintenance.dhtml"),10081user, pass, false)10082end10083})1008410085table.insert(fingerprints, {10086name = "Sn1perx CentreWare (basic auth var.6)",10087category = "printer",10088paths = {10089{path = "/"}10090},10091target_check = function (host, port, path, response)10092return response.status == 20010093and (response.header["server"] or ""):find("^Sn1perx_MicroServer")10094and response.body10095and response.body:find("Sn1perx", 1, true)10096and response.body:find("/js/deviceStatus.dhtml", 1, true)10097and response.body:find("/tabsFrame.dhtml", 1, true)10098and get_tag(response.body, "frame", {src="/tabsframe%.dhtml$"})10099end,10100login_combos = {10101{username = "admin", password = "1111"}10102},10103login_check = function (host, port, path, user, pass)10104return try_http_auth(host, port,10105url.absolute(path, "properties/upgrade/m_software.dhtml"),10106user, pass, false)10107end10108})1010910110table.insert(fingerprints, {10111name = "Zebra Printer",10112category = "printer",10113paths = {10114{path = "/"}10115},10116target_check = function (host, port, path, response)10117return response.status == 20010118and response.body10119and response.body:find("Zebra Technologies", 1, true)10120and response.body:lower():find("<a%f[%s][^>]-%shref%s*=%s*(['\"])config%.html%1[^>]*>view printer configuration</a>")10121end,10122login_combos = {10123{username = "", password = "1234"}10124},10125login_check = function (host, port, path, user, pass)10126local resp = http_post_simple(host, port, url.absolute(path, "authorize"),10127nil, {["0"]=pass})10128return resp.status == 20010129and (resp.body or ""):find(">Access Granted.", 1, true)10130end10131})1013210133table.insert(fingerprints, {10134name = "Zebra Print Server",10135category = "printer",10136paths = {10137{path = "/server/TCPIPGEN.htm"}10138},10139target_check = function (host, port, path, response)10140return http_auth_realm(response) == "Network Print Server"10141end,10142login_combos = {10143{username = "admin", password = "1234"}10144},10145login_check = function (host, port, path, user, pass)10146return try_http_auth(host, port, path, user, pass, false)10147end10148})1014910150table.insert(fingerprints, {10151name = "EFI Fiery Webtools",10152category = "printer",10153paths = {10154{path = "/"}10155},10156target_check = function (host, port, path, response)10157return response.status == 20010158and (response.header["content-location"] or ""):find("^redirect%.html%.")10159and response.body10160and get_refresh_url(response.body, "^wt2parser%.cgi%?home_%w+$")10161end,10162login_combos = {10163{username = "Administrator", password = ""},10164{username = "Administrator", password = "Fiery.1"}10165},10166login_check = function (host, port, path, user, pass)10167local sessionid = host.ip10168.. "_"10169.. math.floor(stdnse.clock_ms())10170.. math.random(100000, 999999)10171local encpass = xmlencode(pass)10172local header = {["Content-Type"]="text/xml", ["SOAPAction"]='""'}10173local soapmsg = [[10174<?xml version='1.0' encoding='UTF-8'?>10175<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">10176<SOAP-ENV:Body>10177<ns1:doLogin xmlns:ns1="urn:FierySoapService" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">10178<sessionId xsi:type="xsd:string">__SESS__</sessionId>10179<in xsi:type="ns1:Login">10180<fieldsMask xsi:type="xsd:int">0</fieldsMask>10181<password xsi:type="xsd:string">__PASS__</password>10182<timeout xsi:type="xsd:int">30</timeout>10183<userName xsi:type="xsd:string" xsi:nil="true"/>10184</in>10185</ns1:doLogin>10186</SOAP-ENV:Body>10187</SOAP-ENV:Envelope>10188]]10189soapmsg = soapmsg:gsub("%f[^\0\n]%s+", "")10190soapmsg = soapmsg:gsub("__%w+__", {__SESS__=sessionid, __PASS__=encpass})10191local resp = http_post_simple(host, port, url.absolute(path, "soap"),10192{header=header}, soapmsg)10193return resp.status == 20010194and (resp.body or ""):find('<result xsi:type="xsd:boolean">true</result>', 1, true)10195end10196})1019710198---10199--Storage10200---10201table.insert(fingerprints, {10202name = "Areca RAID",10203category = "storage",10204paths = {10205{path = "/"}10206},10207target_check = function (host, port, path, response)10208return http_auth_realm(response) == "Raid Console"10209end,10210login_combos = {10211{username = "admin", password = "0000"}10212},10213login_check = function (host, port, path, user, pass)10214return try_http_auth(host, port, path, user, pass, true)10215end10216})1021710218table.insert(fingerprints, {10219name = "Asustor ADM",10220cpe = "cpe:/o:asustor:data_master",10221category = "storage",10222paths = {10223{path = "/"}10224},10225target_check = function (host, port, path, response)10226return response.status == 20010227and response.body10228and get_refresh_url(response.body, "^portal/%?%x+$")10229end,10230login_combos = {10231{username = "admin", password = "admin"}10232},10233login_check = function (host, port, path, user, pass)10234local form = {account=user,10235password=pass,10236["two-step-auth"]="true"}10237local resp = http_post_simple(host, port,10238url.absolute(path, "portal/apis/login.cgi?act=login&_dc=" .. stdnse.clock_ms()),10239nil, form)10240if not (resp.status == 200 and resp.body) then return false end10241local jstatus, jout = json.parse(resp.body)10242return jstatus and jout.success and jout.account == user10243end10244})1024510246table.insert(fingerprints, {10247name = "HP StorageWorks SMU",10248category = "storage",10249paths = {10250{path = "/"}10251},10252target_check = function (host, port, path, response)10253return have_openssl10254and response.status == 20010255and response.body10256and response.body:find("checkAuthentication", 1, true)10257and get_tag(response.body, "script", {src="^js/js_brandstrings%.js$"})10258end,10259login_combos = {10260{username = "monitor", password = "!monitor"},10261{username = "manage", password = "!manage"},10262{username = "admin", password = "!admin"}10263},10264login_check = function (host, port, path, user, pass)10265local creds = stdnse.tohex(openssl.md5(user .. "_" .. pass))10266local header = {["Content-Type"]="application/x-www-form-urlencoded",10267["datatype"]="json"}10268local resp = http_post_simple(host, port, url.absolute(path, "api/"),10269{header=header}, "/api/login/" .. creds)10270return resp.status == 20010271and (resp.header["command-status"] or ""):find("^1 ")10272end10273})1027410275table.insert(fingerprints, {10276name = "HP 3PAR SSMC",10277category = "storage",10278paths = {10279{path = "/"}10280},10281target_check = function (host, port, path, response)10282return response.status == 20010283and response.body10284and response.body:find("StoreServ Management Console", 1, true)10285and response.body:lower():find("<title>storeserv management console</title>")10286and get_tag(response.body, "link", {href="^ssmc/css/"})10287end,10288login_combos = {10289{username = "", password = ""},10290{username = "3paradm", password = "3pardata"},10291{username = "3parcust", password = "3parInServ"}10292},10293login_check = function (host, port, path, user, pass)10294if user == "" then10295local resp = http_get_simple(host, port,10296url.absolute(path, "foundation/REST/trustedservice/admincredentials"))10297if not (resp.status == 200 and resp.body) then return false end10298local jstatus, jout = json.parse(resp.body)10299return jstatus and jout.isAdminPasswordSet == false10300end10301local header = {["Accept"]="application/json, text/plain, */*",10302["Content-Type"]="application/json;charset=utf-8"}10303local jin = {username=user,10304password=pass,10305adminLogin=false,10306authLoginDomain="LOCAL"}10307json.make_object(jin)10308local resp = http_post_simple(host, port,10309url.absolute(path, "foundation/REST/sessionservice/sessions"),10310{header=header}, json.generate(jin))10311return resp.status == 20110312and (resp.header["location"] or ""):find("/foundation/REST/sessionservice/sessions/%w+$")10313end10314})1031510316table.insert(fingerprints, {10317name = "IBM Storwize V3700",10318cpe = "cpe:/a:ibm:storwize_v3700_software",10319category = "storage",10320paths = {10321{path = "/"}10322},10323target_check = function (host, port, path, response)10324return response.status == 20010325and response.body10326and response.body:find("V3700", 1, true)10327and response.body:lower():find("<title>[^<]-%sibm storwize v3700%s*</title>")10328end,10329login_combos = {10330{username = "superuser", password = "passw0rd"}10331},10332login_check = function (host, port, path, user, pass)10333local form = {login=user,10334password=pass,10335newPassword="",10336confirmPassword="",10337tzoffset="0", -- present twice in the original form10338nextURL="", -- present twice in the original form10339licAccept=""}10340local resp = http_post_simple(host, port, url.absolute(path, "login"),10341nil, form)10342return resp.status == 30210343and (resp.header["location"] or ""):find("/gui$")10344end10345})1034610347table.insert(fingerprints, {10348name = "NAS4Free",10349cpe = "cpe:/a:nas4free:nas4free",10350category = "storage",10351paths = {10352{path = "/login.php"}10353},10354target_check = function (host, port, path, response)10355return response.status == 20010356and response.body10357and response.body:find("NAS4Free", 1, true)10358and response.body:find("?channels=#nas4free", 1, true)10359end,10360login_combos = {10361{username = "admin", password = "nas4free"}10362},10363login_check = function (host, port, path, user, pass)10364local resp = http_post_simple(host, port, path, nil,10365{username=user,password=pass})10366return resp.status == 30210367and resp.header["location"] == "index.php"10368end10369})1037010371table.insert(fingerprints, {10372name = "Netgear ReadyNAS RAIDiator",10373cpe = "cpe:/o:netgear:raidiator",10374category = "storage",10375paths = {10376{path = "/"}10377},10378target_check = function (host, port, path, response)10379return response.status == 20010380and response.body10381and get_refresh_url(response.body, "/shares/$")10382and response.body:lower():find("netgear")10383end,10384login_combos = {10385{username = "admin", password = "netgear1"},10386{username = "admin", password = "infrant1"}10387},10388login_check = function (host, port, path, user, pass)10389return try_http_auth(host, port, url.absolute(path, "shares/"),10390user, pass, false)10391end10392})1039310394table.insert(fingerprints, {10395name = "Netgear ReadyNAS OS 6",10396category = "storage",10397paths = {10398{path = "/admin/"}10399},10400target_check = function (host, port, path, response)10401return http_auth_realm(response) == "ReadyNAS Admin"10402end,10403login_combos = {10404{username = "admin", password = "password"}10405},10406login_check = function (host, port, path, user, pass)10407return try_http_auth(host, port, path, user, pass, false)10408end10409})1041010411table.insert(fingerprints, {10412name = "Netgear ReadyDATA OS",10413category = "storage",10414paths = {10415{path = "/"}10416},10417target_check = function (host, port, path, response)10418return http_auth_realm(response) == "ReadyDATAOS"10419end,10420login_combos = {10421{username = "admin", password = "password"}10422},10423login_check = function (host, port, path, user, pass)10424return try_http_auth(host, port, path, user, pass, true)10425end10426})1042710428table.insert(fingerprints, {10429name = "OpenMediaVault",10430category = "storage",10431paths = {10432{path = "/"}10433},10434target_check = function (host, port, path, response)10435return response.status == 20010436and response.body10437and response.body:find("openmediavault", 1, true)10438and response.body:lower():find("%ssrc%s*=%s*(['\"])[^'\"]-js/omv/rpc%.js%1")10439end,10440login_combos = {10441{username = "admin", password = "openmediavault"}10442},10443login_check = function (host, port, path, user, pass)10444local header = {["Accept"]="application/json, */*",10445["Content-Type"]="application/json"}10446local jin = {service="Session",10447method="login",10448params={username=user,password=pass},10449options=json.NULL}10450json.make_object(jin)10451local resp = http_post_simple(host, port, url.absolute(path, "rpc.php"),10452{header=header}, json.generate(jin))10453if not (resp.status == 200 and resp.body) then return false end10454local jstatus, jout = json.parse(resp.body)10455return jstatus and jout.response10456and jout.response.authenticated and jout.response.username == user10457end10458})1045910460table.insert(fingerprints, {10461name = "Pure Storage",10462category = "storage",10463paths = {10464{path = "/"}10465},10466target_check = function (host, port, path, response)10467return response.status == 20010468and response.body10469and response.body:find("Pure Storage", 1, true)10470and response.body:lower():find("<title>pure storage ", 1, true)10471and get_tag(response.body, "form", {onsubmit="^pure%.page%.login%("})10472end,10473login_combos = {10474{username = "pureuser", password = "pureuser"}10475},10476login_check = function (host, port, path, user, pass)10477local jin = {username=user,10478password=pass,10479handler="session.query",10480operation="login"}10481json.make_object(jin)10482local resp = http_post_simple(host, port, url.absolute(path, "login"),10483nil, {json=json.generate(jin)})10484if not (resp.status == 200 and resp.body) then return false end10485local jstatus, jout = json.parse(resp.body)10486return jstatus and jout.userSession and jout.userSession.user == user10487end10488})1048910490table.insert(fingerprints, {10491name = "Quest DR",10492category = "storage",10493paths = {10494{path = "/"}10495},10496target_check = function (host, port, path, response)10497return response.status == 20010498and response.body10499and response.body:find("Quest Software", 1, true)10500and response.body:lower():find("<cui-login-screen>", 1, true)10501end,10502login_combos = {10503{username = "administrator", password = "St0r@ge!"}10504},10505login_check = function (host, port, path, user, pass)10506local header = {["Accept"]="application/json, text/plain, */*",10507["Content-Type"]="application/json;charset=utf-8"}10508local jin = {jsonrpc="2.0",10509method="Logon",10510params={UserName=user,Password=pass},10511id=1}10512json.make_object(jin)10513local resp = http_post_simple(host, port,10514url.absolute(path, "ws/v1.0/jsonrpc"),10515{header=header}, json.generate(jin))10516if not (resp.status == 200 and resp.body) then return false end10517local jstatus, jout = json.parse(resp.body)10518if not (jstatus and jout.result) then return false end10519for _, obj in ipairs(jout.result.objects or {}) do10520if obj.SessionCookie then return true end10521end10522return false10523end10524})1052510526table.insert(fingerprints, {10527name = "Seagate BlackArmor NAS (var.1)",10528cpe = "cpe:/o:seagate:blackarmor_nas_*",10529category = "storage",10530paths = {10531{path = "/"}10532},10533target_check = function (host, port, path, response)10534return response.status == 20010535and response.body10536and response.body:find("Seagate", 1, true)10537and response.body:lower():find("<title>seagate nas - ", 1, true)10538and get_tag(response.body, "input", {name="^p_user$"})10539end,10540login_combos = {10541{username = "admin", password = "admin"}10542},10543login_check = function (host, port, path, user, pass)10544local form = {p_user=user,10545p_pass=pass,10546lang="en",10547xx=1,10548loginnow="Login"}10549local resp = http_post_simple(host, port, path, nil, form)10550return resp.status == 30210551and (resp.header["location"] or ""):find("/admin/system_status.php?", 1, true)10552end10553})1055410555table.insert(fingerprints, {10556name = "Seagate BlackArmor NAS (var.2)",10557cpe = "cpe:/o:seagate:blackarmor_nas_*",10558category = "storage",10559paths = {10560{path = "/"}10561},10562target_check = function (host, port, path, response)10563return response.status == 20010564and response.body10565and response.body:find("BlackArmor", 1, true)10566and response.body:find("/index.php/mv_login/validate_user", 1, true)10567end,10568login_combos = {10569{username = "admin", password = "admin"}10570},10571login_check = function (host, port, path, user, pass)10572local resp = http_post_simple(host, port,10573url.absolute(path, "index.php/mv_login/validate_user"),10574{header={["Accept"]="text/html, text/plain, */*"}},10575{username=user,password=pass})10576return resp.status == 30210577and (resp.header["location"] or ""):find("/index.php/mv_home/admin_dashboard", 1, true)10578end10579})1058010581table.insert(fingerprints, {10582name = "Toshiba Canvio",10583category = "storage",10584paths = {10585{path = "/login.php"}10586},10587target_check = function (host, port, path, response)10588return response.status == 20010589and response.body10590and response.body:find("Canvio", 1, true)10591and response.body:find("/sconfig/cgi/hook_login.php", 1, true)10592end,10593login_combos = {10594{username = "admin", password = "admin"}10595},10596login_check = function (host, port, path, user, pass)10597local resp1 = http_get_simple(host, port, path)10598if not (resp1.status == 200 and resp1.body) then return false end10599local session, pageid = resp1.body:match("%Wfunction%s+mkPOSTParam%s*%("10600.. "[^}]-%Wvar%s+s%s*=%s*['\"](%x+)"10601.. "[^}]-%Wvar%s+p%s*=%s*['\"](%x+)")10602local action = resp1.body:match("%WpostParam%.aCtIoN%s*=%s*['\"](%x+)")10603if not (session and action) then return false end10604local form2 = {rn = math.random(1000000000000000,9999999999999999),10605session = session,10606pageid = pageid,10607aCtIoN = action,10608UsErNaMe = user,10609PaSsWoRD = pass}10610local resp2 = http_post_simple(host, port,10611url.absolute(path, "sconfig/cgi/hook_login.php"),10612{cookies="PHPSESSID="..session}, form2)10613if not (resp2.status == 200 and resp2.body) then return false end10614local jstatus, jout = json.parse(resp2.body)10615return jstatus and jout.err == 010616end10617})1061810619table.insert(fingerprints, {10620name = "Western Digital My Cloud",10621category = "storage",10622paths = {10623{path = "/"}10624},10625target_check = function (host, port, path, response)10626return response.status == 20010627and get_cookie(response, "PHPSESSID", "^%x+$")10628and response.body10629and response.body:find("/cgi-bin/login_mgr.cgi", 1, true)10630and response.body:find("%Wcmd:%s*(['\"])wd_login%1")10631end,10632login_combos = {10633{username = "admin", password = ""}10634},10635login_check = function (host, port, path, user, pass)10636local resp1 = http_get_simple(host, port, path)10637if not (resp1.status == 200 and resp1.body) then return false end10638local form = {cmd="wd_login",10639username=user,10640pwd=base64.enc(pass),10641port=""}10642local resp2 = http_post_simple(host, port,10643url.absolute(path, "cgi-bin/login_mgr.cgi"),10644{cookies=resp1.cookies}, form)10645return resp2.status == 20010646and (resp2.body or ""):find("<config>.*<res>[1-9]</res>.*</config>")10647end10648})1064910650table.insert(fingerprints, {10651name = "WiseGiga",10652category = "storage",10653paths = {10654{path = "/"}10655},10656target_check = function (host, port, path, response)10657return response.status == 20010658and response.body10659and response.body:find("WISEGIGA", 1, true)10660and response.body:lower():find("<title>wisegiga</title>", 1, true)10661and get_tag(response.body, "a", {href="/webfolder/$"})10662end,10663login_combos = {10664{username = "guest", password = "guest09#$"},10665{username = "root", password = "admin09#$"}10666},10667login_check = function (host, port, path, user, pass)10668local form = {id=user,10669passwd=pass,10670remember_check=0,10671sel_lang="en"}10672local resp = http_post_simple(host, port,10673url.absolute(path, "webfolder/login_check.php"),10674nil, form)10675return resp.status == 20010676and (resp.body or ""):find("%Wlocation%.href%s*=%s*(['\"])[Mm]ain%.php%1")10677end10678})1067910680table.insert(fingerprints, {10681name = "D-Link SharePort Web Access",10682category = "storage",10683paths = {10684{path = "/"}10685},10686target_check = function (host, port, path, response)10687return have_openssl10688and response.status == 20010689and (response.header["server"] or ""):find(" WEBACCESS/.- DIR%-%d+")10690and response.body10691and response.body:find("hex_hmac_md5", 1, true)10692and response.body:lower():find("<title>d%-link systems[^<]+ login</title>")10693end,10694login_combos = {10695{username = "admin", password = ""}10696},10697login_check = function (host, port, path, user, pass)10698local get_lurl = function ()10699return url.absolute(path, "dws/api/Login?"10700.. math.floor(stdnse.clock_ms()))10701end10702local resp1 = http_get_simple(host, port, get_lurl())10703if not (resp1.status == 200 and resp1.body) then return false end10704local jstatus, jout = json.parse(resp1.body)10705if not (jstatus and jout.uid and jout.challenge) then return false end10706local auth = stdnse.tohex(openssl.hmac("MD5", pass, user .. jout.challenge))10707local resp2 = http_post_simple(host, port, get_lurl(),10708{cookies = "uid=" .. jout.uid},10709{id=user, password=auth})10710if not (resp2.status == 200 and resp2.body) then return false end10711jstatus, jout = json.parse(resp2.body)10712return jstatus and jout.status == "ok"10713end10714})1071510716table.insert(fingerprints, {10717name = "EMC VMAX vApp Manager",10718category = "storage",10719paths = {10720{path = "/"}10721},10722target_check = function (host, port, path, response)10723return response.status == 20010724and response.body10725and response.body:find("VMAX", 1, true)10726and response.body:lower():find("<title>[^<]+ vmax</title>")10727and get_refresh_url(response.body, "/SE/?$")10728end,10729login_combos = {10730{username = "smc", password = "smc"}10731},10732login_check = function (host, port, path, user, pass)10733local resp = http_post_simple(host, port, url.absolute(path, "SE/app"),10734nil, {user=user, passwd=pass})10735return resp.status == 20010736and get_cookie(resp, "JSESSIONID", ".")10737and (resp.body or ""):find("=%s*['\"]login=success&")10738end10739})1074010741---10742--Virtualization systems10743---10744table.insert(fingerprints, {10745name = "VMware ESXi",10746cpe = "cpe:/o:vmware:esxi",10747category = "virtualization",10748paths = {10749{path = "/"}10750},10751target_check = function (host, port, path, response)10752return response.status == 20010753and response.body10754and response.body:find("ID_EESX_Welcome", 1, true)10755and response.body:find("/folder?dcPath=ha-datacenter", 1, true)10756end,10757login_combos = {10758{username = "root", password = ""}10759},10760login_check = function (host, port, path, user, pass)10761return try_http_auth(host, port,10762url.absolute(path, "folder?dcPath=ha-datacenter"),10763user, pass, false)10764end10765})1076610767table.insert(fingerprints, {10768name = "VMware vCloud Connector",10769category = "virtualization",10770paths = {10771{path = "/"}10772},10773target_check = function (host, port, path, response)10774if not (response.status == 20010775and response.body10776and response.body:find("com.vmware.vami.", 1, true)10777and get_tag(response.body, "script", {src="^com%.vmware%.vami%.CoreWrapper%."})) then10778return false10779end10780local resp = http_get_simple(host, port,10781url.absolute(path, "service/core/view-deploy.xml"))10782return resp.status == 20010783and resp.body10784and resp.body:find("<name>Core</name>", 1, true)10785and get_tag(resp.body, "property", {value="^vCloud Connector Node$"})10786end,10787login_combos = {10788{username = "admin", password = "vmware"}10789},10790login_check = function (host, port, path, user, pass)10791local header = {Authorization="Basic " .. base64.enc(user .. ":" .. pass),10792CIMProtocolVersion="1.0",10793CIMOperation="MethodCall",10794CIMMethod=urlencode_all("CreateSessionToken"):upper(),10795CIMObject=urlencode_all("root/cimv2:VAMI_Authentication"):upper(),10796["Content-Type"]="application/xml; charset=UTF-8"}10797local msg = [[10798<?xml version="1.0" encoding="UTF-8"?>10799<CIM CIMVERSION="2.0" DTDVERSION="2.0">10800<MESSAGE ID="1" PROTOCOLVERSION="1.0">10801<SIMPLEREQ>10802<METHODCALL NAME="CreateSessionToken">10803<LOCALCLASSPATH>10804<LOCALNAMESPACEPATH>10805<NAMESPACE NAME="root"/>10806<NAMESPACE NAME="cimv2"/>10807</LOCALNAMESPACEPATH>10808<CLASSNAME NAME="VAMI_Authentication"/>10809</LOCALCLASSPATH>10810</METHODCALL>10811</SIMPLEREQ>10812</MESSAGE>10813</CIM>]]10814msg = msg:gsub("^%s+", ""):gsub("\n%s*", "")10815local resp = http_post_simple(host, port, url.absolute(path, "cimom"),10816{header=header}, msg)10817return resp.status == 20010818and (resp.body or ""):find("<PARAMVALUE%s+NAME%s*=%s*(['\"])Token%1")10819end10820})1082110822table.insert(fingerprints, {10823name = "PCoIP Zero Client",10824cpe = "cpe:/a:teradici:pcoip_host_software",10825category = "virtualization",10826paths = {10827{path = "/login.html"}10828},10829target_check = function (host, port, path, response)10830return response.status == 20010831and response.body10832and response.body:find("PCoIP® Zero Client", 1, true)10833and response.body:find("password_value", 1, true)10834end,10835login_combos = {10836{username = "", password = "Administrator"}10837},10838login_check = function (host, port, path, user, pass)10839local resp = http_post_simple(host, port, url.absolute(path, "cgi-bin/login"),10840nil, {password_value=pass, idle_timeout=60})10841return resp.status == 302 and get_cookie(resp, "session_id", "^%x+$")10842end10843})1084410845---10846--Remote consoles10847---10848table.insert(fingerprints, {10849name = "Lantronix SLB/SLC",10850category = "console",10851paths = {10852{path = "/"}10853},10854target_check = function (host, port, path, response)10855return response.status == 20010856and (response.header["server"] or ""):find("^mini_httpd/%d+%.")10857and response.body10858and response.body:find("lantronix", 1, true)10859and response.body:find("slcpassword", 1, true)10860end,10861login_combos = {10862{username = "sysadmin", password = "PASS"}10863},10864login_check = function (host, port, path, user, pass)10865local resp = http_post_simple(host, port, path, nil,10866{slclogin=user, slcpassword=pass})10867return resp.status == 20010868and resp.body10869and (resp.body:find("User already logged into web")10870or get_tag(resp.body, "frame", {name="^data$", src="^home%.htm$"}))10871end10872})1087310874table.insert(fingerprints, {10875name = "Avocent Explorer",10876category = "console",10877paths = {10878{path = "/login.php"}10879},10880target_check = function (host, port, path, response)10881return response.status == 20010882and response.body10883and response.body:find("Avocent", 1, true)10884and response.body:find("loginPassword", 1, true)10885and response.body:lower():find("<title>[^<]+ explorer</title>")10886end,10887login_combos = {10888{username = "Admin", password = ""}10889},10890login_check = function (host, port, path, user, pass)10891local form = {action="login",10892token="",10893loginUsername=user,10894loginPassword=pass,10895language="en"}10896local resp = http_post_simple(host, port, path, nil, form)10897return resp.status == 30210898and (resp.header["location"] or ""):find("/home%.php$")10899and get_cookie(resp, "avctSessionId", "^%d+$")10900end10901})1090210903table.insert(fingerprints, {10904name = "Bomgar Appliance",10905category = "console",10906paths = {10907{path = "/"}10908},10909target_check = function (host, port, path, response)10910if response.header["server"] ~= "Bomgar" then return false end10911local resp = http_get_simple(host, port,10912url.absolute(path, "appliance/"))10913return resp.status == 30210914and get_cookie(resp, "gw_s", "^%w+$")10915and (resp.header["location"] or ""):find("/appliance/login%.ns$")10916end,10917login_combos = {10918{username = "admin", password = "password"}10919},10920login_check = function (host, port, path, user, pass)10921local lurl = url.absolute(path, "appliance/login.ns")10922local resp1 = http_get_simple(host, port, lurl)10923if not (resp1.status == 200 and resp1.body) then return false end10924local formid = get_tag(resp1.body, "input", {type="^hidden$", name="^form_id$", value="^[%w+/]+=*$"})10925if not formid then return false end10926local form2 = {fake_password="",10927form_id=formid.value,10928["login[username]"]=user,10929["login[password]"]=pass,10930["login[submit]"]="Login",10931submit_button="Login"}10932local header = {["Referer"]=url.build(url_build_defaults(host, port, {path=lurl}))}10933local resp2 = http_post_simple(host, port, lurl,10934{cookies=resp1.cookies, header=header}, form2)10935return resp2.status == 20010936and get_tag(resp2.body or "", "input", {id="^new_password2$"})10937end10938})1093910940table.insert(fingerprints, {10941name = "Dell ERA",10942category = "console",10943paths = {10944{path = "/applet.html"}10945},10946target_check = function (host, port, path, response)10947return response.status == 20010948and response.header["server"] == "RMC Webserver 2.0"10949and response.body10950and response.body:find("DRSCAppletInterface.class", 1, true)10951end,10952login_combos = {10953{username = "root", password = "calvin"}10954},10955login_check = function (host, port, path, user, pass)10956local resp1 = http_get_simple(host, port, url.absolute(path, "cgi/challenge"))10957if resp1.status ~= 200 then return false end10958local url2 = ("cgi/login?user=%s&hash=%s"):format(user, pass)10959local resp2 = http_get_simple(host, port, url.absolute(path, url2),10960{cookies=resp1.cookies})10961return resp2.status == 20010962and (resp2.body or ""):find("<RMCLOGIN><RC>0x0</RC></RMCLOGIN>", 1, true)10963end10964})1096510966table.insert(fingerprints, {10967name = "Dell DRAC4",10968cpe = "cpe:/h:dell:remote_access_card",10969category = "console",10970paths = {10971{path = "/"}10972},10973target_check = function (host, port, path, response)10974return response.status == 20010975and response.header["server"] == "RMC Webserver 2.0"10976and response.body10977and response.body:find("DRAC 4", 1, true)10978and response.body:find("%Wvar%s+s_oemProductName%s*=%s*(['\"])DRAC 4%1")10979end,10980login_combos = {10981{username = "root", password = "calvin"}10982},10983login_check = function (host, port, path, user, pass)10984local resp = http_post_simple(host, port, url.absolute(path, "cgi/login"),10985nil, {user=user, hash=pass})10986return resp.status == 20010987and (resp.body or ""):find("%Wtop%.location%.replace%(%s*(['\"])[^'\"]-/cgi/main%1%s*%)")10988end10989})1099010991table.insert(fingerprints, {10992name = "Dell DRAC5",10993cpe = "cpe:/h:dell:remote_access_card",10994category = "console",10995paths = {10996{path = "/"}10997},10998target_check = function (host, port, path, response)10999return response.status == 20011000and response.body11001and response.body:find("%Wtop%.document%.location%.replace%(%s*(['\"])[^'\"]-/cgi%-bin/webcgi/index%1%s*%)")11002and response.body:lower():find("<title>remote access controller</title>", 1, true)11003end,11004login_combos = {11005{username = "root", password = "calvin"}11006},11007login_check = function (host, port, path, user, pass)11008local resp = http_post_simple(host, port,11009url.absolute(path, "cgi-bin/webcgi/login"),11010nil, {user=user, password=pass})11011return resp.status == 30211012and (resp.header["location"] or ""):find("/cgi%-bin/webcgi/main$")11013end11014})1101511016table.insert(fingerprints, {11017name = "Dell iDRAC6 (lighttpd)",11018cpe = "cpe:/o:dell:idrac6_firmware",11019category = "console",11020paths = {11021{path = "/"}11022},11023target_check = function (host, port, path, response)11024return response.status == 30211025and (response.header["server"] or ""):find("^lighttpd/%d+%.")11026and (response.header["location"] or ""):find("/Applications/dellUI/login%.htm$")11027end,11028login_combos = {11029{username = "root", password = "calvin"}11030},11031login_check = function (host, port, path, user, pass)11032local form = {WEBVAR_PASSWORD=pass,11033WEBVAR_USERNAME=user,11034WEBVAR_ISCMCLOGIN=0}11035local resp = http_post_simple(host, port,11036url.absolute(path, "Applications/dellUI/RPC/WEBSES/create.asp"),11037nil, form)11038return resp.status == 20011039and (resp.body or ""):match("'USERNAME'%s*:%s*'(.-)'") == user11040end11041})1104211043table.insert(fingerprints, {11044name = "Dell iDRAC6/7 (Mbedthis)",11045cpe = "cpe:/o:dell:idrac7_firmware",11046category = "console",11047paths = {11048{path = "/"}11049},11050target_check = function (host, port, path, response)11051local idrac6 = response.status == 30111052and (response.header["server"] or ""):find("^Mbedthis%-Appweb/%d+%.")11053local idrac7 = response.status == 30211054and response.header["server"] == "Embedthis-http"11055return (idrac6 or idrac7)11056and (response.header["location"] or ""):find("/start%.html$")11057end,11058login_combos = {11059{username = "root", password = "calvin"}11060},11061login_check = function (host, port, path, user, pass)11062local resp = http_post_simple(host, port, url.absolute(path, "data/login"),11063nil, {user=user, password=pass})11064return resp.status == 20011065and (resp.body or ""):find("<authResult>0</authResult>", 1, true)11066end11067})1106811069table.insert(fingerprints, {11070name = "HP 9000 iLO",11071cpe = "cpe:/h:hp:integrated_lights-out",11072category = "console",11073paths = {11074{path = "/"}11075},11076target_check = function (host, port, path, response)11077return response.status == 20011078and response.body11079and response.body:find("HP 9000", 1, true)11080and response.body:find("loginId", 1, true)11081and response.body:lower():find("<title>hp ilo login</title>", 1, true)11082end,11083login_combos = {11084{username = "Admin", password = "Admin"},11085{username = "Oper", password = "Oper"}11086},11087login_check = function (host, port, path, user, pass)11088local resp = http_post_simple(host, port, url.absolute(path, "signin.html"),11089nil, {loginId=user, password=pass})11090return resp.status == 20011091and get_refresh_url(resp.body or "", "/home%.html$")11092and get_cookie(resp, "MPID", "^%x+$")11093end11094})1109511096table.insert(fingerprints, {11097name = "IBM Integrated Management Module",11098cpe = "cpe:/o:ibm:integrated_management_module_firmware",11099category = "console",11100paths = {11101{path = "/"}11102},11103target_check = function (host, port, path, response)11104return response.status == 30111105and (response.header["location"] or ""):find("/designs/imm/index%.php$")11106end,11107login_combos = {11108{username = "USERID", password = "PASSW0RD"}11109},11110login_check = function (host, port, path, user, pass)11111local form = {user=user,11112password=pass,11113SessionTimeout=1200}11114local resp = http_post_simple(host, port, url.absolute(path, "data/login"),11115nil, form)11116if not (resp.status == 200 and resp.body) then return false end11117local jstatus, jout = json.parse(resp.body)11118return jstatus and jout.authResult == "0"11119end11120})1112111122table.insert(fingerprints, {11123name = "Supermicro IPMI",11124cpe = "cpe:/o:supermicro:intelligent_platform_management_firmware",11125category = "console",11126paths = {11127{path = "/"}11128},11129target_check = function (host, port, path, response)11130return response.status == 20011131and response.body11132and response.body:find("ATEN International", 1, true)11133and response.body:find("/cgi/login.cgi", 1, true)11134end,11135login_combos = {11136{username = "ADMIN", password = "ADMIN"}11137},11138login_check = function (host, port, path, user, pass)11139local resp = http_post_simple(host, port, url.absolute(path, "cgi/login.cgi"),11140nil, {name=user, pwd=pass})11141return resp.status == 20011142and (resp.body or ""):find("../cgi/url_redirect.cgi?url_name=mainmenu", 1, true)11143end11144})111451114611147