分类 NDR 下的文章

在高层次上,Suricata 签名由三部分组成:

Action : 当流量符合规则时采取的行动

Header: 一个标题,描述主机、IP地址、端口、协议和流流量方向(传入或传出)

Options : 选项,指定诸如签名ID(sid)、日志信息、匹配数据包内容的正则表达式、分类类型,以及其他可以帮助缩小识别合法和可疑流量的修饰语

签名的一般结构如下:

ACTION HEADER OPTIONS

示例规则分析:

sid:2100498:

alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|";

签名的alert部分是ACTION,ip any -> any any部分是HEADER,签名的其余部分从(msg:GPL ATTACK_RESPONSE...)开始包含了规则的OPTIONS。

Actions

sid:2100498签名的第一部分是Actions,在这里是alert。Suricata签名的Actions部分指定了当数据包符合规则时要采取的动作。根据Suricata是在IDS还是IPS模式下运行,行动还可以是以下之一:

Pass - Suricata将停止扫描该数据包,并允许其通过,但不产生警报。
Drop - 当在IPS模式下工作时,Suricata将立即停止处理该数据包并产生警报。如果产生数据包的连接使用的是TCP,则会超时。
Reject - 当Suricata运行IPS模式时,将发送一个TCP重置包,Suricata将放弃匹配的数据包。
Alert - Suricata将生成一个警报,并将其记录下来以便进一步分析。

Headers

每个Suricata签名都有一个Headers部分,描述了网络协议、源和目的IP地址、端口和流量方向。参考示例 sid:2100498 签名,该规则的头部分是突出显示的ip any any -> any any 部分:

alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)

一条规则的标题部分的一般格式是:

->

PROTOCOL协议可以是以下之一:

TCP
UDP
ICMP
IP
其他一些应用协议

来源和目的地字段可以是IP地址或网络范围,或者是特殊值any,它将匹配所有的IP地址和网络。

箭头->表示流量的方向。

注意:签名也可以使用非方向性标记<>,它将匹配两个方向的流量。然而,Suricata关于方向性标记的文档指出,大多数规则将使用->右侧的匹配箭头。

如果你想对恶意的出站流量(即离开你的网络的流量)发出警报,那么源字段将是你的系统的IP地址或网络范围。目的地可以是一个远程系统的IP或网络,或特殊的任何值。

反过来说,如果你想对传入的恶意流量产生警报,源字段可以设置为任何,而目的地可以是你系统的IP地址或网络范围。

你还可以使用端口字段指定要检查的TCP或UDP端口。一般来说,来自一个系统的流量会被分配一个随机的端口,所以任何值对->指标的左边是合适的。如果你打算检查每个传入数据包的内容,目标端口也可以是任何,或者你可以限制一个签名,只扫描个别端口的数据包,如22用于SSH流量,或443用于HTTPS。

sid:2100498的ip any -> any any头是一个通用的头,将匹配所有的流量,无论协议、源或目标IP或端口。当你想确保入站和出站流量被检查出可疑的内容时,这种捕获所有的头是有用的。

请注意,源、目的和端口字段也可以使用特殊的 !否定操作符,它将处理与该字段值不匹配的流量。

例如,以下签名将使Suricata对所有来自任何网络的SSH数据包发出警报,这些数据包的目的地是你的网络(由203.0.113.0/24 IP块代表),而不是以22端口为目的地:

alert ssh any any -> 203.0.113.0/24 !22 (sid:1000000;)

这种警报并不那么有用,因为它不包含任何关于数据包的信息,也不包含分类类型。为了给警报添加额外的信息,以及根据更具体的标准进行匹配,Suricata规则有一个OPTIONS部分,你可以为一个签名指定一些额外的设置。

OPTIONS

在Suricata签名中的括号(...)内的参数包含各种选项和关键字修改器,你可以用它们来匹配数据包的特定部分,对规则进行分类,或记录自定义信息。规则的header参数是针对IP、端口和协议级别的数据包标题,而OPTIONS则是针对数据包中的数据进行匹配。

Suricata规则中的OPTIONS必须用分号隔开,并且通常使用key:value格式。有些选项没有任何设置,只需要在规则中指定名称。

