0x00 前言
在使用suricata的过程中遇到很多绕过(检测引擎漏报)或者说suricata现有架构难以实现检测(检测引擎误报)的部分,这里简单记录一些复现,没有一一总结了,就想到哪里写到哪里,陆续更新吧。(欢迎同好交流)
0x01 案例分析
1.漏报和性能无法兼顾
alert tcp-pkt any any -> any any (msg:"trojan likely msf connecting"; flow:established,to_client; content:"MZ"; content:"This program cannot be run in DOS mode"; classtype:trojan-activity; sid:10000001;)
这条规则很简单,检测响应中带有"MZ"字符串和"This program cannot be run in DOS mode"字符串的tcp包。但是忽略了对于请求的检查,导致了普通的exe程序也可能带有这些字符引起误报。设想一下,如果编写规则在请求中添加约束,如 check host 将常见域名下的下载exe行为过滤掉,理论上是可以的,会减少很多误报,但是会显著降低性能,因为不可能每个请求都检查host后交给suricata添加一个标记,这会给引擎带来很大负担,所以兼顾误报与性能往往会选择前者。有真实的攻击,会告警,但是更多的普通正常的事件也会触发。这就是目前安全设备尴尬的地方,也是suricata的一个检测瓶颈。
想解决这个问题,我不得不提及一个名词SIEM(security information and event management),从海量日志中提取有价值的信息,产生告警。无论是简单的态势平台的统计规则,还是复杂的行为/AI的规则,只要是跟日志相关的,都属于SIEM的范畴。试想一下,如果我通过过滤原始流量日志,提取出请求头里host不是某些常用域名的请求,再把过滤出来的这些请求的请求体用上面的规则匹配,是不是就解决了这个问题呢?可以极大的降低误报,对于产生的不多的告警,如果我能通过写一个分析模块,在告警数据展示前,再次进行研判(这个分析模块要融合人工研判的经验,分析哪些很可能不是msf的流量并将它去掉),那么这个系统是不是就相当的有价值呢?就目前2022年这个时间点来说,国内市面上的所谓的”主流"安全厂商的安全产品都没有做到这个层次。如果你是大厂的甲方人员,有资源有人力做企业内部的安全建设,不妨尝试我的方法,一定会有所收获。
2. suricata 匹配无三次握手包
在 suricata.yaml 里 stream 下 新增 midstream: yes ,可以匹配没有三次握手的包;
checksum-validation: no 等价于 -k none , 不校验回放时读取的数据包错误
-k none。关掉校验和检查,这个可以在配置文件里关,也可以命令行关。不关的话,校验和不对的包suricata不做传输层以上的处理。
3.0x00
suricata 是一套解析原始流量并输出日志的系统,任何一个环节出了问题,都可能没有告警。
于是乎请看这个例子:
流量中包含0x00,引擎解析过程转为\u0000 unicode 0 处理,引擎日志输出过程,json嵌套对象展开环节,原生json不支持日志内容包含unicode 0,导致无法输出告警。
4.畸形包攻击 updated@220915
举个例子:
网络运营商包注入攻击:
这种攻击可以被用来篡改网页(运营商层面,概率触发篡改成功)
使用TCP传输较大数据时,都会将数据分片,然后按照顺序依次传输。当Wireshark抓包时候,数据包标记为TCP Out-Of-Order,意思是该数据包的发送顺序不对。这意味着网络状况不好。当然,Wireshark有时会将重传的包识别为乱序包。
检测思路可以是,packet Length 小于一定阈值,比如<800 ,还分包了 TCP Out-Of-Order,可以给出告警提示风险。
响应包畸形,一定程度绕过检测,对于里面的 302 Found,
suricata 不把它当作头也不把它当作body。
我的解决方案,这里抛砖引玉:
alert tcp any any -> any any (msg:"packet-injection"; content:"302 Found|0a|Location"; http.stat_code; content:"302"; sid:10000002;)
其他的畸形包导致的协议解析异常(不规则的流量(不符合RFC)):
将http 识别为 dcerpc
5.协议层面绕过 updated@220921
通过对常见协议如http的一些编码构造特殊字符等造成检测引擎解析数据格式异常绕过。
通过对非常见协议的攻击绕过。
以krb5协议为例:
在krb5的密码喷洒攻击时:
假设检测规则:
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:10; sid:3; rev:1;)
对应的日志如下:
{"timestamp":"2020-07-23T03:16:35.086467+0800","flow_id":321326108855864,"pcap_cnt":15,"event_type":"alert","src_ip":"172.16.66.36","src_port":88,"dest_ip":"172.16.66.1","dest_port":50443,"proto":"UDP","tx_id":0,"alert":{"action":"allowed","gid":1,"signature_id":1113,"rev":1,"signature":"Kerberos 5 AS-REQ message","category":"","severity":3},"app_proto":"krb5","flow":{"pkts_toserver":1,"pkts_toclient":1,"bytes_toserver":191,"bytes_toclient":144,"start":"2020-07-23T03:16:35.085560+0800"},"payload":"fmQwYqADAgEFoQMCAR6kERgPMjAyMDA3MjIxOTE2MzVapQUCAwVNgKYDAgEGqREbD1RIUkVFQkVFU0NPLkNPTaokMCKgAwIBAqEbMBkbBmtyYnRndBsPVEhSRUVCRUVTQ08uQ09N","payload_printable":"~d0b..............20200722191635Z.....M..........THREEBEESCO.COM.$0\".......0...krbtgt..THREEBEESCO.COM","stream":0,"pcap_filename":"CA_kerbrute_passwordspray_kerberos_AS-REQ.pcapng"}
{"timestamp":"2020-07-23T03:16:35.086467+0800","flow_id":321326108855864,"pcap_cnt":15,"event_type":"krb5","src_ip":"172.16.66.36","src_port":88,"dest_ip":"172.16.66.1","dest_port":50443,"proto":"UDP","krb5":{"msg_type":"KRB_ERROR","failed_request":"KRB_AS_REQ","error_code":"KDC_ERR_C_PRINCIPAL_UNKNOWN","cname":"<empty>","realm":"<empty>","sname":"krbtgt/THREEBEESCO.COM","encryption":"<none>","weak_encryption":false},"pcap_filename":"CA_kerbrute_passwordspray_kerberos_AS-REQ.pcapng"}
{"timestamp":"2020-07-23T03:16:32.800983+0800","flow_id":321326108855864,"event_type":"flow","src_ip":"172.16.66.1","src_port":50443,"dest_ip":"172.16.66.36","dest_port":88,"proto":"UDP","app_proto":"krb5","flow":{"pkts_toserver":1,"pkts_toclient":1,"bytes_toserver":191,"bytes_toclient":144,"start":"2020-07-23T03:16:35.085560+0800","end":"2020-07-23T03:16:35.086467+0800","age":0,"state":"established","reason":"shutdown","alerted":true},"pcap_filename":"CA_kerbrute_passwordspray_kerberos_AS-REQ.pcapng"}
使用suricata原生的日志解析:
可以观察到只检测了回包的 cname字段,原生没检测请求中的cname字段,也没检测请求中的msg-type字段,只检测了响应里的error-code字段,但命中的响应确实是 msg-type=10 的AS-REQ请求对应的回包,只是回包的msg-type=30。
应该是协议解析bug。
唯一在请求包的日志没有解析出cname字段和msg-type字段。
对于原生的日志解析bug,有2个解决方案。
其一,改协议解析源码,一般是RUST开发的,插件化。
其二,高超的策略师也许可以通过其他方式的写法规避这类问题。
使用下面的规则在 suricata v6.0.1 也无法告警,显然有协议解析bug,不支持检测
- 30 (ERROR)
alert krb5 any any -> any any (msg:"Kerberos 5 AS-REQ message"; krb5_msg_type:30; sid:3; rev:1;)
不过这个问题我已经解决了。
6.引擎的其他弱点 updated@221017
6.1.多规则关联场景
只显示最后命中的一条规则的攻击载荷,导致攻击载荷日志不完整。
6.2.爆破场景
可以检测爆破,但由于缺少判断登录是否成功的“标志位”,无法判断爆破成功。
6.3.爬虫/网站目录扫描行为
只是基于阈值统计,缺少记录的网站路径或代理并关联分析的能力。
7.文件上传类调试