xml_utils.py
8.02 KB
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
#!/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'eduardo'
from lxml import etree
import model.computer
import model.printer
import model.host
from .session import SnmpSession
class NmapXML(object):
"""
Classe para realizar o parsing do arquivo XML do NMAP
"""
def __init__(self,
xml):
self.xml = xml
self.hosts = dict()
def parse_xml(self):
"""
Parse XML file
"""
infile = open(self.xml, 'r')
for _, element in etree.iterparse(infile, events=('start', 'end'), tag='host'):
addr_list = element.findall('address')
# MAC e IP
for addr in addr_list:
if addr.get('addrtype') == 'ipv4':
host = addr.get('addr')
elif addr.get('addrtype') == 'mac':
mac = addr.get('addr')
# A chave do dicionário é o IP
self.hosts[host] = dict()
if 'mac' in locals():
self.hosts[host]['mac'] = mac
# Hostname
self.hosts[host]['hostname'] = dict()
for tag in element.find('hostnames').findall('hostname'):
self.hosts[host]['hostname'][tag.get('type')] = tag.get('name')
# Open ports
ports = element.find('ports')
self.hosts[host]['ports'] = dict()
for port_xml in ports.findall('port'):
if port_xml.find('service') is not None:
service = port_xml.find('service').get('name')
else:
service = None
self.hosts[host]['ports'][port_xml.get('portid')] = {
'protocol': port_xml.get('protocol'),
'state': port_xml.find('state').get('state'),
'service': service,
}
# OS Matches
os = element.find('os')
if os is not None:
self.hosts[host]['os'] = dict()
for osmatch in os.findall('osmatch'):
self.hosts[host]['os'][osmatch.get('name')] = dict()
self.hosts[host]['os'][osmatch.get('name')]['accuracy'] = osmatch.get('accuracy')
for osclass in osmatch.findall('osclass'):
self.hosts[host]['os'][osmatch.get('name')]['osclass'] = {
'type': osclass.get('type'),
'vendor': osclass.get('vendor'),
'osfamily': osclass.get('osfamily'),
'accuracy': osclass.get('accuracy'),
'cpe': osclass.findtext('cpe'),
'version': osmatch.get('name')
}
# General attributes
self.hosts[host]['starttime'] = element.get('starttime')
self.hosts[host]['endtime'] = element.get('endtime')
status = element.find('status')
self.hosts[host]['state'] = status.get('state')
return True
def identify_host(self,
hostname,
timeout=None):
if not self.hosts:
raise AttributeError("It is necessary do load XML file first")
# Ordena os sistemas operacionais por accuracy
host = self.hosts[hostname]
accuracy = int(0)
if host.get('ports'):
scantime = int(host.get('endtime')) - int(host.get('starttime'))
#FIXME: Tem que encontrar uma forma melhor de identificar a impressora
for value in ['9100']:
if value in host['ports'].keys():
# Regra temporária!!! As impressoras serão identificadas pela porta 9100
printer = model.printer.Printer(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host['ports'],
)
return printer
else:
# Tenta ler o contador para identificar a impressora
snmp_session = SnmpSession(
DestHost=hostname,
Timeout=timeout
)
status = snmp_session.printer_counter()
if status is not None:
# Se conseguir ler o contador, é impressora
printer = model.printer.Printer(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host['ports'],
)
return printer
elif host.get('os'):
# Nesse caso já sei que é computador. Precisa identificar o OS
for os in host['os'].keys():
if int(host['os'][os]['accuracy']) > accuracy:
accuracy = int(host['os'][os]['accuracy'])
os_final = os
scantime = int(host.get('endtime')) - int(host.get('starttime'))
computer = model.computer.Computer(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host.get('ports'),
so=host['os'][os_final]
)
return computer
else:
# Desiste e retorna host genérico
host = model.host.Host(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host['ports'],
)
return host
else:
host = model.host.Host(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host['ports'],
)
return host
elif host.get('os'):
# Nesse caso já sei que é computador. Precisa identificar o OS
for os in host['os'].keys():
if int(host['os'][os]['accuracy']) > accuracy:
accuracy = int(host['os'][os]['accuracy'])
os_final = os
scantime = int(host.get('endtime')) - int(host.get('starttime'))
computer = model.computer.Computer(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host.get('ports'),
so=host['os'][os_final]
)
return computer
else:
# Não foi possível identificar. Só gera um host genérico
scantime = int(host.get('endtime')) - int(host.get('starttime'))
host = model.host.Host(
ip_address=hostname,
mac_address=host.get('mac'),
hostname=host.get('hostname'),
inclusion_date=host.get('endtime'),
scantime=scantime,
open_ports=host['ports'],
)
return host