Linux Shell命令审计

  1. 一种简单的bash审计方法
    1. 交互式bash记录命令
    2. 非交互式bash记录命令
    3. 白名单

一种简单的bash审计方法

在高交互蜜罐环境中,ssh服务允许攻击者成功由ssh登录并获取到一个可进行各种操作的真实shell,同时需要记录shell中所有操作。严谨的方案是在bash源码及内核模块中做审计记录。这里给出另一种娱乐性质的方案,简单而tricky的方式达成该目标的基本功能,当然这种方案在了解的人面前很容易被绕过。

本文参考环境为Ubuntu 18.01

这里记录shell执行命令的核心是bash内建的trap命令,trap可以看作bash的信号处理,同时有一些虚拟信号,这里要使用的是DEBUG信号。trap arg DEBUG执行后,arg命令将在每一个命令执行前被执行,同时可以从变量BASH_COMMAND中读取到将要执行的命令。参考man trapman bash

交互式bash记录命令

先看一下例子,log_command中可以替换为其他脚本,将记录到的命令发送到远程服务器并保存。这里仅简单保存日志文件。

function log_command()
{
	echo -e "\e[33m$(date +"%Y-%m-%d %H:%M:%S")\e[0m" ["\e[01;35m`whoami`\e[0m""@""\e[01;36m$(who am i | awk "{print \$2\"\"\$5}")\e[0m":"\e[01;32m`pwd`\e[0m"]# $BASH_COMMAND >> /var/log/history.log
}

unset PROMPT_COMMAND

trap 'log_command' DEBUG

试验一下

[root@GuangZhou:sbin]# source /usr/local/sbin/cli.sh 
[root@GuangZhou:sbin]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Apr04 ?        00:12:43 /sbin/init
root         2     0  0 Apr04 ?        00:00:00 [kthreadd]
root         4     2  0 Apr04 ?        00:00:00 [kworker/0:0H]
root         6     2  0 Apr04 ?        00:00:00 [mm_percpu_wq]
root         7     2  0 Apr04 ?        00:01:51 [ksoftirqd/0]
root         8     2  0 Apr04 ?        00:01:57 [rcu_sched

看看输出

[root@GuangZhou:sbin]# tail -n2 /var/log/history.log 
2021-05-10 17:16:27 [root@pts/0(192.168.21.254):/usr/local/sbin]# ps -ef
2021-05-10 17:16:59 [root@pts/0(192.168.21.254):/usr/local/sbin]# tail -n2 /var/log/history.log

为了让每个bash都能生效,在/etc/bashrc文件末尾增加一行. /etc/bash_logger.sh,这样在默认配置下每一个交互式bash都会加载新增的文件(除非通过参数指定bash不加载配置文件)。

非交互式bash记录命令

上一个例子里可以记录到交互式bash中调用的命令,那么再试一下通过bash执行的脚本文件是否可以记录到脚本文件内调用的命令,结果是无法记录。因为trap只能影响到当前bash,通过bash SCRIPT_NAMEbash -c COMMAND会启动一个子进程,执行非交互式bash,不会加载之前准备的配置文件。

之前说过非交互式bash会检查环境变量BASH_ENV并尝试加载其指定的文件。因此在配置文件中再增加BASH_ENV环境变量。

function log_command()
{
	echo -e "\e[33m$(date +"%Y-%m-%d %H:%M:%S")\e[0m" ["\e[01;35m`whoami`\e[0m""@""\e[01;36m$(who am i | awk "{print \$2\"\"\$5}")\e[0m":"\e[01;32m`pwd`\e[0m"]# $BASH_COMMAND >> /var/log/history.log
}

    unset PROMPT_COMMAND
    export BASH_ENV=/usr/local/sbin/cli.sh


trap 'log_command' DEBUG

重启一个bash,验证一下

[root@GuangZhou:~]# cat test.sh 
echo 1
echo 2
[root@GuangZhou:~]# bash test.sh 
1
2
[root@GuangZhou:~]# 

看看日志

2021-05-10 17:20:14 [root@pts/0(192.168.21.254):/root]# bash test.sh
2021-05-10 17:20:14 [root@pts/0(192.168.21.254):/root]# echo 1
2021-05-10 17:20:14 [root@pts/0(192.168.21.254):/root]# echo 2
2021-05-10 17:20:36 [root@pts/0(192.168.21.254):/root]# cat /var/log/history.log

可以看到没有函数内部的调用记录。想要这部分记录也很简单,在配置文件中增加一行set -o functrace,参考man setman bash

白名单

经过上面的步骤,已经可以记录bash和sh调用的所有命令了,但是由于linux中大量使用shell做一些辅助工作,因此很多时候会有大量冗余的调用记录。比如执行一下man bash,就会在日志文件中看到数十行调用记录,这里可以通过增加白名单的方式把明显无害的调用排除出记录范围。


转载请注明来源