Skip to content

Commit 51cbecc

Browse files
Some Nessus related tools.
1 parent 568d1aa commit 51cbecc

File tree

2 files changed

+295
-0
lines changed

2 files changed

+295
-0
lines changed

Diff for: scan/exploitable.go

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
Copyright (c) 2017, AverageSecurityGuy
3+
# All rights reserved.
4+
5+
Created: 2018-11-08
6+
Modified: 2018-11-08
7+
Author: Stephen Haywood
8+
Sources: http://blog.davidsingleton.org/parsing-huge-xml-files-with-go/
9+
*/
10+
11+
package main
12+
13+
import (
14+
"encoding/xml"
15+
"fmt"
16+
"os"
17+
"strings"
18+
)
19+
20+
type Tag struct {
21+
Name string `xml:"name,attr"`
22+
Value string `xml:",chardata"`
23+
}
24+
25+
type Host struct {
26+
ip string
27+
fqdn string
28+
os string
29+
Properties []Tag `xml:"tag"`
30+
}
31+
32+
func (h *Host) Parse() {
33+
for _, hp := range h.Properties {
34+
switch hp.Name {
35+
case "host-ip":
36+
h.ip = hp.Value
37+
case "operating-system":
38+
h.os = hp.Value
39+
case "os":
40+
if h.os == "" {
41+
h.os = hp.Value
42+
}
43+
case "host-fqdn":
44+
h.fqdn = hp.Value
45+
default:
46+
continue
47+
}
48+
}
49+
}
50+
51+
type HostItem struct {
52+
host Host
53+
Port string `xml:"port,attr"`
54+
Protocol string `xml:"protocol,attr"`
55+
PluginId string `xml:"pluginID,attr"`
56+
Metasploit bool `xml:"exploit_framework_metasploit"`
57+
Module string `xml:"metasploit_name"`
58+
}
59+
60+
func (h *HostItem) String() string {
61+
return fmt.Sprintf("%s\t%s\t%s\t%s", h.host.ip, h.Port, h.host.fqdn, h.host.os)
62+
}
63+
64+
func check(e error) {
65+
if e != nil {
66+
fmt.Printf("Error: %s\n", e.Error())
67+
os.Exit(0)
68+
}
69+
}
70+
71+
func parseFile(fn string, hic chan<- *HostItem) {
72+
reader, err := os.Open(fn)
73+
check(err)
74+
75+
decoder := xml.NewDecoder(reader)
76+
77+
var host Host
78+
79+
for {
80+
tkn, err := decoder.Token()
81+
if tkn == nil {
82+
break
83+
}
84+
85+
if err != nil {
86+
fmt.Printf("Parse Error: %s", err)
87+
continue
88+
}
89+
90+
switch ele := tkn.(type) {
91+
case xml.StartElement:
92+
switch ele.Name.Local {
93+
case "HostProperties":
94+
decoder.DecodeElement(&host, &ele)
95+
host.Parse()
96+
case "ReportItem":
97+
var item HostItem
98+
99+
item.host = host
100+
decoder.DecodeElement(&item, &ele)
101+
hic <- &item
102+
default:
103+
continue
104+
}
105+
default:
106+
continue
107+
}
108+
}
109+
110+
close(hic)
111+
}
112+
113+
func processExploitable(hi *HostItem, exp map[string][]string) {
114+
if hi.Metasploit {
115+
_, ok := exp[hi.Module]
116+
if !ok {
117+
exp[hi.Module] = []string{hi.String()}
118+
} else {
119+
exp[hi.Module] = append(exp[hi.Module], hi.String())
120+
}
121+
}
122+
}
123+
124+
func main() {
125+
if len(os.Args) != 2 {
126+
fmt.Println("Usage: go run exploitable.go nessus_file")
127+
os.Exit(1)
128+
}
129+
130+
exploitable := make(map[string] []string)
131+
hostItemChan := make(chan *HostItem, 100)
132+
133+
go parseFile(os.Args[1], hostItemChan)
134+
135+
for hi := range hostItemChan {
136+
processExploitable(hi, exploitable)
137+
}
138+
139+
for e := range exploitable {
140+
fmt.Println(e)
141+
fmt.Println(strings.Join(exploitable[e], "\n"))
142+
fmt.Println("")
143+
}
144+
}

