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
|
---
-- This library was written to ease interaction with OpenVAS Manager servers
-- using OMP (OpenVAS Management Protocol) version 2.
--
-- A very small subset of the protocol is implemented.
-- * Connection/authentication
-- * Targets enumeration
--
-- The library can also store accounts in the registry to share them between
-- scripts.
--
-- The complete protocol documentation is available on the official OpenVAS
-- website: http://www.openvas.org/omp-2-0.html
--
-- Sample use:
-- <code>
-- local session = omp2.Session:new()
-- local status, err = session:connect(host, port)
-- local status, err = session:authenticate(username, password)
-- ...
-- session:close()
-- </code>
--
-- @author Henri Doreau
-- @copyright Same as Nmap -- See https://nmap.org/book/man-legal.html
--
-- @args omp2.username The username to use for authentication.
-- @args omp2.password The password to use for authentication.
--
local nmap = require "nmap"
local stdnse = require "stdnse"
local table = require "table"
_ENV = stdnse.module("omp2", stdnse.seeall)
local HAVE_SSL = false
if pcall(require,'openssl') then
HAVE_SSL = true
end
--- A Session class holds connection and interaction with the server
Session = {
--- Creates a new session object
new = function(self, socket)
local o = {}
setmetatable(o, self)
self.__index = self
o.username = nmap.registry.args["omp2.username"]
o.password = nmap.registry.args["omp2.password"]
o.socket = socket or nmap.new_socket()
return o
end,
--- Establishes the (SSL) connection to the remote server
connect = function(self, host, port)
if not HAVE_SSL then
return false, "The OMP2 module requires OpenSSL support"
end
return self.socket:connect(host, port, "ssl")
end,
--- Closes connection
close = function(self)
return self.socket:close()
end,
--- Attempts to authenticate on the current connection
authenticate = function(self, username, password)
local status, err, xmldata
-- TODO escape credentials
status, err = self.socket:send("<authenticate><credentials>"
.. "<username>" .. username .. "</username>"
.. "<password>" .. password .. "</password>"
.. "</credentials></authenticate>")
if not status then
stdnse.debug1("ERROR: %s", err)
return false, err
end
status, xmldata = self.socket:receive()
if not status then
stdnse.debug1("ERROR: %s", xmldata)
return false, xmldata
end
return xmldata:match('status="200"')
end,
--- Lists targets defined on the remote server
ls_targets = function(self)
local status, err, xmldata
local res, target_names, target_hosts = {}, {}, {}
status, err = self.socket:send("<get_targets/>")
if not status then
stdnse.debug1("ERROR: %s", err)
return false, err
end
status, xmldata = self.socket:receive()
if not status then
stdnse.debug1("ERROR: %s", xmldata)
return false, xmldata
end
-- As NSE has no XML parser yet, we use regexp to extract the data from the
-- XML output. Targets are defined as a name and the corresponding host(s).
-- Thus we gather both and return an associative array, using names as keys
-- and hosts as values.
local i = 0
for name in xmldata:gmatch("<name>(.-)</name>") do
-- XXX this is hackish: skip the second and third "<name>" tags, as they
-- describe other components than the targets.
-- see: http://www.openvas.org/omp-2-0.html#command_get_targets
if i % 3 == 0 then
table.insert(target_names, name)
end
i = i + 1
end
for hosts in xmldata:gmatch("<hosts>(.-)</hosts>") do
table.insert(target_hosts, hosts)
end
for i, _ in ipairs(target_names) do
res[target_names[i]] = target_hosts[i]
end
return res
end,
}
--- Registers OMP2 credentials for a given host
function add_account(host, username, password)
if not nmap.registry[host.ip] then
nmap.registry[host.ip] = {}
end
if not nmap.registry[host.ip]["omp2accounts"] then
nmap.registry[host.ip]["omp2accounts"] = {}
end
table.insert(nmap.registry[host.ip]["omp2accounts"], {["username"] = username, ["password"] = password})
end
--- Retrieves the list of accounts for a given host
function get_accounts(host)
local accounts = {}
local username, password
username = nmap.registry.args["omp2.username"]
password = nmap.registry.args["omp2.password"]
if username and password then
table.insert(accounts, {["username"] = username, ["password"] = password})
end
if nmap.registry[host.ip] and nmap.registry[host.ip]["omp2accounts"] then
for _, account in pairs(nmap.registry[host.ip]["omp2accounts"]) do
table.insert(accounts, account)
end
end
if #accounts > 0 then
return accounts
end
return nil
end
return _ENV;
|