检测Linux二进制文件污染

概述

二进制污染是篡改系统命令并用恶意版本替换它。这可以是全面替换为一个新文件,设计成像旧命令一样运行,或者篡改原地可执行文件,使其直接运行恶意代码。

如果一个毫不知情的用户运行了一个被污染的命令,就是以该用户身份运行攻击者想要执行的代码。

简单污染示例

下面的shell模拟污染/bin/ls

注意:不要在生成环境中进行下面的实验操作!!!
注意:不要在生成环境中进行下面的实验操作!!!
注意:不要在生成环境中进行下面的实验操作!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# root @ ubuntu in ~/tmp [16:09:03]
$ cat poison_test.sh
#!/usr/bin/env bash
# Linux binary poisoning example.
# Based on backdoorme poison script.

echo "Poisoning ls command."
echo "Making backup of ls to /bin/ls.bak"
if [ ! -f /bin/ls.bak ]; then
cp /bin/ls /bin/ls.bak
fi

echo "Making /bin/.bin to hold original binary"
mkdir /bin/.bin
echo "Moving original binary to /bin/.bin"
mv /bin/ls /bin/.bin/

echo "Creating poisoned ls script in /bin"
echo "#!/bin/bash" > /bin/ls
echo "( ls & ) > /dev/null 2>&1 && /bin/.bin/ls \$@" >> /bin/ls
echo "echo \"POISONED /bin/ls active!\"" >> /bin/ls
chmod +x /bin/ls

echo "Done"
# root @ ubuntu in ~/tmp [16:09:11]
$ bash ./poison_test.sh
Poisoning ls command.
Making backup of ls to /bin/ls.bak
Making /bin/.bin to hold original binary
Moving original binary to /bin/.bin
Creating poisoned ls script in /bin
Done

当然上面是写了无害的echo \"POISONED /bin/ls active!\" ,我们可以做任何shell可以做的操作,添加crontab,往authorized_keys添加公钥,下载木马等等。

可以看到ls已经被我们污染了

1
2
3
4
5
6
7
8
$ ls /tmp/
systemd-private-eac9d075027e4c038c766b9a8b7d0834-apache2.service-O1DAvq
systemd-private-eac9d075027e4c038c766b9a8b7d0834-colord.service-txti0P
systemd-private-eac9d075027e4c038c766b9a8b7d0834-ModemManager.service-CUXkDr
systemd-private-eac9d075027e4c038c766b9a8b7d0834-rtkit-daemon.service-EkyD2v
systemd-private-eac9d075027e4c038c766b9a8b7d0834-systemd-resolved.service-bRmKdM
systemd-private-eac9d075027e4c038c766b9a8b7d0834-systemd-timesyncd.service-pcKTtw
POISONED /bin/ls active!

在Linux上手动查找被感染的命令

如果手动去寻找,非常耗时,且很难下手。在Ubuntu系统中,仅在/bin和/sbin目录下就有500多个命令。如果再加上/usr/bin和/usr/sbin目录,那就有数千个命令了。因此,首先要尝试的是运行软件包验证来加快这个过程。

假如是Redhat based的系统,可以执行rpm -Va | grep ^..5.

假如是Debian/Ubuntu based的系统,可以apt安装debsums,执行debsums -c

下面我以Ubuntu为例,可以看到,debsums 很快发现了/bin/ls不对劲

1
2
3
# root @ ubuntu in ~ [16:11:56]
$ debsums -c
/bin/ls

假如上面debsums 没有发现任何内容,接下来我们需要手动操作,查找不是ELF的可执行文件,当然攻击者可以用另一个编译好的二进制文件替换一个二进制文件。但是替换shell是最容易实现的

比如针对/bin目录: file /bin/* | grep -v ELF | grep -v link, grep -v link是忽略掉软链接文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ file /bin/* | grep -v ELF | grep -v link
/bin/bzdiff: POSIX shell script, ASCII text executable
/bin/bzexe: POSIX shell script, ASCII text executable
/bin/bzgrep: POSIX shell script, ASCII text executable
/bin/bzmore: POSIX shell script, ASCII text executable
/bin/egrep: POSIX shell script, ASCII text executable
/bin/fgrep: POSIX shell script, ASCII text executable
/bin/gunzip: POSIX shell script, ASCII text executable
/bin/gzexe: POSIX shell script, ASCII text executable
/bin/lesspipe: POSIX shell script, ASCII text executable
/bin/ls: Bourne-Again shell script, ASCII text executable
/bin/red: POSIX shell script, ASCII text executable
/bin/setupcon: POSIX shell script, UTF-8 Unicode text executable
/bin/uncompress: POSIX shell script, ASCII text executable
/bin/unicode_start: POSIX shell script, ASCII text executable
/bin/which: POSIX shell script, ASCII text executable
/bin/zcat: POSIX shell script, ASCII text executable
/bin/zcmp: POSIX shell script, ASCII text executable
/bin/zdiff: POSIX shell script, ASCII text executable
/bin/zegrep: POSIX shell script, ASCII text executable
/bin/zfgrep: POSIX shell script, ASCII text executable
/bin/zforce: POSIX shell script, ASCII text executable
/bin/zgrep: POSIX shell script, ASCII text executable
/bin/zless: POSIX shell script, ASCII text executable
/bin/zmore: POSIX shell script, ASCII text executable
/bin/znew: POSIX shell script, ASCII text executable

我们可以看到这里也有/bin/ls,而且还是个Bourne-Again shell script,这就很有问题了。

如果你怀疑某个命令可能被篡改,请直接使用strings命令查看是否有任何可疑内容。不要对你认为可能是恶意文件的任何文件运行strace命令。我们将这一点用粗体标出,因为有些人可能想尝试strace命令,但实际上运行strace会在主机上运行实际的可执行文件,这是一个非常糟糕的想法。

1
2
3
4
$ strings /bin/ls
#!/bin/bash
( ls & ) > /dev/null 2>&1 && /bin/.bin/ls $@
echo "POISONED /bin/ls active!"

可以看到这里还有隐藏目录/bin/.bin/

最后我们用rm -rf /bin/.bin/ && mv /bin/ls.bak /bin/ls来恢复ls

参考

https://sandflysecurity.com/blog/detecting-linux-binary-file-poisoning/

打赏专区