2021SC@SDUSC
InventoryTask_NMAP.py OSSIM-agent源代码分析(九)
简述
OSSIM Agent的主要职责是收集网络上存在的各种设备发送的所有数据,然后按照一种标准方式(standardized way)有序的发送给OSSIM Server,Agent收集到数据后在发送给Server之前要对这些数据进行标准化处理,这样Server就可以依一种统一的方式来处理这些信息,并且也简化了Server的处理过程,
map是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端。确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统(这是亦称 fingerprinting)。它是网络管理员必用的软件之一,以及用以评估网络系统安全。所以在ossim中nmap是一个非常重要的模块,而这个文件就是进行相关nmap模块管理的 InventoryTask_NMAP就是对NMAP进行相关管理的部分
相关代码
初始导报:
import nmap
import xml.dom.minidom
import re
from InventoryTask import InventoryTask
from Event import HostInfoEvent
from Logger import Logger
类class NMAP_TASK:
构造函数:将运行状态置为未运行,初始化InventoryTask类和nmap.PortScanner类
def __init__(self, task_name, task_params, task_period, task_reliability, task_enable, task_type, task_type_name):
self._running = False
self._nm = nmap.PortScanner()
InventoryTask.__init__(self, task_name, task_params, task_period, task_reliability, task_enable,
task_type, task_type_name)
查询任务,准备排除参数和ip
def runQuery(self):
try:
host_arg, args_arg = self._task_params.split('#', 1)
if "!" in host_arg:
excludes = ','.join([host.lstrip('!') for host in host_arg.split(' ') if host.startswith('!')])
host_arg = ' '.join([host for host in host_arg.split(' ') if not host.startswith('!')])
args_arg += ' --exclude={}'.format(excludes)
logger.debug("NMAP scan: %s %s" % (str(host_arg), str(args_arg)))
self._nm.scan(hosts=host_arg, arguments=args_arg)
xmldata = self._nm.get_nmap_last_output()
except Exception, e:
logger.error("ERRROR :%s" % str(e))
return
dom = xml.dom.minidom.parseString(xmldata)
for nmaphost in dom.getElementsByTagName('host'):
host = HostInfoEvent()
for status in nmaphost.getElementsByTagName('status'):
处理主机状态
host['state'] = status.getAttributeNode('state').value
for address in nmaphost.getElementsByTagName('address'):
addrtype = address.getAttributeNode('addrtype').value
if addrtype == 'ipv4' or addrtype == 'ipv6':
host['ip'] = address.getAttributeNode('addr').value
if address.getAttributeNode('addrtype').value == 'mac':
host['mac'] = address.getAttributeNode('addr').value
hostnames = nmaphost.getElementsByTagName('hostnames')
if hostnames:
for hn in nmaphost.getElementsByTagName('hostname'):
host['hostname'] = hn.getAttributeNode('name').value
端口服务处理
str_ports = ''
software = set()
operative_system = set()
hardware = set()
ports = nmaphost.getElementsByTagName('ports')
if ports:
for port in nmaphost.getElementsByTagName('port'):
protocol = port.getAttributeNode('protocol').value
portnumber = port.getAttributeNode('portid').value
portstates = port.getElementsByTagName('state')
state = 'unknown'
if portstates:
if portstates[0].getAttributeNode('state'):
state = portstates[0].getAttributeNode('state').value
portservices = port.getElementsByTagName('service')
状态服务处理
if state != "open":
continue
str_services = ''
product = ''
version = ''
extrainfo = ''
services = []
str_cpe = ''
for ps in portservices:
try:
product = ps.getAttributeNode('product').value
except AttributeError:
pass
try:
version = ps.getAttributeNode('version').value
except AttributeError:
pass
try:
extrainfo = ps.getAttributeNode('extrainfo').value
except AttributeError:
pass
service_name = ps.getAttributeNode('name').value
if service_name == '' or service_name is None:
continue
try:
tunnel = ps.getAttributeNode('tunnel').value
if tunnel == 'ssl' and service_name == 'http':
service_name = 'https'
except AttributeError:
pass
services.append(service_name)
banner服务处理
banner = []
if product:
banner.append(product)
if version:
banner.append(version)
if extrainfo:
banner.append(extrainfo)
for cpe in ps.getElementsByTagName('cpe'):
if not banner:
banner.append(self.get_pretty_cpe(cpe))
ocpe = cpe.firstChild.nodeValue
cpe.firstChild.nodeValue += '|'
cpe.firstChild.nodeValue += (' '.join(banner)).lstrip(' ')
if cpe.firstChild.nodeValue.startswith('cpe:/o:'):
operative_system.add(cpe.firstChild.nodeValue)
elif cpe.firstChild.nodeValue.startswith('cpe:/h:'):
hardware.add(cpe.firstChild.nodeValue)
else:
if str_cpe:
str_cpe += ','
str_cpe += ocpe
software.add(cpe.firstChild.nodeValue)
if not str_cpe and banner:
str_cpe = (' '.join(banner)).lstrip(' ')
if len(services) > 0:
str_services = ','.join(["%s" % s for s in services])
if str_ports:
str_ports += ','
if str_cpe:
str_ports += '%s|%s|%s|%s' % (protocol, portnumber, str_services, str_cpe)
else:
str_ports += '%s|%s|%s|unknown' % (protocol, portnumber, str_services)
os = nmaphost.getElementsByTagName('os')
if os:
str_os = ''
last_accuracy = 0
for os in nmaphost.getElementsByTagName('osclass'):
osfamily = ''
try:
osfamily = os.getAttributeNode('osfamily').value
except:
pass
if osfamily not in ['embedded', '', 'unknown']:
accuracy = 0
try:
accuracy = os.getAttributeNode('accuracy').value
except:
pass
if accuracy > last_accuracy:
last_accuracy = accuracy
if os.getAttributeNode('osfamily') and os.getAttributeNode('osgen'):
str_os = '%s %s' % (osfamily, os.getAttributeNode('osgen').value)
operative_system_new = set()
hardware_new = set()
for cpe in os.getElementsByTagName('cpe'):
banner = self.get_pretty_cpe(cpe)
if cpe.firstChild.nodeValue.startswith('cpe:/o:'):
operative_system_new.add(cpe.firstChild.nodeValue + '|' + banner)
elif cpe.firstChild.nodeValue.startswith('cpe:/h:'):
hardware_new.add(cpe.firstChild.nodeValue + '|' + banner)
if len(operative_system_new) > 0 or len(hardware_new) > 0:
operative_system = operative_system_new
hardware = hardware_new
操作系统和软件相关字符处理
if str_os != '':
host['os'] = str_os
str_software = ''
software.update(operative_system)
software.update(hardware)
for s in software:
if str_software == '':
str_software += '%s' % s
else:
str_software += ',%s' % s
host['service'] = str_ports
host['software'] = str_software
host['inventory_source'] = 5
self.send_message(host)
通过正则表达式获取cpe
def get_pretty_cpe(cpe):
data_source = re.sub(r"^cpe:/.:", '', re.sub(r":+", ':', cpe.firstChild.nodeValue))
return ' '.join([s[0].upper() + s[1:] for s in re.sub(':', ' ', data_source).split(' ')])
running函数和开始工作函数
def doJob(self):
self._running = True
logger.info("Starting NMAP")
self.runQuery()
logger.info("NMAP collector ending..")
self._running = False
def get_running(self):
return self._running
|