-
Notifications
You must be signed in to change notification settings - Fork 45
/
freevulnsearch.nse
378 lines (321 loc) · 10.8 KB
/
freevulnsearch.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
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
-- Head
-- Required NSE libraries
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local http = require "http"
local json = require "json"
-- Input Arguments
local apipath = stdnse.get_script_args("freevulnsearch.apipath")
local notls = stdnse.get_script_args("freevulnsearch.notls")
local summary = stdnse.get_script_args("freevulnsearch.summary")
local xmlhtml = stdnse.get_script_args("freevulnsearch.xmlhtml")
description = [[
This script [Version 1.1.8] allows you to automatically search for CVEs using the API of
https://www.circl.lu/services/cve-search/ in connection with the found CPEs
using the parameter -sV in NMAP.
This script is part of the FreeOCSAF Project - https://freecybersecurity.org.
Use only with legal authorization and at your own risk! ANY LIABILITY WILL BE REJECTED!
Thanks to cve-search.org and circl.lu for the ingenious api
and special thanks to the community for many useful ideas that speed up my coding!
Realized functions:
Version 1.0 - Contains the basic functions to quickly find relevant CVEs.
Version 1.0.1 - Includes EDB and MSF in output and minor changes.
Version 1.0.2 - Special CPE formatting and output optimization.
Version 1.0.3 - Small adjustments
Version 1.1 - Support your own cve-search api-link - https://<IP>/api/cvefor/
Version 1.1.1 - Adaptation to CVSS rating instead of OSSTMM - Input from the community, thanks
Version 1.1.2 - Special CPE formatting - Many thanks to Tore (cr33y) for testing.
Version 1.1.3b - Special CPE formatting - Many thanks to Tore (cr33y) for testing.
Version 1.1.4 - Optimization for OCSAF freevulnaudit.sh project.
Version 1.1.5 - Assignment to external category only
Version 1.1.6 - Adaptation API to http and tls as option
Version 1.1.6a - Adaptation API to tls and http as option
Version 1.1.7 - Optimized for nmap 7.80
Version 1.1.8 - Optimized for cve-search api
Future functions:
Version 1.2 - Shall contains optional sort by severity (CVSS)
Version 1.3 - Implementation of your useful ideas.
Usage:
nmap -sV --script freevulnsearch <target>
Output explanation:
CVE-Number Rating CVSS EDB MSF CVE-Link
CVE-Number:
Common Vulnerabilities and Exposures
CVSS v3.0 Ratings:
Critical (CVSS 9.0 - 10.0)
High (CVSS 7.0 - 8.9)
Medium (CVSS 4.0 - 6.9)
Low (CVSS 0.1 - 3.9)
None (CVSS 0.0)
CVSS:
Common Vulnerability Scoring System with with the level of severty from 0.0 - 10.0
EDB:
There is an exploit in the Exploit-DB.com
MSF:
There is a module in the Metasploit Framework
CVE-Link:
Additional information on the vulnerability found.
]]
author = "Mathias Gut"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"safe", "vuln", "external"}
-- @usage
-- nmap -sV --script freevulnsearch [--script-args apipath=<url>] <target>
-- nmap -sV --script freevulnsearch [--script-args notls=yes] <target>
-- nmap -sV --script freevulnsearch [--script-args summary=yes] <target>
-- nmap -sV --script freevulnsearch [--script-args xmlhmtl=yes] <target>
--
-- @output
--
-- 22/tcp open ssh OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
-- | freevulnsearch:
-- | CVE-2018-15473 Medium 5.0 EDB MSF https://cve.circl.lu/cve/CVE-2018-15473
-- | CVE-2017-15906 Medium 5.0 https://cve.circl.lu/cve/CVE-2017-15906
-- | CVE-2016-10708 Medium 5.0 https://cve.circl.lu/cve/CVE-2016-10708
-- | CVE-2010-4755 Medium 4.0 https://cve.circl.lu/cve/CVE-2010-4755
-- | CVE-2010-4478 High 7.5 https://cve.circl.lu/cve/CVE-2010-4478
-- | CVE-2008-5161 Low 2.6 https://cve.circl.lu/cve/CVE-2008-5161
-- |_ *CVE found with NMAP-CPE: (cpe:/a:openbsd:openssh:4.7p1)
--
-- Portrule
-- The table port.version contains the CPEs
portrule = function(host, port)
local portv=port.version
return portv ~= nil and portv.version ~= nil
end
-- Function to check if a version number exists at the CPE
function func_check_cpe(cpe)
_, count = string.gsub(cpe, ":", " ")
if count >= 4 then
return cpe
else
return 0
end
end
-- Function to check for special CPE formatting.
function func_check_cpe_form(cpe)
local cpe_form
local sub_form1
local sub_form2
local sub_form3
local cpe_front
local cpe_version
_, count1 = string.gsub(cpe, ":httpfileserver:", " ")
_, count2 = string.gsub(cpe, ".*:.*:.*:.*:.*-", " ")
_, count3 = string.gsub(cpe, ".*:.*:.*:.*:.*_", " ")
_, count4 = string.gsub(cpe, ".*:.*:.*:.*:.*%..*%.%d%a%d", " ")
_, count5 = string.gsub(cpe, ".*:.*:.*:.*:.*%a%d", " ")
_, count6 = string.gsub(cpe, ".*:.*:.*:.*:.*%d%a", " ")
if count1 ~= 0 then
cpe_form = string.gsub(cpe,"httpfileserver","http_file_server")
return cpe_form
elseif count2 ~= 0 then -- (MySQL) 5.0.51a-3ubuntu5 -to- 5.0.51a
sub_form1 = string.gsub(cpe,".*:",":")
cpe_version = string.gsub(sub_form1,"-.*","")
cpe_front = string.gsub(cpe,cpe_version .. ".*","")
cpe_form = cpe_front .. cpe_version
return cpe_form
elseif count3 ~= 0 then -- (Exim smtpd) 4.90_1 -to- 4.90
sub_form1 = string.gsub(cpe,".*:",":")
cpe_version = string.gsub(sub_form1,"_.*","")
cpe_front = string.gsub(cpe,cpe_version .. ".*","")
cpe_form = cpe_front .. cpe_version
return cpe_form
elseif count4 ~= 0 then -- (OpenSSH) 6.6.1p1 -to- 6.6:p1
sub_form1 = string.gsub(cpe,".*:",":")
sub_form2 = string.gsub(sub_form1,"%.%d%a%d.*","")
sub_form3 = string.gsub(sub_form1,".*%.%d","")
cpe_version = sub_form2 .. ":" .. sub_form3
cpe_front = string.gsub(cpe,sub_form1,"")
cpe_form = cpe_front .. cpe_version
return cpe_form
elseif count5 ~= 0 then -- (OpenSSH) 7.5p1 -to- 7.5:p1
sub_form1 = string.gsub(cpe,".*:",":")
sub_form2 = string.gsub(sub_form1,"%a.*","")
sub_form3 = string.gsub(sub_form1,sub_form2,"")
cpe_version = sub_form2 .. ":" .. sub_form3
cpe_front = string.gsub(cpe,sub_form1,"")
cpe_form = cpe_front .. cpe_version
return cpe_form
elseif count6 ~= 0 then -- (ProFTPD) 1.3.5a -to- 1.3.5
sub_form1 = string.gsub(cpe,".*:",":")
sub_form2 = string.gsub(sub_form1,"%d.*","")
cpe_version = string.gsub(sub_form1,sub_form2,"")
cpe_front = string.gsub(cpe,sub_form1,"")
cpe_form = cpe_front .. cpe_version
return cpe_form
else
return 0
end
end
-- Function to check for known vulnerabilities without CVE
function func_check_known_vuln(cpe)
local cpe_vuln
if cpe == "cpe:/a:vsftpd:vsftpd:2.3.4" then
cpe_vuln = "EDB-ID-17491\t" .. "Critical\t" .. "None\t" .. "EDB MSF\t" .. "https://www.exploit-db.com/exploits/17491"
return cpe_vuln
else
return 0
end
end
-- Function to query CVEs via CPEs with API (circl.lu).
function func_check_cve(cpe)
local url
local option = {
max_body_size=40000000,
timeout=40000
}
local response
local request
local status
local vulnerabilities
if not apipath then
if not notls then
url = "https://cve.circl.lu/api/cvefor/"
else
url = "http://cve.circl.lu/api/cvefor/"
end
else
url = apipath
end
request = url .. cpe
response = http.get_url(request, option)
status, vulnerabilities = json.parse(response.body)
if status ~= true then
return 1
elseif type(next(vulnerabilities)) == "nil" then
return 2
elseif (status == true and vulnerabilities ~= "") then
return func_output(vulnerabilities)
else
return 2
end
end
-- Function to generate the script output.
function func_output(vulnerabilities)
local output_table = {}
local input_table = {}
local cve_url= "https://cve.circl.lu/cve/"
local cve_value
local cvss
local cvss_value
local cvss_rating
local url_value
local edb
local msf
local exploit
local sum
local cwe
local xmlhtml_out
local i
local t
if not xmlhtml then
xmlhtml_out = ""
else
xmlhtml_out = " "
end
for i,t in ipairs(vulnerabilities) do
cve_value = t.id
cvss = tonumber(t.cvss)
url_value = cve_url .. t.id
if t.refmap then
edb = t.refmap["exploit-db"]
msf = t.refmap.metasploit
end
if not cvss then
cvss_value = "None"
cvss_rating = "None"
else
cvss_value = cvss
cvss_rating = func_rating(cvss)
end
if not edb and not msf then
exploit = ""
elseif edb and not msf then
exploit = "EDB"
elseif not edb and msf then
exploit = "MSF"
elseif edb and msf then
exploit = "EDB MSF"
end
if not summary then
output_table = cve_value .. xmlhtml_out .. "\t" .. cvss_rating .. "\t" .. cvss_value .. "\t" .. exploit .. "\t" .. url_value
else
sum = t.summary
if not t.cwe then
output_table = cve_value .. xmlhtml_out .. "\t" .. cvss_rating .. "\t" .. cvss_value .. "\t" .. exploit .. "\t" .. url_value ..
"\n *SUMMARY: " .. sum .. "\n"
else
cwe = t.cwe
output_table = cve_value .. xmlhtml_out .. "\t" .. cvss_rating .. "\t" .. cvss_value .. "\t" .. exploit .. "\t" .. url_value ..
"\n *CWE: " .. cwe ..
"\n *SUMMARY: " .. sum .. "\n"
end
end
input_table[i] = output_table
end
return input_table
end
-- Function to assign CVSS values to CVSS V3.0 ratings
function func_rating(cvss)
if (cvss == 0.0) then
return "None\t"
elseif (3.9 >= cvss and cvss >= 0.1) then
return "Low\t"
elseif (6.9 >= cvss and cvss >= 4.0) then
return "Medium\t"
elseif (8.9 >= cvss and cvss >= 7.0) then
return "High\t"
elseif (10.0 >= cvss and cvss >= 9.0) then
return "Critical"
end
end
-- Action
-- Main-Function
action = function(host, port)
local cpe=""
local check
local sort_values
local form_cpe
local known_vuln
local i
for i, cpe in ipairs(port.version.cpe) do
check = func_check_cpe(cpe)
if check ~= 0 then
sort_values = func_check_cve(check)
if sort_values == 1 then
return "*Error with API query. API or network possibly not available."
elseif sort_values == 2 then
form_cpe = func_check_cpe_form(check)
if form_cpe == 0 then
known_vuln = func_check_known_vuln(check)
if known_vuln == 0 then
return "\n *No CVE found with NMAP-CPE: (" .. check .. ")" ..
"\n *Check other sources like https://www.exploit-db.com"
else
return "\n " .. known_vuln .. "\n *No CVE found with CPE: (" .. check .. ")"
end
else
sort_values = func_check_cve(form_cpe)
if sort_values == 2 then
return "\n *No CVE found with NMAP-CPE: (" .. check .. ")" ..
"\n *No CVE found with freevulnsearch function: (" .. form_cpe .. ")" ..
"\n *Check other sources like https://www.exploit-db.com"
else
table.sort(sort_values, function(a, b) return a>b end)
table.insert(sort_values, "*No CVE found with NMAP-CPE: (" ..check .. ")")
table.insert(sort_values, "*CVE found with freevulnsearch function: (" .. form_cpe .. ")")
return sort_values
end
end
else
table.sort(sort_values, function(a, b) return a>b end)
table.insert(sort_values, "*CVE found with NMAP-CPE: (" ..check .. ")")
return sort_values
end
elseif check == 0 then
return "\n *Check unspecific version manually: (".. cpe .. ")"
end
end
end