基于suricata 的IEC104 插件设计与实现*
2021-01-26张周晶申玲钰
张周晶,申玲钰
(1.中国电子科技网络信息安全有限公司,四川 成都 610041;2.中国电子科技集团公司第三十研究所,成都 610041)
0 引言
随着工业互联网的发展,工业网络单独组网的状态正在被改变,为了将人、数据和设备进行有效连接,国外众多大型公司已根据其自身产品及产业特点构建了对应的工业互联网平台,我国在该领域也正在建立更加完善的框架。
中国工业互联网联盟设计并提出了工业互联网平台架构[1],如图1 所示,在该平台架构设计中,工业安全防护贯穿了应用层、平台层、Iaas 层以及边缘层。在工业互联网的架构中,互联网可以访问工业网络的情况也变得更加普遍,工业互联网的安全防护从底层到应用层都有关键技术,覆盖工业互联网全架构。在四个层面的安全防护中,数据安全包括数据存储安全和数据传输安全是重点和难点。上传和下发指令的工业协议会直接影响产品的质量、设备的运行状态,如果指令不当,将对生产造成实际的损失,情况严重将毁坏生产设备,因此监测防护设备对于工业协议的指令级行为监测需求也在稳步提高。
在工业协议中,IEC104 协议被广泛应用于电力行业和轨道交通行业[2]。通过IEC104 协议,实体设备之间能够通过数据传输进行设备的行为控制,例如控制主站能够远程读取子站设备状态,操作设备行为,调整设备参数,子站设备能够主动定时上传状态及相关监测数据。如果主站下达指令通过协议错误地发送给子站,会影响子站设备的正常行为,而子站上传状态错误则会影响主站对子站实际情况的监测,因此IEC104 协议指令级的监测、检测和审计是工业环境中入侵检测设备的必要功能。
图1 工业互联网平台架构
在当前的入侵检测软件系统中,suricata 框架提供多平台支持,能够根据实际情况进行配置,并且具有高效的采集能力,自带协议解析器引擎和基于snort 规则的检测引擎,能够满足当前工业环境中的流量监测、TCP 会话监测及部分通用协议的指令监测。因此在suricata 当前的解析器引擎、监测引擎和输出引擎内增加IEC104 协议的解析器、检测器和日志输出器能够补充suricata 入侵检测软件框架在IEC104 协议监测上的不足,为工业互联网提供一个能够进行指令级的可审计的入侵监测系统。
1 Suricata 软件框架
suricata 支持三种工作模式,分别是single 模式、autofp 模式和workers 模式。single 模式为单线程工作模式,即只启动一个线程完成采集、分析、会话管理、检测、日志输出的功能;autofp 模式通常采用多采集线程,在采集和解析完成后发送给会话管理线程做后续处理;worker 模式采用多线程模式,每个线程完整地进行采集、每个线程独立完成采集、分析、会话管理、检测、输出功能,驱动层就做了适当的负载均衡,单个数据包都在一个线程里处理。
Suricata 系统[3]采用自定义信号—与槽机制,用中断信号进行中断,从而调用对应回调函数的方式触发流程,因此在程序初始化时,即依据配置信息初始化了回调函数。以auto 模式为例,数据包在被接收后,数据的流向如图3 所示。先查找包对应的流,再根据数据包的信息更新对应的流,在StreamTcp 中判断包是否需要校验,然后根据StreamTcpPacket 更新数据包对应的流以及应用层数据;在检测[4]的时候根据流监测结果采用DetectFlow 或者DetectNoFlow,根据会话信息和规则内容进行匹配。在数据检测结束后,进行日志的输出。
图2 suricata 三种工作模式流程图
因此,IEC104 协议的插件包括三个部分:解析插件、检测插件和日志输出插件。协议解析插件能够完成对于IEC104 报文的十六进制码的分析,将IEC104 协议的报文解析成具有可读性的结构化数据;检测插件部分能够根据解析器输出的结构化数据和规则进行匹配比对,从而对指令级别的内容进行检测,并记录警告;日志输出插件能够将每条IEC104 报文的可读性指令输出。
2 IEC104 解析模块设计
2.1 IEC104 解析模块注册
在图2 中可见,入口为AppLayerParseSetup 中调用的注册函数RegisterIEC104Parse。其中包括以下内容:
(1)注册协议端口和协议名称;
(2)注册预处理函数,预处理函数使用位置在AppLayer 层判断数据包的应用层类型时调用,预处理协议即会将数据传入对应的应用层协议解析器,进行十六进制数据包解析;
(3)注册解析函数IEC104RequestParse 和IEC104ResponseParse,分别处理请求和响应数据包;
(4)注册应用层会话管理函数IEC104State Alloc,IEC104StateFree,IEC104StateTxFree
分别管理应用层状态空间的分配、清理以及清理每个会话中的传输对象;
图3 suricata 内部插件调用流程
(5)注册传输对象相关函数,如获取当前传输对象IEC104GetTx,获取总的传输对象个数IEC104GetTxCnt;
(6)注册日志相关函数,如传输对象日志状态IEC104GetTxLogged,IEC104SetTxLogged;
(7)注册IEC104GetAlstateProgressCompletionS tatus,返回当前应用层会话状态。
重点关注解析函数内部的实现,即IEC104Parser。
2.2 IEC104 协议说明及解析函数设计
IEC104 规约发布于1992 年,更新于2002 年,当前使用较多的是2002 年版本。基于TCP/IP 的IEC104协议格式称为应用规约数据单元(Application Protocol Data Unit,APDU),其中分为应用规约控制信息(Application Protocol Control Information,APCI)和应用服务数据单元(Application Service Data Unit,ASDU),根据传输需求分为不编号的控制功能格式(U 帧)、编号的监视功能格式(S 帧)和编号的信息传输格式(I 帧)。
I 帧用于传输应用数据,根据类型标识的不同,数据格式各有差异,一般而言为APCI+ASDU 两部分组成,总格式见图4,其中控制域1 和控制域2为发送序号,控制域3 和控制域4 为接收序号,类型标识定义了信息对象的结构类型和格式,传送原因标识了协议发出的原因,详表见表1。ASDU 包含公共体地址和信息体地址,其中公共体地址长度为2 字节,其低位表示标志装置地址;信息体地址长度为3 字节,对应点表的点号。
例如请求和响应的十六进制数如下所示,解释如括号中所示。
请求:68(启动符) 12(APDU 长度)02 c7(发送序号)ce ca(接收序号) 01(type)02(可变结构限定词)03
响应:00(传送原因) 01 00 (公共体地址),49 01 00 (信息体地址)01(信息体元素)4a 01 00(信息对象地址) 00(信息体元素)…
U 帧为控制用报文,其格式见图6,只有APCI格式部分一共只有启动/启动确认、停止传送/停止传送确认以及链路测试/链路测试确认共3 类6种命令。
S 帧用于无应用数据可传输时确认对方的发送,只有APCI 部分,其控制域如图5 所示,控制域1和控制域2 已经被固定,即不存在发送序号,只有接收序号。
图4 IEC104 报文结构
图5 IEC104 报文S 帧结构
图6 IEC104 报文U 帧结构
IEC104 协议中,U 帧和S 帧只有APCI 部分,仅I 帧有ASDU 部分,因此将IEC104 的解析区分为APCIParser 和ASDUParser。APCIParser 需要解析启动字符为0x68,APDU 长度,控制域1,控制域2,控制域3 和控制域4,每个控制域为一个字节。根据1.1 节可知,能够通过控制域1 的低2 位来区分帧格式,若低2 位为0x00,则为I 帧,0x01 为S 帧,0x03 为U 帧。
ASDUParser 仅解析I 帧报文的ASDU 结构体,ASDU 为变长结构体和定长结构体两部分,定长结构体能够解析内容为报文类型,传送质量、传送信息体个数、原因、测试以及对象地址,变长部分为信息体地址及其结构体。由于变长部分有自定义内容,因此只检查报文的完整性,不做内容具体解析。从应用层第7 字节开始,获取定长结构体信息,再根据解析到的信息体个数完成已知信息体格式的结构体解析。
例如,若报文为I 类型报文,其应用层报文为:
68(启动字符) 0e (长度) 04 00(RX) 00 00(TX)03 01 01 00 01 00 00 00 00 00
第一字节到第七字节由APCIParser 解析,剩余部分由ASDUParser 解析,解析结果如表1 所示。
表1 parser 处理内容及对应关系
在注册完成后,流操作线程会根据数据流走向调用对应的已经注册的IEC104 函数,从而进行创建、设置和解析。这也是suricata 框架的一大优点,即解析器的状态分配都是可以被流操作线程控制的。重点关注的是请求和响应的解析函数。由于IEC104 数据报文的请求和响应都是I 帧、U帧和S 帧,其实完成的是同一个IEC104Parser。IEC104Parser 的流程图如图所示,其总流程为:收到应用层数据包并检测会话状态、流状态;然后解析APCI 头部的固定格式,若完成解析则给当前State 创建Tx,根据APCI 头部信息检查包类型,若为I 帧,则调用ASDUParser 进行解析,直到解析完成,并处理可能存在的待组包层应用层信息。流程图如图6 所示。
3 IEC104 监测模块的设计
监测模块以解析模块为基础,输入为解析结果,如自定义IEC104 结构transaction 等,IEC104 协议监测模块针对数据包类型PacketType 和TypeId。入口函数为SigTableSetup[5],需要将PacketType 和TypeId 的三类函数,即setup,free,match 函数进行注册,同时注册IEC104 的监测模块到主引擎。
suricata 引擎首先确定了回调函数的参数,应用层协议注册监测模块时,setup、free、match 的回调函数需要按照固定参数注册。在PacketType 中对I 帧、U 帧、S 帧进行告警。若I 帧进行警告日志的输出,在初始化时,s 引擎将该规则转换成可用数据,存储在DetectIEC104 结构中,通过与解析结果进行比对,即可得到结果。PacketType 的检测流程为:通过match 函数获取解析结构transaction 和预置规则结构DetectIEC104,通过比对transaction 中packetType 和检测结构中的packetType 即可得出结果,若相同则返回1,表示需要输出警告信息,否则输出0,不进行警告信息输出。
4 IEC104 日志模块的设计
suricata 框架的日志模块为独立模块,在worker模式下日志模块的结构图如图8 所示。注册的table包括告警表、应用层协议日志表等,在应用层日志输出时,在调用时按照数据包日志表、传输日志表、文件日志表、文件内容日志表及流日志表的顺序轮询,在查到传输数据表时也按照图8 第二行注册的表信息依次轮询,首先找到alert 表,查看alert 表是否有警告信息需要输出,若有则调用回调函数进行输出,若没有,则继续查询到应用层日志事件表,若有输出,则调用输出函数进行输出,5 张数据表中都注册有一到多个子表。
IEC104 日志模块通过OutputRegisterLoggers()调用IEC104 的日志注册函数,注册函数JsonIE C104Register 注册了ToServer 和ToClient 的线程启停管理函数,配置读取函数及日志输出函数,并在Init 时通过AppLayerParserRegisterLogger 将IEC104的日志模块注册到日志的module 里。在软件初始化时,调用状态初始化函数JsonIEC104LogInitCtx初始化读取到的配置信息,配置信息包括文件类型、文件状态,根据配置信息完成文件创建、文件状态初始化,JsonIEC104LogDeInitCtx 完成文件的清理。JsonIEC104LoggerToClient 和JsonIEC104 LoggerToServer 分别生成请求及响应的报文日志。在生成日志前,传入参数传输对象Tx,Tx 中存储解析后的内容,如APCI 头部结构,ASDU 内部结构,通过读取Tx 结构体能够将关心的参数如typeId,causeTx 等信息提取至json 格式中。通过调用CreateJSONHeader,能够将该数据包的流信息输出到json 格式中暂存,通过OutputJSONBuffer 将js数据写入buffer 中,并将buffer 通过LogFileWrite 的方式输出,输出结构是根据配置信息中的logType进行区分,根据配置和依赖项可以支持写入syslog文件、unix socket 或者redis 服务器上。
图7 解析函数设计流程图
图8 日志模块数据结构设计
5 IEC104 插件实现结果
IEC104 插件实现后,会有以下日志结果发生变化。首先是suricata 的运行日志,其中会增加应用层IEC104 的数据解析个数、transaction 个数信息。其示例如图9 所示。
图9 stats 增加数据结构
其次,能够在日志中看到iec104 的日志信息,其示例如下:
6 结语
通过在suricata 软件框架下设计及实现IEC104插件,当前的版本能够统计IEC104 的报文个数、流量情况,能根据IEC104 解析器解析结果报告指令、传输原因和公共体地址信息。该设计增强了suricata 的功能,提供了针对性的检测和告警信息。能够完成工业互联网的指令级检测。