使用上一节的签名示例,你可以添加msg选项(即触发规则后返回的提示信息),其值为在非SSH端口检测到的SSH流量,解释警报的内容:

alert ssh any any -> 203.0.113.0/24 !22 (msg:"SSH TRAFFIC on non-SSH port"; sid:1000000;)

关键字:Content

任何规则最重要的选项之一是Content内容关键词。回顾一下sid:2100498签名的例子:

alert ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)

突出显示的内容: "uid=0|28|root|29|";部分包含Content关键字,以及Suricata将在数据包内寻找的值。在这个签名示例中,来自任何端口的任何IP地址的所有数据包都将被检查,以确保它们不包含字符串值uid=0|28|root|29|(在以前的教程中,它被用作表示被攻击的主机的例子)

Content关键字可以与Suricata中的大多数其他关键字一起使用。你可以使用头文件的组合来创建非常具体的签名,以及针对特定应用协议的选项,然后使用正则表达式检查数据包内容的单个字节、字符串或匹配。

例如,下面的签名检查DNS流量,寻找任何内容为your_domain.com的数据包,并生成一个警报:

alert dns any any -> any any (msg:"DNS LOOKUP for your_domain.com"; dns.query; content:"your_domain.com"; nocase; sid:1000001;)

现在,小写或大写字母的任何组合仍将与内容关键词相匹配。

关键字msg

本教程中的签名示例都包含了带有签名信息的msg关键字。虽然msg选项不是必须的,但留空的话,在检查Suricata的日志时,就很难理解为什么会发生警报或删除动作。

msg选项的设计是对一个警报的可读文本描述。它应该是描述性的,并为警报添加上下文,以便您或其他正在分析日志的人理解为什么警报被触发。在本教程的reference Keyword部分,你将了解到参考选项,你可以用它来链接到关于签名和它所要检测的问题的更多信息。

关键字 sid 和 rev

每个Suricata签名都需要一个唯一的签名ID(sid)。如果两个规则具有相同的sid(在下面的输出示例中是sid:10000000),Suricata将不会启动,而会产生一个类似下面的错误:

Example Duplicate sid Error. . .
19/11/2021 -- 01:17:40 - - [ERRCODE: SC_ERR_DUPLICATE_SIG(176)] - Duplicate signature "drop ssh any any -> 127.0.0.0/8 !22 (msg:"blocked invalid ssh"; sid:10000000;)"
. . .

当你创建自己的签名时,1000000-1999999的范围被保留给自定义规则。Suricata的内置规则的范围是2200000-2299999。其他边框范围在新出现的威胁SID分配页面上有记录。

sid选项通常是Suricata规则的最后部分。然而,如果一个签名有多个版本,并随着时间的推移而变化,则有一个rev选项,用于指定规则的版本。例如,本教程早期的SSH警报可以改为只扫描2022端口的SSH流量:

alert ssh any any -> 203.0.113.0/24 2022 (msg:"SSH TRAFFIC on non-SSH port"; sid:1000000; rev:2;)

关键字reference

reference参考关键词在签名中用来描述在哪里可以找到更多关于规则所要检测的攻击或问题的信息。例如,如果一个签名是为了检测一种新的漏洞或攻击方法,参考字段可以用来链接到一个安全研究员或公司的网站,记录这个问题。

关键字classtype
Suricata可以根据一套预先配置好的类别对流量进行分类,这些类别在你用Linux发行版的软件包管理器安装Suricata软件包时就已经包含了。默认的分类文件通常在/etc/suricata/classification.config中找到,包含如下条目:

config classification:shortname,short description,priority

config classification: not-suspicious,Not Suspicious Traffic,3
config classification: unknown,Unknown Traffic,3
config classification: bad-unknown,Potentially Bad Traffic, 2

如文件头所示,每个分类条目有三个字段:

shortname:一个简短的、机器可读的名字,在上面的例子中分别是:not-suspicious、unknown和bad-unknown
short description:用于警报的分类描述,例如:Not Suspicious Traffic
priority:一个优先级字段,它决定了签名将被Suricata处理的顺序。最高的优先级是值1。当Suricata处理一个数据包时,使用更高优先级的分类器的签名将被首先检查。

