OSSIM开源安全信息管理系统(十二)

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 = ""

                    #命令可用。请注意,只有“ping”对任何人开放。
                    #调用函数self.__check_sensor_ip()实现对ip地址的检测,如果是当前主机ip,即127.0.0.1,直接通过检测
                    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":
                            # spawn our control timer
                            #生成我们的控制计时器,如果为none,新生成一个
                            if controlmanager is None:
                                controlmanager = ControlManager(OssimConf())

                            response = controlmanager.process(self, command, line)

下面的就是一些仅有当前主机才可以请求的命令

#下面的仅有本主机可以
elif self.client_address[0] == '127.0.0.1':
	# Only control messages coming from localhost.
    #仅来自本地主机的控制消息。

    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":  # struct.unpack('!H',line[0:2])[0] == 0x1F1F:
            # it's a tlv
            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:
            # Cannot connect to database, return false.
            logger.warning("Cannot find registered sensors: %s" % str(msg))
            return False
        
        #从数据库中查询出id对应的ip
        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:
            # Uncomment for SSL
            #            certfile='/var/ossim/ssl/local/cert_local.pem'
            #            keyfile='/var/ossim/ssl/local/key_local.pem'
            serverAddress = ("0.0.0.0", int(self.__conf[VAR_FRAMEWORK_PORT]))
            logger.info("Listen on: %s:%s" % serverAddress)
            sleep(3)

            # Uncomment for Non SSL
            self.__server = FrameworkBaseServer(serverAddress, FrameworkBaseRequestHandler)
            # Uncomment for SSL
            #            self.__server = FrameworkBaseServer(serverAddress, FrameworkBaseRequestHandler, certfile=certfile, keyfile=keyfile, conf=OssimConf())

            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、日志记录内容

不同设备记录日志格式不同,那么什么样的日志才是有利于审计和有利于安全信息平台使用呢?目前国际上还没有统一的标准去衡量,但是通常来讲完整的日志应该包含如下信息:

  • Who:谁登录了。

  • What:他们在做什么,又发生了什么。

  • Where:发生在何处,在哪台主机,哪个文件系统上,或者哪个网络接口等等.

  • When:何时发生,应该包含开始时间和结束时间。

    为了得到更详细的内容,有时候还希望得到:为什么会发生( Why),如何发生(How),以及发生发展的趋势是什么,简单说就是5W1H。在网上找了一个图来大概描述一下,如下图所示。

在这里插入图片描述

有关安全运营的日志记录主要包含以下几个方面:

  1. 身份认证和授权。
  2. 系统变更管理(记录系统变更或组件变更等)。
  3. 网络威胁管理(由防火墙,IPS 设备产生)。
  4. 性能和容量管理(包括系统各种阈值,如CPU利用率、内存、网络带宽占用等)
  5. 业务的可持续性管理(系统开关机和冗余备份相关功能)。


上一篇:OSSIM开源安全信息管理系统(十一)
下一篇:

猜你喜欢

转载自blog.csdn.net/m0_47470899/article/details/121492640