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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
local ipOps = require "ipOps"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
local tab = require "tab"
local table = require "table"
description=[[
Discovers hosts and routing information from devices running RIPv2 on the
LAN. It does so by sending a RIPv2 Request command and collects the responses
from all devices responding to the request.
]]
---
-- @usage
-- nmap --script broadcast-rip-discover
--
-- @output
-- Pre-scan script results:
-- | broadcast-rip-discover:
-- | Discovered RIPv2 devices
-- | 10.0.200.107
-- | ip netmask nexthop metric
-- | 10.46.100.0 255.255.255.0 0.0.0.0 1
-- | 10.46.110.0 255.255.255.0 0.0.0.0 1
-- | 10.46.120.0 255.255.255.0 0.0.0.0 1
-- | 10.46.123.0 255.255.255.0 10.0.200.123 1
-- | 10.46.124.0 255.255.255.0 10.0.200.124 1
-- | 10.46.125.0 255.255.255.0 10.0.200.125 1
-- | 10.0.200.101
-- | ip netmask nexthop metric
-- |_ 0.0.0.0 0.0.0.0 10.0.200.1 1
--
-- @args broadcast-rip-discover.timeout timespec defining how long to wait for
-- a response. (default 5s)
--
-- Version 0.1
-- Created 29/10/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
--
author = "Patrik Karlsson"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"broadcast", "safe"}
prerule = function() return not( nmap.address_family() == "inet6") end
RIPv2 = {
Command = {
Request = 1,
Response = 2,
},
AddressFamily = {
IP = 2,
},
-- The Request class contains functions to build a RIPv2 Request
Request = {
-- Creates a new Request instance
--
-- @param command number containing the RIPv2 Command to use
-- @return o instance of request
new = function(self, command)
local o = {
version = 2,
command = command,
domain = 0,
family = 0,
tag = 0,
address = 0,
subnet = 0,
nexthop = 0,
metric = 16
}
setmetatable(o, self)
self.__index = self
return o
end,
-- Converts the whole request to a string
__tostring = function(self)
assert(self.command, "No command was supplied")
assert(self.metric, "No metric was supplied")
assert(self.address, "No address was supplied")
local RESERVED = 0
-- RIPv2 stuff, should be 0 for RIPv1
local tag, subnet, nexthop = 0, 0, 0
local data = string.pack(">BB I2 I2 I2 I4 I4 I4 I4",
self.command, self.version, self.domain, self.family, self.tag,
self.address, self.subnet, self.nexthop, self.metric)
return data
end,
},
-- The Response class contains code needed to parse a RIPv2 response
Response = {
-- Creates a new Response instance based on raw socket data
--
-- @param data string containing the raw socket response
-- @return o Response instance
new = function(self, data)
local o = { data = data }
if ( not(data) or #data < 3 ) then
return
end
local pos, _
o.command, o.version, _, pos = string.unpack(">BBI2", data)
if ( o.command ~= RIPv2.Command.Response or o.version ~= 2 ) then
return
end
local routes = tab.new(2)
tab.addrow(routes, "ip", "netmask", "nexthop", "metric")
while( #data - pos >= 20 ) do
local family, address, metric, netmask, nexthop
family, _, address, netmask, nexthop,
metric, pos = string.unpack(">I2 I2 I4 I4 I4 I4", data, pos)
if ( family == RIPv2.AddressFamily.IP ) then
local ip = ipOps.fromdword(address)
netmask = ipOps.fromdword(netmask)
nexthop = ipOps.fromdword(nexthop)
tab.addrow(routes, ip, netmask, nexthop, metric)
end
end
if ( #routes > 1 ) then o.routes = routes end
setmetatable(o, self)
self.__index = self
return o
end,
}
}
action = function()
local timeout = stdnse.parse_timespec(stdnse.get_script_args('broadcast-rip-discover.timeout'))
timeout = (timeout or 5) * 1000
local socket = nmap.new_socket("udp")
socket:set_timeout(timeout)
local rip = RIPv2.Request:new(RIPv2.Command.Request)
local status, err = socket:sendto("224.0.0.9",
{ number = 520, protocol = "udp" },
tostring(rip))
local result = {}
repeat
local data
status, data = socket:receive()
if ( status ) then
local status, _, _, rhost, _ = socket:get_info()
local response = RIPv2.Response:new(data)
table.insert(result, rhost)
if ( response and response.routes and #response.routes > 0 ) then
--response.routes.name = "Routes"
table.insert(result, { tab.dump(response.routes) } )
end
end
until( not(status) )
if ( #result > 0 ) then
result.name = "Discovered RIPv2 devices"
end
return stdnse.format_output(true, result)
end
|