关键字 target

Suricata签名中另一个有用的选项是target目标选项。它可以被设置为两个值之一:src_ip和dest_ip。这个选项的目的是为了在Suricata的警报日志中正确识别源主机和目标主机。

例如,本教程前面的SSH签名可以用target:dest_ip;选项来加强
alert ssh any any -> 203.0.113.0/24 2022 (msg:"SSH TRAFFIC on non-SSH port"; target:dest_ip; sid:1000000; rev:3;)

alert tcp $EXTERNAL_NET any -> 10.200.0.0/24 80 (msg:"WEB-IIS CodeRed v2 root.exe access"; flow:to_server,established; uricontent:"/root.exe"; nocase; classtype:web application-attack; reference:url,www.cert.org/advisories/CA-2001 19.html; sid:1255; rev:7;)

alert:告诉Suricata将此行为作为警报报告(在为STA创建的规则中是强制性的)。

tcp: 表示此规则只适用于TCP的流量。

$EXTERNAL_NET:这是在Suricata中定义的一个变量。

默认情况下,变量HOME_NET被定义为这些范围内的任何IP:192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,而EXTERNAL_NET则定义为这些范围之外的任何IP。

你可以通过指定单个IP如10.200.0.0、IP CIDR范围如192.168.0.0/16或IP列表如[192.168.0.0/16,10.0.0.8]来指定IP地址。请注意,列表中的空格是不允许的。

any:在这种情况下,它意味着 "来自任何源端口",然后有一个箭头'->',意味着 "连接到"(没有'<-'操作符,但你可以简单地翻转操作符周围的参数。你可以使用'<>'操作符来表示连接方向与此规则无关),然后是一个IP范围,表示目标IP地址,然后是端口。你可以用冒号来表示一个端口范围,比如0:1024表示0-1024。在圆括号中,有一些指令用于设置警报信息、关于规则的元数据,以及额外的检查。

msg: 是一个指令,它简单地设置了在检测到匹配流量的情况下将发送的信息(在STA情况下发送到Coralogix)。

flow: 是一个指令,表示我们即将定义为签名的内容是否需要出现在与服务器("to_server")或与客户("to_client")的通信中。这可能非常有用,例如,如果我们想检测服务器的响应,该项可表明它已被攻破。

established: 是一个指令,它将导致Suricata限制其搜索匹配此签名的数据包,只搜索属于已建立连接的数据包。这对于尽量减少Suricata的负载是很有用的。

uricontent: 是一个指令,指示Suricata在规范化的HTTP URI内容中寻找某个文本。在这个例子中,我们要寻找的url正是"/root.exe "这样的文本。

nocase:是一个指令,表示我们希望Suricata进行不区分大小写的搜索。

classtype:是一个指令,它是一个元数据属性,表明该规则检测的活动类型。

reference:是一个指令,是一个元数据属性,链接到另一个系统以获取更多信息。在我们的例子中,值url,https://....链接到互联网上的一个URL。

sid: 是一个指令,是一个元数据属性,表示签名的ID。如果你正在创建你自己的签名(即使你只是替换一个内置的规则),请使用一个高于9,000,000的值,以防止与另一个预先存在的规则发生碰撞。

rev: 是一个指令,表示规则的版本。

一、部署PF_RING

step1:安装依赖
[root@localhost ~]# yum install -y flex bison kernel-devel kernel-headers gcc gcc-c++ make wget
[root@localhost ~]# git clone https://github.com/ntop/PF_RING.git
[root@localhost ~]# cd PF_RING/
[root@localhost PF_RING]# make
[root@localhost PF_RING]# cd kernel
[root@localhost kernel]# make
[root@localhost kernel]# make install
stpe2:加载模块
[root@localhost kernel]# insmod pf_ring.ko
[root@localhost kernel]# cd ../userland/lib
[root@localhost lib]# ./configure
[root@localhost lib]# make
[root@localhost lib]# make install
[root@localhost lib]# cd ../libpcap
[root@localhost libpcap]# ./configure
[root@localhost libpcap]#
[root@localhost libpcap]# make install
stpe3:验证
[root@localhost libpcap]# cd ../examples
[root@localhost examples]# make
[root@localhost examples]# ./pfcount -i ens33
step4:检查模块
[root@localhost examples]# modinfo pf_ring

