-
Notifications
You must be signed in to change notification settings - Fork 16
/
erldp-info.nse
139 lines (115 loc) · 3.38 KB
/
erldp-info.nse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local bin = require "bin"
local match = require "match"
-- @usage
-- nmap -sT -p <port> <ip> --script erldp-info -sV
--
-- @output
-- PORT STATE SERVICE
-- 25672/tcp open erldp
-- | erldp-info:
-- | version: 6e00
-- | node: rabbit@iron
-- |_ flags: 500037f
--
-- Erlang daemons - couchdb, ejabberd and rabbitmq are the most common -
-- may expose a sensitive asset called Erlang distribution protocol.
-- This script actively scans for Erlang distribution protocol.
-- The portrule below asks to scan for every open TCP port.
--
-- Note that epmd-info.nse may already provide information regarding
-- named Erlang nodes.
--
-- Running the same command as above plus --script epmd-info gives:
-- PORT STATE SERVICE
-- 4369/tcp open epmd
-- | epmd-info:
-- | epmd_port: 4369
-- | nodes:
-- |_ rabbit: 25672
-- 5672/tcp open amqp
-- 25672/tcp open erldp
-- | erldp-info:
-- | version: 6e00
-- | node: rabbit@iron
-- |_ flags: 500037f
--
-- However, some security guidelines recommend to disallow access to 4369
-- while Erlang nodes might still be accessible.
--
description = [[
Identifies Erlang distribution, which provides remoting for Erlang based servers.
]]
author = "Guillaume Teissier <gteissier@gmx.com>"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"default", "safe", "discovery", "version"}
portrule = function(host, port)
return port.protocol == "tcp" and port.state == "open"
end
local random = math.random
local function uuid()
local template ='xxxxxxxx@devnull'
return string.gsub(template, '[x]', function (c)
local v = random(0, 0xf)
return string.format('%x', v)
end)
end
local function decode(conn)
local status, data
status, data = conn:receive_buf(match.numbytes(2), true)
if not status then
return
end
length = select(2, bin.unpack(">S", data))
status, data = conn:receive_buf(match.numbytes(length), true)
if not status then
return
end
return data
end
local function decode_recv_challenge(data)
local version, flags, challenge, offset
offset, cmd, version, flags, challenge = bin.unpack(">CSII", data)
return version, flags, challenge, data:sub(offset)
end
action = function(host, port)
local client = nmap.new_socket()
local status
local data
local send_name
local local_name = uuid()
local output = stdnse.output_table()
status, data = client:connect(host, port)
if not status then
client:close()
return
end
send_name = bin.pack('>SCSIA', 7+string.len(local_name), 110, 5, 0x7499c, local_name)
if not client:send(send_name) then
client:close()
return
end
data = decode(client)
if not data or data:sub(1, 1) ~= "s" or data:sub(2, 3) ~= "ok" then
client:close()
return
end
data = decode(client)
if not data or data:sub(1, 1) ~= "n" then
client:close()
return
end
local version, flags, challenge, peer_name = decode_recv_challenge(data)
output["version"] = stdnse.tohex(version)
output["node"] = peer_name
output["flags"] = stdnse.tohex(flags)
port.version.product = "Erlang distribution protocol"
port.version.name = "erldp"
nmap.set_port_state(host, port, "open")
nmap.set_port_version(host, port, "hardmatched")
return output
end