2021SC@SDUSC
本周主要分析的内容为 Framework 模块中,Listener.py 文件。然后衔接上周内容,继续对 OSSIM 系统的日志分析部分进行简单分析。
1、Listener.py
在这个文件中,主要定义了两个类 FrameworkBaseRequestHandler 和 FrameworkBaseServer,分别实现的主要功能是对请求的数据包进行一些处理
同样先导入一些包
import re
import socket
import SocketServer
import sys
import threading
import json
from time import sleep
然后导入自己在其他文件中定义的
import Action
from DoControl import ControlManager
from DoASEC import ASECHandler
from DoWS import WSHandler
from DoNagios import NagiosManager
from BackupManager import BackupRestoreManager
from Logger import Logger
from OssimConf import OssimConf
from OssimDB import OssimDB
from DBConstantNames import *
接下来定义全局变量
logger = Logger.logger
controlmanager = None
asechandler = None
bkmanager = None
接下来就是具体的类代码部分
首先分析 FrameworkBaseRequestHandler
先是获取了请求的 IP 、端口、请求 ID 等基本信息
class FrameworkBaseRequestHandler(SocketServer.StreamRequestHandler):
__nagiosmanager = None
__conf = None
__sensorID = ""
def getRequestorIP(self):
return self.client_address[0]
def getRequestorPort(self):
return self.client_address[1]
def getRequestorID(self):
return self.__id
def handle(self):
主要功能是对 sensor 发送的请求进行处理
def handle(self):
global controlmanager
global bkmanager
global asechandler
self.__id = None
logger.debug("Request from: %s:%i" % (self.client_address))
接下来是一个 while 循环,其中有很多 if else 分支语句,主要就是对不同的请求进行不同的处理相应
通过调用函数 self.__check_sensor_ip() 实现对 ip 地址的检测,如果是当前主机 ip ,即 127.0.0.1,直接通过检测。函数 self.__check_sensor_ip() 的实现在下面的分析过程中讲解
while 1:
try:
line = self.rfile.readline().rstrip('\n')
if len(line) > 0 and not line.isspace():
command = line.split()[0]
response = ""
if self.__check_sensor_ip(self.client_address[0]) or self.client_address[0] == '127.0.0.1':
if command == "ping":
response = "pong\n"
elif command == "control":
if controlmanager is None:
controlmanager = ControlManager(OssimConf())
response = controlmanager.process(self, command, line)
下面的就是一些仅有当前主机才可以请求的命令
elif self.client_address[0] == '127.0.0.1':
if command == "nagios":
if self.__nagiosmanager is None:
self.__nagiosmanager = NagiosManager(OssimConf())
response = self.__nagiosmanager.process(line)
elif command == "add_asset" or command == "remove_asset" or command == "refresh_asset_list":
linebk = ""
if controlmanager is None:
controlmanager = ControlManager(OssimConf())
linebk = "action=\"refresh_asset_list\"\n"
response = controlmanager.process(self, command, linebk)
elif command == "backup":
if bkmanager is None:
bkmanager = BackupRestoreManager(OssimConf())
response = bkmanager.process(line)
elif command == "asec":
if asechandler is None:
asechandler = ASECHandler(OssimConf())
response = asechandler.process_web(self, line)
elif command == "asec_m":
if asechandler is None:
asechandler = ASECHandler(OssimConf())
response = asechandler.process(self, line)
elif command == "ws":
try:
[ws_data] = re.findall('ws_data=(.*)$', line)
ws_json = json.loads(ws_data)
logger.info("Received new WS: %s" % str(ws_json))
except Exception, msg:
logger.warning("WS json is invalid: '%s'" % line)
else:
if ws_json['ws_id'] != '':
for ws_id in ws_json['ws_id'].split(','):
try:
ws_handler = WSHandler(OssimConf(), ws_id)
except Exception, msg:
logger.warning(msg)
else:
response = ws_handler.process_json('insert', ws_json)
else:
logger.warning("WS command does not contain a ws_id field: '%s'" % line)
elif command == 'event':
a = Action.Action(line)
a.start()
else:
logger.info("Unrecognized command from source '%s': %s" % (self.client_address[0], command))
return
接下来的 else 分值是不被允许的主机
else:
logger.info("Dropped data from a disallowed source '%s': %s" % (self.client_address[0], command))
return
if len(response) > 0:
self.wfile.write(response)
line = ""
最后一部分是异常处理
except socket.error, e:
logger.warning("Client disconnected...%s" % e)
except IndexError:
logger.error("IndexError")
except Exception, e:
logger.error("Unexpected exception in listener: %s" % str(e))
import sys, traceback
traceback.print_exc(file=sys.stdout)
return
两个类属性设置的函数
def set_id(self, id):
self.__id = id
def set_sensorID(self, uuid):
self.__sensorID = uuid
两个获得类属性值的函数
def get_sensorID(self):
return self.__sensorID
def get_id(self):
return self.__id
__check_sensor_ip(addr)
刚才在上面的分析过程中,已经在 handle 函数中调用了这个方法
这个方法主要实现的功能就是检查请求是否来自准许的传感器
接收参数为 adrr,为具有 ip 地址和请求端口的元组
返回值为 true 或者 false,如果是来自于传感器,返回 true,否则返回 false
@staticmethod
def __check_sensor_ip(addr):
try:
conf = OssimConf()
myDB = OssimDB(conf[VAR_DB_HOST],
conf[VAR_DB_SCHEMA],
conf[VAR_DB_USER],
conf[VAR_DB_PASSWORD])
myDB_connected = myDB.connect()
except Exception, msg:
logger.warning("Cannot find registered sensors: %s" % str(msg))
return False
query = 'select inet6_ntoa(sensor.ip) as ip from sensor, system where sensor.id=system.sensor_id;'
result = myDB.exec_query(query)
for r in result:
if r['ip'] == addr:
return True
else:
return False
后面还有一个 FrameworkBaseServer 类,继承自 SocketServer.ThreadingTCPServer ,实现的也比较简单,仅有两个函数,一个是构造函数,进行参数的简单初始化。另一个函数主要是调用 handle_request() 来进行一些处理。
由于比较简单,代码也很短,这里就不再详细阐述了。
最后一个类是 Listener 类,继承自 threading.Thread ,主要功能就是监听相应主机
class Listener(threading.Thread):
def __init__(self):
self.__conf = OssimConf()
self.__server = None
threading.Thread.__init__(self)
def run(self):
try:
serverAddress = ("0.0.0.0", int(self.__conf[VAR_FRAMEWORK_PORT]))
logger.info("Listen on: %s:%s" % serverAddress)
sleep(3)
self.__server = FrameworkBaseServer(serverAddress, FrameworkBaseRequestHandler)
self.__server.serve_forever()
except socket.error, e:
logger.critical("Something wrong happend while binding the socket. %s" % str(e))
sys.exit(-1)
except Exception, e:
logger.error("ERROR: %s" % str(e))
sys.exit(-1)
2、日志记录内容
不同设备记录日志格式不同,那么什么样的日志才是有利于审计和有利于安全信息平台使用呢?目前国际上还没有统一的标准去衡量,但是通常来讲完整的日志应该包含如下信息:
有关安全运营的日志记录主要包含以下几个方面:
- 身份认证和授权。
- 系统变更管理(记录系统变更或组件变更等)。
- 网络威胁管理(由防火墙,IPS 设备产生)。
- 性能和容量管理(包括系统各种阈值,如CPU利用率、内存、网络带宽占用等)
- 业务的可持续性管理(系统开关机和冗余备份相关功能)。
上一篇:OSSIM开源安全信息管理系统(十一) 下一篇:
|