原文:《Incident Response
Tools For Unix, Part Two: File-System Tools》
这是关于应急响应工具介绍的三个系列文章中的第二部分。第一部分聚焦在系统工具上,本部分将主要讨论文件系统工具,下一部分则主要是网络工具和其他工具。这三部分都是基于 OpenBSD 3.2, Debian GNU/Linux 3.0 (woody), RedHat 8.0 (psyche), and Solaris 9 (aka Solaris 2.9 or SunOS 5.9)的。这些工具都是系统中比较通用的工具,除了少部分外。如果某个工具在操作系统中不存在,那么在文章的参考部分中应该可以找到相关信息。
文章中的这些工具都执行在用户空间。如果攻击者安装一些核心模块,或者root-kit来替换系统上的二进制文件,那么这些工具就可能不会很准确。这就是将数据离线在安全的系统中分析的一个原因。除非这些数据能够确认是可信的,否则绝对不能信任它们。介绍多个工具来做相类似的事情,可以在响应事件的时候有更多选择。
必须强调的是,这些工具都应该仅仅在只读介质中执行,或者一个安全的系统中用来作离线分析。使用只读介质可以确认这些工具不能被更改。
在应对事件的时候,安全人员应该首先知道的是,他们优先捕获纪录的是哪些数据。这些数据是存在被更改的趋势的。应急响应队伍需要讨论处理的优先级,是否需要让机器离线,还是应该先作好系统的镜像,或者捕获那些活动数据,比如当前的进程、建立的网络连接,内存分配和使用情况,用户登录情况。在事件发生后,系统在线的时间越长,那么,从(远程的、本地)攻击者或者系统造成破坏的威胁就更大。
通过法律的介入可以来检验安全队伍的事件处理过程是否符合必要的法律取证。类似HTCIA(US)和NHTCU(UK)这样的组织能够帮助处理技术专家同应对计算机犯罪进行取证的法律官员之间的联系。
第一部分文章中最后找到了密码破解工具,John the Ripper,在本文,我们将利用文件系统工具来继续去挖掘信息来揭露这个是怎么被入侵的。
Sum packages need to be checked
攻击者是在03:17开始破解密码的,现在从03:17开始进行搜索,但是这个时间并不是攻击者闯入的时间。攻击者通常使用一些自动化的程序来扫描和攻击有漏洞的系统,这就意味着攻击者使用的工具通常会在一些时间之前就留下了一些痕迹。
现在深入到一些可以帮助我们来检测文件系统的改变的工具。一些工具在系统中默认存在的,而一些需要另外指定安装或者是一些第三方的工具。
在Solaris和Linux上,有一些自身存在的命令来比较当前系统安装的包。命令是: rpm -Vva(RH8.0),pkgchk -vn(Solaris 9),和debsums -ac(Deb3.0)。rpm和debian格式化都能用RFC2440 (OpenPGP)来根据签名验证这些包。也可以用MD5来作为校验和。在Solaris系统上,pkgchk用SystemV(SYSV)算法来验证二进制是否被篡改。SYSV运算法则可以检测出只改变文件内容而不改变文件长度的变化。然而,不可能根据SYSV算法来进行完整性检查。它只是更多地依赖于文件大小和时间戳。用惯了十六进制编辑器和touch命令的人都知道改变文件内容而不改变文件大小,以及改变文件的时间戳,这些操作是多么的容易。在Debian GNU/Linux,可以指定一套包来进行对比检查。如果在/mnt上装载了一套只读的包 ,可以通过这个命令来检查包文件:debsums -cagp /mnt/* 。这相当于rpm命令:rpm -Vvp /mnt/Redhat/RPMS/*.rpm 。用rpm -Vva --dbpath <some_path> 可以来验证备用数据库。在Debian系统上相似的命令是: debsums -cagd <some_path>。这些数据库应该保存在只读介质上并且来自可信系统。如果你想获得rpm的详细数量,可以加上参数-v。这些命令可以帮助检查攻击者做的一些改变。
package tools verifying current file system state against package metadata:
{redhat80} $ rpm -vVa
[ snip lots of output ]
..5....T /bin/ls
[ snip lots of output ]
{solaris9} $ pkgchk -vn
[ snip lots of output ]
ERROR: /usr/bin/ls
modtime <04/06/02 10:54:41 PM> expected <09/08/03 01:04:01 AM> actual
file cksum <63074> expected <63042> actual
/usr/bin/ls
[ snip lots of output ]
{debian30} $ debsums -ac
[ snip lots of output ]
bin/ls
[ snip lots of output ]
比较当前的系统上的安装的包的数据库有很多帮助,但是,如果系统被高度自定义过了,打包系统和当前的文件系统上的metadata可能是完全不同的。所以用包工具来比较当前文件系统状态和程序包数据库可能不会得到期望的结果。OpenBSD上有一个工具叫mtree,它可以用hash函数[5]来确信文件系统上的文件从上次数据库更新起是否被改变过。如果攻击者附加或者修改已经在mtree的数据库中存储了hash的文件,那么这些改变就可以被mtree检测出来。另外一些第三方的工具也有类似功能,比如:AIDE, integrit, Osiris和tripwire。另外一些工具,比如:changedfiles, dnotify, 和FAM用核心模块,或者监控查询文件系统来检测文件改变,这些工具可以比文件系统完整性检测工具更快地得到文件改变的通知。这是因为文件系统完整性检查工具是通过周期性地用hash函数来检测的。当然,所有这些工具都应该在被入侵之前先安装配置好。
如果上面这些工具还没有安装配置,或者需要进行进一步的挖掘,这里还有一些其它工具可以用到。这些工具通常可以用在文件上,在Solaris系统,也可以用于目录。当然,这需要拥有一个可信系统,在其上运行相同的工具,来比较两者的运行结果,这些工具才是有用的。如果信任 The Shmoo Group(http://www.shmoo.com/),那么就可以参考这里的 Known Goods(http://www.knowngoods.org/)数据库来查询hash和文件大小。 md5sum工具可以在Linux系统上进行MD5 hash的计算。在OpenBSD上,类似的工具是md5,OpenBSD也有基于SHA1和RIPEMD 160 hash算法功能的工具:sha1和rmd160 。命令openssl可以利用OpenSSL库来进行hash计算。 openssl dgst <some_file> 默认使用MD5算法。用openssl dgst -?可以察看这个命令的使用方法以及提供的不同hash算法。实际上,执行命令的时候可以不需要'dgst'符号。比如,如果用MD5对文件来进行hash,可以执行 openssl md5 <filename>。 另外一个工具:shash [8]可以用前面提到的hash算法来进行校验(详见 shash -l),它也可以用一对另外的算法来计算校验和。
那些不是通过hash函数来进行校验和的命令,则并不应该使用在应急响应中。比如命令chsum和sum。校验和(checksum)算法(CRC*, BSD和SYSV)不能到达hash函数所能提供的断言等级。事实上也是这样,checksum算法根本不能在取证中值得信任。checksum算法主要用于检测数据传输和存储中是否发生错误,而不是用于保护和警报数据被恶意攻击者修改。很容易可以找到多种数据的组合,而有相同的校验和。即使先得到数据的checksum,并且把checksum和它们的数据都存储在只读介质中,可以确保这些数据不会被修改,而应对的策略则是可以创建另一些数据,并且有相同的checksum,这种应对办法导致的结果就是这些数据会被怀疑,但是checksum并没有提供足够的断言:这些数据是被篡改了。依赖checksum算法要匹配的复杂度是很小的,而基于MD5算法的复杂度是2^128,SHA1则是2^160。对于MD5和SHA1算法,是很难找到两组数据能够产生相同的hash值。checksum算法可以对付数据的意外干扰,而不是对付恶意攻击的。这就是为什么使用基于hash函数如MD5或SHA1的必须的。
Hash/Checksum tools in action:
{deb30} $ md5sum /bin/ls
a5c720b6776331b9695d9a1f4f5c2194 /bin/ls
{deb30} $ openssl dgst /bin/ls
MD5(/bin/ls)= a5c720b6776331b9695d9a1f4f5c2194
{deb30} $ shash /bin/ls
# MD5 HASH
a5c720b6776331b9695d9a1f4f5c2194 /bin/ls
{deb30} $ cksum /bin/ls
2890986056 43784 /bin/ls
{deb30} $ sum -r /bin/ls
56701 43
{deb30} $ sum -s /bin/ls
6968 86 /bin/ls
Hey MAC, what time ya got?
UNIX或者类UNIX文件系统存储一套时间戳元数据,这些时间戳包括modify、access和change时间,即MAC时间。这些时间戳都保存在文件系统索引节点(inode)结构中。除了这些时间戳外,inode也包含其他的文件信息,比如:文件类型、许可、所属、组、大小、硬连接数,以及文件占用的数据块。目录也有它们自己的inode,这包括目录下的文件名,以及包含文件信息的inode数量。
mtime (modify time)反映的是文件数据最后被修改的时间,系统调用比如write, trucate, mknod 都会改变mtime。 ctime(change time)反映的是文件的inode结构最后被改变的时间,atime(access time)反映的是文件数据最后被访问的时间。当系统调用execve, read, mknode, utime, pipe等都会修改atime。你可以在stat(2)的帮助中找到更多关于mtime, atime, ctime的细节。
要改变MAC时间有多种不同的命令和不同的方法。下面的表格现实了一些普通命令对MAC时间的作用。这些表是基于使用ext2文件系统的Debian3.0,其中包含加载在loopback设备上的flat file。如果在LINUX系统的loopback设备上加载许多镜像,可以在引导程序中设置max_loop = 255,来在启动前传递给系统核心。那么就可以加载255个镜像,而不是默认限制的8个。一旦文件系统加载到loopback设备上,就可以用debugfs检查。建议在你自己的系统上对下面表格中的内容进行试验[9]验证。下面表中基本是可以通用的。
(译注:因为文本的排版问题,可参考原文的表格)
How common commands change MACtimes for a directory (foo):
Action atime ctime mtime
creation (mkdir foo) X X X
directory move (mv foo bar) X X
file creation (touch foo/foo) X X
file creation (dd if=/dev/zero of=foo/foo count=1) X X
list directory (ls foo) X
change directory (cd foo)
file test (-f foo)
file move/rename (mv foo foo_mvd) X X
permissions change (chmod/chown <some_perm> foo) X
file copy (mv foo_mvd foo) X X
file edit (vim foo) X X
file edit (emacs foo) X X X
file edit (nvi/nano foo)
How common commands change MACtimes for a file (f1):
Action atime ctime mtime
creation (touch foo) X X X
creation (dd if=/dev/zero of=foo count=1) X X X
rename (mv foo bar)
permissions change (chmod <some_perm> foo) X
copy (cp foo bar) X
copy overwrite (cp bar foo) X X
append (cat >> foo) X X
overwrite (cat > foo) X X
truncate (cp /dev/null foo) X X
list file (ls foo)
edit (vim/emacs/xemacs/joe/jed foo) X X X
edit (ed/nvi/vi (sun)/vi (obsd)/nano/pico foo) X1 X1 X1
1 - all times changed, but atime is slightly older than mtime and ctime
ls命令可以用来现实文件的MAC时间,下表显示的是多个ls命令,来按最后修改时间的排序列举。
displaying MACtimes using ls:
Linux (ls from GNU fileutils) OpenBSD Solaris
mtime ls -latr --full-time ls -latTr ls -latr
atime ls -laur --full-time ls -lauTr ls -laur
ctime ls -lacr --full-time ls -lacTr ls -lacr
find命令也是非常有用的,可以用来查询被修改了的文件,只需要使用-ctime, -atime, -mtime参数。当使用find命令的时候,注意,那些目录下的文件的atime都会被改变。如果要更正规的使用find命令,那么应该使用在只读的镜像中。
多数Linux都有find[10],GNU版的find有很强的功能,可以指定一个时间区域,这样让find来显示这个区域的时间戳。如果你想查询多个至少7天前被修改的文件,并现实它们的mtime,ctime,atime和inode,可以用下面的命令:
# find / \( -mtime +2 -a -mtime -7 \) -a -printf "M:%t C:%c %i\t%p\n"
如果使用Linux,但是没有GNU的find,那么可以用stat命令,如果没有stat命令的权限,但可以用perl,那么可以用perl来当作stat(2):
# find / \( -mtime +2 -a -mtime -7 \)|perl -ne
'chomp;($i,$m,$c)=(stat)[1,9,10];printf"M:%s\t$i\t$_\n",localtime($m)." C:".localtime($c)'
攻击者可能通过有问题的suid或sgid的二进制来提升权限。攻击者有是也留下可以suid root 的shell,这样让他们更方便。find命令可以捕获到这样的文件。可以使用这样的命令:
find / -perm -6000 -ls
下面是一些find命令的例子:
the find command in action:
##==
##== find all files which have had their status changed in
##== the last 24 hrs (display ctime, inode, and filename)
# find / -ctime -1 -printf "%c %i\t%p\n"
Fri Sep 7 11:55:14 2003 174945 /var/lib/rpm
Fri Sep 7 11:55:14 2003 174946 /var/lib/rpm/__db.001
Fri Sep 7 11:55:17 2003 174947 /var/lib/rpm/__db.002
Fri Sep 7 11:55:17 2003 174948 /var/lib/rpm/__db.003
Fri Sep 7 11:55:55 2003 160125 /var/lib/random-seed
Fri Sep 7 11:55:16 2003 222706 /var/log
Fri Sep 7 12:17:05 2003 224545 /var/log/messages
[ output deleted ]
##==
##== find all files which have had their status changed from
##== 5 to 30 (inclusive) days ago and display the ctime, inode, and filename
# find / -ctime +4 -ctime -31 -printf "%c %i\t%p\n"
Sat Aug 30 19:49:52 2003 414661 /boot/System.map-2.4.20-20.8bigmem
Sat Aug 30 19:49:52 2003 414662 /boot/config-2.4.20-20.8bigmem
Sat Aug 30 19:49:52 2003 414663 /boot/module-info-2.4.20-20.8bigmem
Sat Aug 30 19:49:53 2003 414664 /boot/vmlinux-2.4.20-20.8bigmem
Sat Aug 30 19:49:53 2003 414665 /boot/vmlinuz-2.4.20-20.8bigmem
[ output deleted ]
If I had a photograph of you... something to remind me...
在Linux和Unix上创建文件系统镜像的最通常的命令是dd。 dd命令按位从输入中读取,并保存在输出中。dd不显示进度,因此如果是输入的块同输出块大小不相同的时候就会非常慢。比dd更友好的是sdd[11],它就没有这些缺点。sdd可以显示当前的统计,也可以显示当前的进度。
在使用dd来制作文件系统镜像之前,可以先用工具创建需要镜像的文件系统的hash。假设在Linux平台上要创建/dev/hda的镜像,可以运行md5sum /dev/hda,然后开始dd。 dd完成后,对保存的镜像运行相同的工具。如果这些值不匹配,应该检查为什么出现了差异。在openBSD和Solaris上进行应急响应的时候,应该用raw device。
对于Linux,工具e2image可以用来创建ext2和ext3文件系统的镜像。e2image只解释需要被镜像的文件系统,而不是保存原始bit。e2image就不能保存那种聪明的攻击者存储在磁盘上的文件系统结构之外的数据。 e2image可以创建“raw”和“nomal”镜像,这两种方法都可以节约空间。因此,用e2image创建的镜像同硬盘上的文件系统有不同的hash,这很难让你对捕获的数据进行断言。这导致e2image在取证上,依然是不能替代dd的。
另一个创建系统镜像的工具是partimage[12],可以将镜像文件通过ssl传输到一个partimage服务器上,当前可以支持ext2,ext3,ReiserFS,JFS,和XFS,也支持FAT16/32和HPFS(OS/2),并且正在逐步增加支持UFS(Solaris, *BSD), HFS(MaxOS)和NTFS。
partimage只能镜像被使用的分区块,因此跟e2image一样,用partimage制作的镜像并不能精确地反映镜像制作的时候磁盘的真实状态。这跟流行的PC产品ghost一样可以创建镜像,但是不适合于取证。在面对很严重的状态下,在使用ghost之前,应该先阅读手册,确信是否适合你使用。
可能你要问,为什么在这篇文章中介绍这些不适合于取证的工具。这是基于下面的原因:
当选择工具[13]来创建取证镜像的时候,所选用的工具必须能够精确反映创建镜像的时候磁盘的真实状态。
当制作文件系统镜像的时候,你需要理解工具作者是怎么理解“image”的。可以用下面方法进行测试:
1,离线测试计算机的文件系统
2,对包含文件系统的设备,运行md5sum或者执行SHA1的工具
3,用工具制作镜像
4,对镜像执行md5sum或者SHA1的工具
如果指纹不匹配,那么就不要在取证中用该工具。