2021SC@SDUSC
SessionParser.py
OSSIM-agent源代码分析(十)
简述
OSSIM Agent的主要职责是收集网络上存在的各种设备发送的所有数据,然后按照一种标准方式(standardized way)有序的发送给OSSIM Server,Agent收集到数据后在发送给Server之前要对这些数据进行标准化处理,这样Server就可以依一种统一的方式来处理这些信息,并且也简化了Server的处理过程。
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。
作为使用cs模型的OSSIM,session的处理和控制就至关重要了
相关代码
初始导包
import re
from sets import Set
import sgmllib
import socket
SessionParser类
class SessionParser(sgmllib.SGMLParser):
解析给定字符串函数
def parse(self, s):
self.feed(s)
self.close()
初始化函数,将ip、端口、端口组等变量初始化
def __init__(self, verbose=0):
sgmllib.SGMLParser.__init__(self, verbose)
self.starting_description = 0
self.inside_table_element = 0
self.inside_table_row = 0
self.in_session = 0
self.td_count = 0
self.seen = 0
self.sessions = []
self.session_num = 0
self.queried_ip = ""
self.dst_port_group = {}
self.src_port_group = {}
self.source_ip = ""
self.source_port = ""
self.dest_ip = ""
self.dest_port = ""
self.data_sent = 0
self.data_rcvd = 0
self.active_since = ""
self.last_seen = ""
self.duration = 0
self.inactive = 0
时间处理函数,通过正则表达式,将只有秒,时分秒,日期时分秒分开处理
def tosecs(self, data):
if data.endswith('sec'):
data = data.split(' ', 1)[0]
elif data.__contains__('day'):
result = re.findall('(\d+) days? (\S+)', data)
(days, time) = result[0]
seconds = int(days) * 86400
dt = time.split(':')
seconds += int(dt.pop())
try:
seconds += seconds + int(dt.pop()) * 60
seconds += seconds + int(dt.pop()) * 3600
except IndexError:
pass
data = str(seconds)
else:
dt = data.split(':')
seconds = int(dt.pop())
try:
seconds += int(dt.pop()) * 60
seconds += int(dt.pop()) * 3600
except IndexError:
pass
data = str(seconds)
return data
设置td开始函数
def start_td(self, attributes):
self.td_count += 1
self.inside_table_element = 1
设置td结束函数
def end_td(self):
self.inside_table_element = 0
self.seen = 0
设置tr开始函数
def start_tr(self, attributes):
self.inside_table_row = 1
设置tr结束函数,同时如果session和ip都存在,则将将ip、端口等数据记录在tmp中,保存于日志中
def end_tr(self):
self.inside_table_row = 0
self.td_count = 0
if self.in_session and self.source_ip:
self.session_num += 1
tmp = "%s:%s --> %s:%s (%f %f) duration: %s" % (self.source_ip,self.source_port,self.dest_ip,self.dest_port, self.data_sent, self.data_rcvd, self.duration)
self.sessions.append(tmp)
设置a开始函数,如果name为href且session存在则设置match
def start_a(self, attributes):
self.inside_table_row = 1
for name, value in attributes:
if name == "href" and self.in_session:
matches = re.findall("\d+\.\d+\.\d+\.\d+",value)
if len(matches) > 0:
if self.td_count is 1:
self.source_ip = matches[0]
elif self.td_count is 2:
self.dest_ip = matches[0]
数据设置函数,如果ip未设置,则通过matches,来补充ip设置
def handle_data(self, data):
if self.queried_ip is "":
matches = re.findall("(\d+\.\d+\.\d+\.\d+)",data)
if len(matches) > 0:
self.queried_ip = matches[0]
根据data的类型,设置对应的session标志
if data.__contains__("Active TCP/UDP Sessions"):
self.in_session = 1
if data.__contains__("The color of the host"):
self.sessions.append("NumSessions:%d" % int(self.session_num))
self.in_session = 0
source_sessions = 0
dest_sessions = 0
通过sess,清洗session中的各个数据
for sess in self.sessions:
src_str = "^%s:.*" % self.queried_ip
dst_str = "^\d+\.\d+\.\d+\.\d+:\S+\s+-->\s+%s:.*" % self.queried_ip
src_sess = "^%s:\S+\s+-->\s+(\d+\.\d+\.\d+\.\d+):(\S+)" % self.queried_ip
dst_sess = "^(\d+\.\d+\.\d+\.\d+):\S+\s+-->\s+%s:(\S+)" % self.queried_ip
根据session重新设置matches
if re.findall(src_str, sess):
source_sessions += 1
if re.findall(dst_str, sess):
dest_sessions += 1
matches = re.findall(src_sess, sess)
再次根据matches,设置端口及端口组
if len(matches) > 0:
if matches[0][1] in self.src_port_group:
self.src_port_group[matches[0][1]].add(matches[0][0])
else:
self.src_port_group[matches[0][1]] = Set()
self.src_port_group[matches[0][1]].add(matches[0][0])
matches = re.findall(dst_sess, sess)
if len(matches) > 0:
if matches[0][1] in self.dst_port_group:
self.dst_port_group[matches[0][1]].add(matches[0][0])
else:
self.dst_port_group[matches[0][1]] = Set()
self.dst_port_group[matches[0][1]].add(matches[0][0])
self.sessions.append("SessionsAsSource:%s" % source_sessions)
self.sessions.append("SessionsAsDest:%s" % dest_sessions)
根据端口,添加session的数据
for port in self.src_port_group:
self.sessions.append("UniqPort%sAsSourceSessions:%d" % (port, len(self.src_port_group[port])))
for port in self.dst_port_group:
self.sessions.append("UniqPort%sAsDestSessions:%d" % (port, len(self.dst_port_group[port])))
处理相关的端口和端口组的流量,并记录其对应的时间
if self.inside_table_element and self.in_session:
if self.td_count <= 2:
matches = re.findall(":(\w+)",data)
if len(matches) > 0:
try:
port = socket.getservbyname(matches[0])
except:
port = matches[0]
if self.td_count is 1:
self.source_port = port
elif self.td_count is 2:
self.dest_port = port
elif self.td_count is 3:
if self.seen == 0:
self.data_sent = float(data)
self.seen = 1
else:
if data.__contains__("KB"):
self.data_sent *= 1024
elif data.__contains__("MB"):
self.data_sent *= 1024 * 1024
elif data.__contains__("GB"):
self.data_sent *= 1024 * 1024 * 1024
self.seen = 0
elif self.td_count is 4:
if self.seen == 0:
self.data_rcvd = float(data)
self.seen = 1
else:
if data.__contains__("KB"):
self.data_rcvd *= 1024
elif data.__contains__("MB"):
self.data_rcvd *= 1024 * 1024
elif data.__contains__("GB"):
self.data_rcvd *= 1024 * 1024 * 1024
self.seen = 0
elif self.td_count is 5:
self.active_since = data
elif self.td_count is 6:
self.last_seen = data
elif self.td_count is 7:
self.duration = self.tosecs(data)
elif self.td_count is 8:
self.inactive = self.tosecs(data)
获取session函数
def get_sessions(self):
return self.sessions