Diff for: scan/plugin.py

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/usr/bin/env python
2+
# Copyright (c) 2012, AverageSecurityGuy
3+
# All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without modification,
6+
# are permitted provided that the following conditions are met:
7+
#
8+
# Redistributions of source code must retain the above copyright notice, this
9+
# list of conditions and the following disclaimer.
10+
#
11+
# Redistributions in binary form must reproduce the above copyright notice,
12+
# this list of conditions and the following disclaimer in the documentation
13+
# and/or other materials provided with the distribution.
14+
#
15+
# Neither the name of AverageSecurityGuy nor the names of its contributors may
16+
# be used to endorse or promote products derived from this software without
17+
# specific prior written permission.
18+
#
19+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24+
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
25+
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28+
# OF SUCH DAMAGE.
29+
30+
import xml.etree.ElementTree
31+
import sys
32+
import re
33+
import os.path
34+
35+
#------------------------------------
36+
# Object to hold Nessus host items
37+
#------------------------------------
38+
39+
class VulnItem():
40+
def __init__(self, ip, fqdn, op, port):
41+
self.ip = ip
42+
self.fqdn = fqdn
43+
self.os = op
44+
self.port = port
45+
46+
47+
class Vulnerability():
48+
def __init__(self, pid):
49+
self.pid = pid
50+
self.name = ''
51+
self.desc = ''
52+
self.hosts = []
53+
54+
55+
def usage():
56+
print("plugin.py nessus_file plugin_id")
57+
sys.exit()
58+
59+
60+
##
61+
# function to return an IP address as a tuple of ints. Used for sorting by
62+
# IP address.
63+
def ip_key(ip):
64+
return tuple(int(part) for part in ip.split('.'))
65+
66+
67+
##
68+
# Take the filename and confirm that it exists, is not empty, and is a Nessus
69+
# file.
70+
def open_nessus_file(filename):
71+
if not os.path.exists(filename):
72+
print("{0} does not exist.".format(filename))
73+
sys.exit()
74+
75+
if not os.path.isfile(filename):
76+
print("{0} is not a file.".format(filename))
77+
sys.exit()
78+
79+
# Load Nessus XML file into the tree and get the root element.
80+
nf = xml.etree.ElementTree.ElementTree(file=filename)
81+
root = nf.getroot()
82+
83+
# Make sure this is a Nessus v2 file
84+
if root.tag == 'NessusClientData_v2':
85+
return filename, root
86+
else:
87+
print("{0} is not a Nessus version 2 file.".format(filename))
88+
sys.exit()
89+
90+
91+
#-------------------------#
92+
# Begin the main program. #
93+
#-------------------------#
94+
95+
if len(sys.argv) != 3:
96+
usage()
97+
98+
if sys.argv[1] == '-h':
99+
usage()
100+
else:
101+
file_name, nessus = open_nessus_file(sys.argv[1])
102+
plugin = sys.argv[2]
103+
104+
vuln = Vulnerability(plugin)
105+
106+
##
107+
# Find all the reports in the Nessus file
108+
reports = nessus.findall('Report')
109+
110+
##
111+
# Process each of the reports
112+
for report in reports:
113+
report_name = report.attrib['name']
114+
115+
# Process each host in the report
116+
report_hosts = report.findall('ReportHost')
117+
for host in report_hosts:
118+
hid = ''
119+
host_properties = host.find('HostProperties')
120+
121+
for tag in host_properties.findall('tag'):
122+
if tag.attrib['name'] == 'host-ip':
123+
hid = tag.text
124+
125+
# if hid is empty then the host scan did not complete or
126+
# some other error has occured. Skip this host.
127+
if (hid == ''):
128+
continue
129+
130+
# Find and process all of the ReportItems
131+
report_items = host.findall('ReportItem')
132+
for item in report_items:
133+
item_plugin = item.attrib['pluginID']
134+
135+
if item_plugin == plugin:
136+
vuln.name = item.attrib['pluginName']
137+
vuln.desc = item.find('description').text
138+
port = '{0}/{1}'.format(item.attrib['port'], item.attrib['protocol'])
139+
140+
vuln.hosts.append((hid, port))
141+
continue
142+
143+
144+
print("{0} ({1})".format(vuln.name, vuln.pid))
145+
print("{0}\n".format(vuln.desc))
146+
147+
if len(vuln.hosts) > 0:
148+
for vi in sorted(vuln.hosts, key=lambda x: ip_key(x[0])):
149+
print('{0}\t{1}'.format(vi[0], vi[1]))
150+
else:
151+
print("No vulnerable hosts found.")

0 commit comments

Comments
 (0)