目前有两种主流威胁检测技术:基于签名的检测和基于异常的检测。
- 使用基于签名的IDS,可以搜索一直恶意流量的规则和模式。一旦找到与签名相匹配的项,就会告警。例如snort和suricata
- 使用基于异常的IDS,也即是基于行为的IDS,依赖于基线而不是签名,。它将搜索偏离先前活动或先前看到的活动的平均值。例如,如果用户总是从加利福尼亚登录网络,如果发现在一个用户从印度登录网络,则是一个危险的信号。例如Zeek(基于签名和异常的双重IDS)
基于签名的检测会发生较少的误报,但只是标记已知的威胁,基于异常可能会出现更多误报,但如果配置正确,则会捕获到未知的威胁。
1 suricata和snort区别
Suricata是一个高性能的网络IDS、IPS和网络安全监控引擎。
- 多线程-snort以单线程运行,意味着只能使用一个CPU。Suricata可以多线程运行,更能充分利用CPU
- 内置硬件加速
- 文件提取-直接从suricata捕获的流量中获取文件
- LuaJIT-一个脚本检测引擎,可以与suricata一起使用
- 不仅仅记录数据包-suricata可以抓取和记录例如证书,http请求,DNS请求之类的
2 Suricata概述
官方网站:https://suricata.readthedocs.io/en/latest/index.html
3 Suricata规则
包括:
- 规则头
- 动作
- 协议
- IP地址和端口号
- 方向操作符
- 规则选项
3.1 规则头
3.1.1 规则动作
- alert – 告警
- pass – 停止进一步检查数据包
- drop – 丢弃数据包并生成劲警报
- reject – 向匹配数据包的发送方发送 RST/ICMP 未到达错误
- rejectsrc – 同reject
- rejectdst – 向匹配数据包的接收方发送 RST/ICMP 未到达错误
- rejectboth – 向对话双方发送 RST/ICMP 未到达错误
3.1.2 协议
基本协议:
- tcp
- udp
- ip
- icmp
应用层协议:
- http
- ftp
- tls (this includes ssl)
- smb
- dns
- dcerpc
- ssh
- smtp
- imap
- modbus (disabled by default)
- dnp3 (disabled by default)
- enip (disabled by default)
- nfs
- ike
- krb5
- ntp
- dhcp
- rfb
- rdp
- snmp
- tftp
- sip
- http2
3.1.3 来源、目的和端口
Operator | Description |
---|---|
../.. | 范围 例如 10.0.0.0/24 |
! | 不包括 例如 !1.1.1.1 不包括这个ip |
[.., ..] | 分组 |
端口
Operator | Description |
---|---|
: | 端口范围 [80:83] 80-83端口 |
! | 不包括 !80 不包括80端口 |
[.., ..] | 分组 [80,81,82]三个端口 |
3.2 规则选项
msg – 在报警和包日志中打印一个消息 | 告诉记录和报警引擎,记录或报警一个包的内容的同时打印的消息。格式是msg:””; |
sid – 规则id | 例如 sid:123 |
rev – 规则版本 | 例如 rev:123 |
gid – 提供另一个id | 默认为1 |
classtype – 提供有关规则和警报分类的信息 | 由短名称,长名称和优先级组成。例如:classtype:trojan-activity |
reference – 引用 | reference:type,reference 例如 reference:url,www.info.com |
priority – 优先级,从1-255,常用1-4,优先级较高首先被检查 | 例如:priority:1 |
metadata – 元数据 将附加的非功能信息添加到签名中 | 格式:metadata:type value,type value |
target – 指定哪一册是攻击目标 | 格式:target:[src_ip|dest_ip] |
ttl – 用于检查数据包标头中的特定 IP 生存时间值 | 格式:ttl:<number> 例如:ttl:10 |
ipopts – 用于检查是否设置了特定的IP选项 | 格式:ipopts:<name> 例如:ipopts:lsrr |
sameip – 用于检查源IP和目的IP是否相同 | 格式:sameip |
ip_proto – 匹配包头中的IP协议 | 可以匹配 ICMP TCP UDP GRE ESP AH IPv6-ICMP |
ipv4.hdr – 在整个IPv4头上匹配缓冲区 | 例如:alert ip any any -> any any ( ipv4.hdr; content:”|3A|”; offset:9; depth:1; sid:1234; rev:5;) |
ipv6.hdr – 在整个IPv6头上匹配缓冲区 | |
ID – 可以匹配特定的 IP ID 值 | 每个数据包都有一个IP ID,当数据包被分片时,这些数据包都具有相同ID,格式:id:<number> 例如:id:1 |
geoip – 匹配物理地址,并查看国家地区 | geoip:src,RU geoip:dst,CN,RU,IR geoip:both,CN,RU geoip:any,CN,IR |
fragbits – 可以检查 IP 标头中是否设置了分片和保留位 | 格式:fragbits:[*+!]<MDR> M (最大分片) D(不分片) R(保留位) +(匹配指定位和其他位) *(匹配设置的指定位) !(匹配没有设置的指定位) |
fragoffset – 匹配 IP 片段偏移字段的特定十进制值 | 格式:fragoffset:[!|<|>]<number> <(匹配小于指定的值) >(匹配大于指定的值) !(匹配不等于指定的值) |
tos – 匹配 IP 标头 TOS 字段的特定十进制值 0-255 | 格式:tos:[!]<number> 例如:tos:8 |
seq – 检测特定的TCP序列号seq | 例如:seq:0 |
ack – 检测特定的ack | 例如:acl:1 |
window – 检测特定的TCP窗口大小 | 格式:window:[!]<number> |
tcp.mss – 匹配TCP MSS值 | 格式:tcp.mss:<min>-<max> tcp.mss:[<|>]<number> tcp.mss:<value> |
tcp.hdr – 在整个TCP标头匹配Sticky buffer | |
udp.hdr – 在整个UDP标头上匹配Sticky buffer | |
itype – 用于匹配特定的 ICMP 类型 | ICMP 有多种消息,并使用代码来阐明这些消息。不同的消息因名称不同而不同,但更重要的是数字值。格式:itype:min<>max itype:[<|>]<number> 在官网找到数字代表的含义 |
icode – 匹配特定的ICMP代码 | 格式:icode:min<>max icode:[<|>]<number> 在官网找到数字代表的含义 |
icmp_id – 匹配特定的ICMP id值 | 每个 ICMP 数据包在发送时都会获得一个 ID。在接收方收到数据包的那一刻,它将使用相同的 id 发送回复,以便发送方识别它并将其与正确的 ICMP 请求连接。格式:icmp_id:<number> |
icmp_seq – 检查ICMP序列号 | ICMP 消息都有序列号。这对于检查哪个回复消息属于哪个请求消息很有用(与 id 一起)。格式:icmp_sql:<number> |
icmpv4.hdr – 在整个 ICMPv4 标头匹配Sticky buffer | |
icmpv6.hdr – 在整个 ICMPv6 标头匹配Sticky buffer | |
imcpv6.mtu – 匹配 ICMPv6 MTU 可选值。如果 MTU 不存在,则不匹配 | 格式:icmpv6_mtu:<min>-<max> icmpv6_mtu:[<|>]<number> icmpv6_mtu:<value> |
content – 匹配的内容,区分大小写 | 十六进制:|00|表示,例如匹配“;”,则可以使用|3B| |
nocase – 不区分大小写 | 例如:content:”abc”;nocase |
depth – 深度检测, | 例如:depth:12, |
startswith – 以…开始,必须跟在一个content之后 | content:“GET|20|”; startswith; |
endswith – 以…结束,必须跟在一个content之后 | content:“.php”; endswith; |
offset – 指定将检查有效负载中的哪个字节以找到匹配项 | content:“def”; offset:3; depth:3; |
distance – 它表示此内容关键字与其前面的内容之间的关系 |
within – 之内,是相对于前面的匹配 | 确保只有在内容与设定字节数内的有效负载匹配时才会匹配 |
isdataat – 查看有效负载的特定部分是否仍有数据 | isdataat:512; |
bsize – 匹配缓冲区的长度 | bsize:<number> |
dsize – 匹配数据包有效负载的大小 | dsize:<number>; |