二、部署hyperscan
step1:安装LuaJIT
[root@NIDS ~]# wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
[root@NIDS ~]# tar zxvf LuaJIT-2.0.4.tar.gz
[root@NIDS ~]# cd LuaJIT-2.0.4
[root@NIDS LuaJIT-2.0.4]# make
[root@NIDS LuaJIT-2.0.4]# make install
step2:安装依赖
[root@NIDS]# yum install -y libpcap zlib libyaml libpcap-devel jansson-devel pcre-devel lua-devel libmaxminddb-devel epel-release libnetfilter_queue-devel nss-devel libyaml-devel zlib-devel luajit-devel rustc cargo
[root@NIDS ~]# yum install -y rustc cargo
step3:安装hyperscan
[root@NIDS ~]# yum install cmake ragel libtool python-devel GyeoIP-devel -y
[root@NIDS ~]# yum install boost boost-devel boost-doc -y
[root@NIDS ~]# yum install libquadmath libquadmath-devel bzip2-devel -y
[root@NIDS ~]# wget https://jaist.dl.sourceforge.net/project/boost/boost/1.76.0/boost_1_76_0.tar.gz
[root@NIDS ~]# tar zxvf boost_1_76_0.tar.gz
[root@NIDS ~]# cd boost_1_76_0
[root@NIDS boost_1_76_0]# ./bootstrap.sh --prefix=/tmp/boots-1.76
[root@NIDS boost_1_76_0]# ./b2 install
[root@NIDS ~]# git clone https://github.com/intel/hyperscan.git
[root@NIDS ~]# mkdir build
[root@NIDS ~]# cd build/
[root@NIDS build]# cmake -DBUILD_STATIC_AND_SHARED=1 -DBOOST_ROOT=/tmp/boots-1.76 ../hyperscan
[root@NIDS build]# make
[root@NIDS build]# make install
[root@NIDS build]# vim /etc/ld.so.conf
增加
/usr/local/lib64
[root@NIDS build]# ldconfig
step4:安装suricata

[root@NIDS ~]# wget https://www.openinfosecfoundation.org/download/suricata-6.0.15.tar.gz
[root@NIDS ~]# tar zxvf suricata-6.0.15.tar.gz
[root@NIDS ~]# cd suricata-6.0.15

[root@NIDS suricata-6.0.15]# LIBS="-lrt" ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-pfring --with-libpfring-includes=/usr/local/pfring/include --with-libpfring-libraries=/usr/local/pfring/lib --enable-geoip --enable-luajit --with-libluajit-includes=/usr/local/include/luajit-2.0/ --with-libluajit-libraries=/usr/local/lib/ --with-libhs-includes=/usr/local/include/hs/ --with-libhs-libraries=/usr/local/lib/ --enable-profiling --enable-nfqueue

[root@NIDS suricata-6.0.15]# make
[root@NIDS suricata-6.0.15]# make install
[root@NIDS suricata-6.0.15]# ldconfig
[root@NIDS suricata-6.0.15]# make install-conf
[root@NIDS suricata-6.0.15]# vim /etc/ld.so.conf
增加一行
/usr/local/lib
[root@NIDS suricata-6.0.15]# ldconfig

安装规则文件
[root@NIDS ~]# yum install -y python3-pip
[root@NIDS ~]# python3 -m pip install --upgrade suricata-update
[root@NIDS ~]# suricata-update
[root@NIDS suricata-6.0.15]# make install-rules
[root@NIDS ~]# suricata --build-info
以PF_RING模式运行
[root@NIDS suricata-6.0.15]# suricata --pfring-int=ens33 --pfring-cluster-id=99 --pfring-cluster-type=cluster_flow -c /etc/suricata/suricata.yaml
[root@NIDS ~]# cat /proc/net/pf_ring/info