local comm = require "comm"
local nmap = require "nmap"
local math = require "math"
local irc = require "irc"
local stdnse = require "stdnse"
local rand = require "rand"
description = [[
Gathers information from an IRC server.
It uses STATS, LUSERS, and other queries to obtain this information.
]]
---
-- @output
-- 6665/tcp open irc
-- | irc-info:
-- | server: asimov.freenode.net
-- | version: ircd-seven-1.1.3(20111112-b71671d1e846,charybdis-3.4-dev). asimov.freenode.net
-- | servers: 31
-- | ops: 36
-- | chans: 48636
-- | users: 84883
-- | lservers: 1
-- | lusers: 4350
-- | uptime: 511 days, 23:02:29
-- | source host: source.example.com
-- |_ source ident: NONE or BLOCKED
--@xmloutput
-- <elem key="server">asimov.freenode.net</elem>
-- <elem key="version">ircd-seven-1.1.3(20111112-b71671d1e846,charybdis-3.4-dev). asimov.freenode.net </elem>
-- <elem key="servers">31</elem>
-- <elem key="ops">36</elem>
-- <elem key="chans">48636</elem>
-- <elem key="users">84883</elem>
-- <elem key="lservers">1</elem>
-- <elem key="lusers">4350</elem>
-- <elem key="uptime">511 days, 23:02:29</elem>
-- <elem key="source host">source.example.com</elem>
-- <elem key="source ident">NONE or BLOCKED</elem>
author = {"Doug Hoyte", "Patrick Donnelly"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
portrule = irc.portrule
local banner_timeout = 60
function action (host, port)
local nick = rand.random_alpha(9)
local output = stdnse.output_table()
local sd, line = comm.tryssl(host, port,
("USER nmap +iw nmap :Nmap Wuz Here\nNICK %s\n"):format(nick),
{request_timeout=6000})
if not sd then return "Unable to open connection" end
local buf = stdnse.make_buffer(sd, "\r?\n")
while line do
stdnse.debug2("%s", line)
-- This one lets us know we've connected, pre-PONGed, and got a NICK
-- Start of MOTD, we'll take the server name from here
local info = line:match "^:([%w-_.]+) 375"
if info then
output.server = info
sd:send("LUSERS\nVERSION\nSTATS u\nWHO " .. nick .. "\nQUIT\n")
end
-- MOTD could be missing, we want to handle that scenario as well
info = line:match "^:([%w-_.]+) 422"
if info then
output.server = info
sd:send("LUSERS\nVERSION\nSTATS u\nWHO " .. nick .. "\nQUIT\n")
end
-- NICK already in use
info = line:match "^:([%w-_.]+) 433"
if info then
nick = rand.random_alpha(9)
sd:send("NICK " .. nick .. "\n")
end
-- PING/PONG
local dummy = line:match "^PING :(.*)"
if dummy then
sd:send("PONG :" .. dummy .. "\n")
end
-- Server version info
info = line:match "^:[%w-_.]+ 351 %w+ ([^:]+)"
if info then
output.version = info
end
-- Various bits of info
local users, invisible, servers = line:match "^:[%w-_.]+ 251 %w+ :There are (%d+) users and (%d+) invisible on (%d+) servers"
if users then
output.users = math.tointeger(users + invisible)
output.servers = servers
end
local users, servers = line:match "^:[%w-_.]+ 251 %w+ :There are (%d+) users and %d+ services on (%d+) servers"
if users then
output.users = users
output.servers = servers
end
info = line:match "^:[%w-_.]+ 252 %w+ (%d+) :"
if info then
output.ops = info
end
info = line:match "^:[%w-_.]+ 254 %w+ (%d+) :"
if info then
output.chans = info
end
-- efnet
local clients, servers = line:match "^:[%w-_.]+ 255 %w+ :I have (%d+) clients and (%d+) server"
if clients then
output.lusers = clients
output.lservers = servers
end
-- ircnet
local clients, servers = line:match "^:[%w-_.]+ 255 %w+ :I have (%d+) users, %d+ services and (%d+) server"
if clients then
output.lusers = clients
output.lservers = servers
end
local uptime = line:match "^:[%w-_.]+ 242 %w+ :Server Up (%d+ days, [%d:]+)"
if uptime then
output.uptime = uptime
end
local ident, host = line:match "^:[%w-_.]+ 352 %w+ %S+ (%S+) ([%w-_.]+)"
if ident then
if ident:find "^~" then
output["source ident"] = "NONE or BLOCKED"
else
output["source ident"] = ident
end
output["source host"] = host
end
local err = line:match "^ERROR :(.*)"
if err then
output.error = err
end
line = buf()
end
if output.server then
return output
else
return nil
end
end
{"id": "NMAP:IRC-INFO.NSE", "bulletinFamily": "scanner", "title": "irc-info NSE Script", "description": "Gathers information from an IRC server. \n\nIt uses STATS, LUSERS, and other queries to obtain this information.\n\n## Example Usage \n \n \n nmap -sV -sC <target>\n\n## Script Output \n \n \n 6665/tcp open irc\n | irc-info:\n | server: asimov.freenode.net\n | version: ircd-seven-1.1.3(20111112-b71671d1e846,charybdis-3.4-dev). asimov.freenode.net\n | servers: 31\n | ops: 36\n | chans: 48636\n | users: 84883\n | lservers: 1\n | lusers: 4350\n | uptime: 511 days, 23:02:29\n | source host: source.example.com\n |_ source ident: NONE or BLOCKED\n\n## Requires \n\n * comm\n * nmap\n * math\n * irc\n * stdnse\n * rand\n\n* * *\n", "published": "2008-11-06T02:52:59", "modified": "2018-09-08T17:07:06", "cvss": {"score": 0.0, "vector": "NONE"}, "href": "https://nmap.org/nsedoc/scripts/irc-info.html", "reporter": "Doug Hoyte, Patrick Donnelly", "references": [], "cvelist": [], "type": "nmap", "lastseen": "2018-09-09T16:23:10", "edition": 5, "viewCount": 35, "enchantments": {"score": {"value": -0.5, "vector": "NONE", "modified": "2018-09-09T16:23:10", "rev": 2}, "dependencies": {"references": [], "modified": "2018-09-09T16:23:10", "rev": 2}, "vulnersScore": -0.5}, "sourceData": "local comm = require \"comm\"\nlocal nmap = require \"nmap\"\nlocal math = require \"math\"\nlocal irc = require \"irc\"\nlocal stdnse = require \"stdnse\"\nlocal rand = require \"rand\"\n\ndescription = [[\nGathers information from an IRC server.\n\nIt uses STATS, LUSERS, and other queries to obtain this information.\n]]\n\n---\n-- @output\n-- 6665/tcp open irc\n-- | irc-info:\n-- | server: asimov.freenode.net\n-- | version: ircd-seven-1.1.3(20111112-b71671d1e846,charybdis-3.4-dev). asimov.freenode.net\n-- | servers: 31\n-- | ops: 36\n-- | chans: 48636\n-- | users: 84883\n-- | lservers: 1\n-- | lusers: 4350\n-- | uptime: 511 days, 23:02:29\n-- | source host: source.example.com\n-- |_ source ident: NONE or BLOCKED\n--@xmloutput\n-- <elem key=\"server\">asimov.freenode.net</elem>\n-- <elem key=\"version\">ircd-seven-1.1.3(20111112-b71671d1e846,charybdis-3.4-dev). asimov.freenode.net </elem>\n-- <elem key=\"servers\">31</elem>\n-- <elem key=\"ops\">36</elem>\n-- <elem key=\"chans\">48636</elem>\n-- <elem key=\"users\">84883</elem>\n-- <elem key=\"lservers\">1</elem>\n-- <elem key=\"lusers\">4350</elem>\n-- <elem key=\"uptime\">511 days, 23:02:29</elem>\n-- <elem key=\"source host\">source.example.com</elem>\n-- <elem key=\"source ident\">NONE or BLOCKED</elem>\n\nauthor = {\"Doug Hoyte\", \"Patrick Donnelly\"}\n\nlicense = \"Same as Nmap--See https://nmap.org/book/man-legal.html\"\n\ncategories = {\"default\", \"discovery\", \"safe\"}\n\nportrule = irc.portrule\n\nlocal banner_timeout = 60\n\nfunction action (host, port)\n local nick = rand.random_alpha(9)\n\n local output = stdnse.output_table()\n\n local sd, line = comm.tryssl(host, port,\n (\"USER nmap +iw nmap :Nmap Wuz Here\\nNICK %s\\n\"):format(nick),\n {request_timeout=6000})\n if not sd then return \"Unable to open connection\" end\n\n local buf = stdnse.make_buffer(sd, \"\\r?\\n\")\n\n while line do\n stdnse.debug2(\"%s\", line)\n\n -- This one lets us know we've connected, pre-PONGed, and got a NICK\n -- Start of MOTD, we'll take the server name from here\n local info = line:match \"^:([%w-_.]+) 375\"\n if info then\n output.server = info\n sd:send(\"LUSERS\\nVERSION\\nSTATS u\\nWHO \" .. nick .. \"\\nQUIT\\n\")\n end\n\n -- MOTD could be missing, we want to handle that scenario as well\n info = line:match \"^:([%w-_.]+) 422\"\n if info then\n output.server = info\n sd:send(\"LUSERS\\nVERSION\\nSTATS u\\nWHO \" .. nick .. \"\\nQUIT\\n\")\n end\n\n -- NICK already in use\n info = line:match \"^:([%w-_.]+) 433\"\n if info then\n nick = rand.random_alpha(9)\n sd:send(\"NICK \" .. nick .. \"\\n\")\n end\n\n -- PING/PONG\n local dummy = line:match \"^PING :(.*)\"\n if dummy then\n sd:send(\"PONG :\" .. dummy .. \"\\n\")\n end\n\n -- Server version info\n info = line:match \"^:[%w-_.]+ 351 %w+ ([^:]+)\"\n if info then\n output.version = info\n end\n\n -- Various bits of info\n local users, invisible, servers = line:match \"^:[%w-_.]+ 251 %w+ :There are (%d+) users and (%d+) invisible on (%d+) servers\"\n if users then\n output.users = math.tointeger(users + invisible)\n output.servers = servers\n end\n\n local users, servers = line:match \"^:[%w-_.]+ 251 %w+ :There are (%d+) users and %d+ services on (%d+) servers\"\n if users then\n output.users = users\n output.servers = servers\n end\n\n info = line:match \"^:[%w-_.]+ 252 %w+ (%d+) :\"\n if info then\n output.ops = info\n end\n\n info = line:match \"^:[%w-_.]+ 254 %w+ (%d+) :\"\n if info then\n output.chans = info\n end\n\n -- efnet\n local clients, servers = line:match \"^:[%w-_.]+ 255 %w+ :I have (%d+) clients and (%d+) server\"\n if clients then\n output.lusers = clients\n output.lservers = servers\n end\n\n -- ircnet\n local clients, servers = line:match \"^:[%w-_.]+ 255 %w+ :I have (%d+) users, %d+ services and (%d+) server\"\n if clients then\n output.lusers = clients\n output.lservers = servers\n end\n\n local uptime = line:match \"^:[%w-_.]+ 242 %w+ :Server Up (%d+ days, [%d:]+)\"\n if uptime then\n output.uptime = uptime\n end\n\n local ident, host = line:match \"^:[%w-_.]+ 352 %w+ %S+ (%S+) ([%w-_.]+)\"\n if ident then\n if ident:find \"^~\" then\n output[\"source ident\"] = \"NONE or BLOCKED\"\n else\n output[\"source ident\"] = ident\n end\n output[\"source host\"] = host\n end\n\n local err = line:match \"^ERROR :(.*)\"\n if err then\n output.error = err\n end\n\n line = buf()\n end\n\n if output.server then\n return output\n else\n return nil\n end\nend\n", "nmap": {"categories": ["discovery", "safe", "default"], "scriptType": "portrule"}}