Print Logo

Building a Security Audit Toolkit




<<  <   >  >>

As moon-howling, tree-hugging, packet-sniffing pagans, we like to celebrate the Summer Solstice by doing a security audit of the systems on our network. Spending the longest day of the year auditing systems will help us avoid spending the longest night of the year restoring a hacked one.

In our audit, we will be disabling unused accounts, shutting down unnecessary services, and generally cleaning up and hardening. We will also be checking for rootkits and other signs that a system's been hacked already. Preparing a toolkit to help us determine if a system has been compromised is the focus of this article.

We want to use the chkrootkit tool to check our systems. It can detect trojaned binaries, LKM trojans, hidden directories, sniffer logs, and rootkit configuration files. Be sure to download the latest version, as the rootkit signatures can be updated fairly frequently as new ones come out.

The problem with running chkrootkit on a live system is its use of external binaries -- the same external binaries which are usually trojaned by rootkits, such as ps, ls, and netstat. So if the system's been owned already, we can't completely trust what chkrootkit says. One solution would be to copy the binaries from a pristine system to media which we will then mount temporarily on the system to be examined. But binaries on modern systems use shared libraries. To run them, we would be relying on the integrity of the shared libraries on the suspect system. We don't want to trust anything on the system. So we are going to build static binaries from source on a trusted system, and a statically linked chkrootkit tool set too. These can then be stored in a safe place and mounted on the systems to be examined.

Building the Binaries

The chkrootkit tools use awk, cut, echo, egrep, find, head, id, ls, netstat, ps, strings, sed, and uname. For a starting point, since we're running Red Hat, we'll do an rpm query to find out what package each of these binaries belongs to:

[root@hazel rescue]# rpm -qf /bin/ps
procps-2.0.7-12

A google search leads us to freshmeat.net, and ultimately we can download the source for procps utilities from http://procps.sourceforge.net. We download, untar the tarball, and read the README, which reveals that if we want statically linked binaries, we should run the following:

[usr-4@hazel procps-3.1.9]$ make SHARED=0

The output of gcc spews forth, with no serious errors, and all is well. We have a number of binaries in our build directory. Let's make sure they're really static:

[usr-4@hazel procps-3.1.9]$ ls -F
AUTHORS      Makefile   pmap.1       skill.1        t*       top.o     vmstat.o
BUGS         minimal.c  pmap.c       skill.c        tload*   uptime*   w*
COPYING      NEWS       pmap.o       skill.o        tload.1  uptime.1  w.1
COPYING.LIB  pgrep*     proc/        snice*         tload.c  uptime.c  watch*
free*        pgrep.1    procps.lsm   snice.1        tload.o  uptime.o  watch.1
free.1       pgrep.c    procps.spec  sysctl*        TODO     v*        watch.c
free.c       pgrep.o    ps/          sysctl.8       top*     vmstat*   watch.o
free.o       pkill*     README       sysctl.c       top.1    vmstat.8  w.c
kill*        pkill.1    README.top   sysctl.conf.5  top.c    vmstat.c  w.o
kill.1       pmap*      skill*       sysctl.o       top.h    vmstat.h
[usr-4@hazel procps-3.1.9]$ ldd w
libc.so.6 => /lib/libc.so.6 (0x4002b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
[usr-4@hazel procps-3.1.9]$ ls -l w
-rwxr-xr-x    1 usr-4   usr-4     174555 Jun 17 13:27 w

It looks like the w binary is dynamically linked! What's up with that? Compare it to the w binary from procps built without the SHARED=0 option:

[usr-4@hazel procps-3.1.9]$ ldd w  
libproc.so.3.1.9 => not found
libc.so.6 => /lib/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
[usr-4@hazel procps-3.1.9]$ ls -l w
-rwxr-xr-x    1 usr-4   usr-4      76138 Jun 17 13:31 w

It appears that the SHARED=0 option only keeps procps from dynamically linking its own library, the libproc.so. So the binary is statically linked against that library, but not the system libraries.

A further perusal of the README tells us that we can pass gcc options to the compiler. This may be what we need:

[usr-4@hazel procps-3.1.9]$ make clean
rm -f uptime tload free w top vmstat watch skill snice kill sysctl pmap pgrep pk
ill proc/.depend proc/lib*.so* proc/lib*.a proc/alloc.o proc/devname.o proc/esca
pe.o proc/ksym.o proc/prof.o proc/pwcache.o proc/readproc.o proc/sig.o proc/stat
us.o proc/sysinfo.o proc/version.o proc/whattime.o ps/ps ps/debug DEADJOE *~ *.o
core gmon.out proc/DEADJOE proc/*~ proc/*.o proc/core proc/gmon.out ps/DEADJOE
ps/*~ ps/*.o ps/core ps/gmon.out
[usr-4@hazel procps-3.1.9]$ make SHARED=0 CC='gcc -static'
--output from make snipped--
[usr-4@hazel procps-3.1.9]$ ldd w
not a dynamic executable
[usr-4@hazel procps-3.1.9]$ ls -l w
-rwxr-xr-x    1 usr-4   usr-4     627172 Jun 17 13:35 w

There's the joy. This package has given us some nice tools in addition to the required ps. We will also take w, free, vmstat, top, and uptime. We've made a directory called audit, created a bin directory beneath it, and are copying all of our statically linked binaries there. Only 9 more packages to go! Don't worry, we'll give you the executive summary from this point forward.

awk

download: http://ftp.gnu.org/gnu/gawk/gawk-3.1.1.tar.gz

build:

[usr-4@hazel gawk-3.1.1]$ ./configure
[usr-4@hazel gawk-3.1.1]$ make CC="gcc -static"

postinstall: in your audit bin, make a symbolic link to gawk from awk, because chkrootkit will look for awk.

cut,echo,head,id,ls,uname

We are in luck! The three packages textutils, shellutils, and fileutils have been combined into one coreutils package. Six of our needed utilities in one package! download: http://ftp.gnu.org/pub/gnu/coreutils

build:

[usr-4@hazel coreutils-5.0]$ ./configure
[usr-4@hazel coreutils-5.0]$ make CC="gcc -static"

Copy the desired binaries from the src directory to your audit bin. I'm thinking md5sum might also be nice to have.

grep

download: http://www.gnu.org/directory/GNU/grep.html

build:

[usr-4@hazel grep-2.5]$ ./configure
[usr-4@hazel grep-2.5]$ make CC="gcc -static"

Copy the binary from src directory, make a symbolic link to it from "egrep".

netstat

download: http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.60.tar.bz2

build:

[usr-4@hazel net-tools-1.60]$ make config
(interactive - defaults worked for us)
[usr-4@hazel net-tools-1.60]$ make CC="gcc -static"

This one has some other goodies that might be handy in an audit too, like route, arp, and even ifconfig.

strings

download: http://ftp.gnu.org/gnu/binutils/binutils-2.13.1.tar.gz

build:

[usr-4@hazel binutils]$ ./configure
[usr-4@hazel binutils]$ make -e LDFLAGS=-all-static

Copy the utilities from the binutils subdirectory. For some reason, running gcc with the static flag did not result in statically linked binaries. So I set the LDFLAGS variable instead and got the joy.

sed

download: http://ftp.gnu.org/pub/gnu/sed/sed-4.0.7.tar.gz

build:

[usr-4@hazel sed-4.0.7]$ ./configure
[usr-4@hazel sed-4.0.7]$ make CC="gcc -static"

find

download:
ftp://ftp.linuxfromscratch.org/lfs-packages/4.0/findutils-4.1.tar.bz2
ftp://ftp.linuxfromscratch.org/lfs-packages/4.0/findutils-4.1.patch.bz2

Note: though the official location for findutils is gnu.org, findutils will not build on our system (Red Hat 7.3, all current updates). Since we need a patch which is not available on the gnu server, we'll download both from the LFS server. After expanding the findutils tarball, we unzipped the patch and copied it into the build directory.

build:

[usr-4@hazel findutils-4.1]$ patch -Np1 -i findutils-4.1.patch
[usr-4@hazel findutils-4.1]$ ./configure
[usr-4@hazel findutils-4.1]$ make CC="gcc -static"

Building chkrootkit

Now let's build chkrootkit statically:

[usr-4@hazel chkrootkit-0.40]$ make sense CC="gcc -static"

After building, we copied the entire build dir to our audit directory.

[usr-4@hazel sec]$ cp -a chkrootkit-0.40/ audit/

Using the Toolkit

We also built a statically compiled bash shell, downloading it from gnu.org and building it in the same way as the other gnu packages. Now we've got a good little toolkit for auditing systems. Because the executables are statically linked, they are MUCH bigger than dynamically linked programs. These tools are not going to fit on a floppy. Either burn them onto a cdrom (the best) and mount them from this read-only media, or mount them read-only from a trusted NFS server. If you must, you can copy them to the machine being audited, but once you're working on the local file system, you are through the looking glass. I've exported my audit tree using NFS from a trusted system. Now, I will use it to check for rootkits on another system. I've exported it read-only, so I don't need to make sure it's mounted read-only. To use our statically compiled binaries, we will supply the -p (path) option to chkrootkit.

[root@sketchy root]# mount hazel:/u01/audit /mnt/tmp
[root@sketchy root]# cd /mnt/tmp
[root@sketchy chkrootkit-0.40]# ./chkrootkit -p ../bin
[root@sketchy chkrootkit-0.40]# ./chkrootkit -p ../bin
ROOTDIR is `/'
Checking `amd'... not found
Checking `basename'... not infected
Checking `biff'... not found
Checking `chfn'... not infected
Checking `chsh'... not infected
Checking `cron'... not infected
Checking `date'... not infected
Checking `du'... not infected
Checking `dirname'... not infected
Checking `echo'... not infected
Checking `egrep'... not infected
Checking `env'... not infected
Checking `find'... not infected
Checking `fingerd'... not infected
Checking `gpm'... not infected
Checking `grep'... not infected
Checking `hdparm'... not infected
Checking `su'... not infected
Checking `ifconfig'... not infected
Checking `inetd'... not tested
Checking `inetdconf'... not found
Checking `identd'... not infected
Checking `init'... not infected
Checking `killall'... not infected
Checking `ldsopreload'... not infected
Checking `login'... not infected
Checking `ls'... not infected
Checking `lsof'... not infected
Checking `mail'... not infected
Checking `mingetty'... not infected
Checking `netstat'... not infected
Checking `named'... not found
Checking `passwd'... not infected
Checking `pidof'... not infected
Checking `pop2'... not found
Checking `pop3'... not found
Checking `ps'... not infected
Checking `pstree'... not infected
Checking `rpcinfo'... not infected
Checking `rlogind'... not infected
Checking `rshd'... not infected
Checking `slogin'... not infected
Checking `sendmail'... not infected
Checking `sshd'... not infected
Checking `syslogd'... not infected
Checking `tar'... not infected
Checking `tcpd'... not infected
Checking `tcpdump'... not infected
Checking `top'... not infected
Checking `telnetd'... not infected
Checking `timed'... not found
Checking `traceroute'... not infected
Checking `w'... not infected
Checking `write'... not infected
Checking `aliens'... no suspect files
Searching for sniffer's logs, it may take a while... nothing found
Searching for HiDrootkit's default dir... nothing found
Searching for t0rn's default files and dirs... nothing found
Searching for t0rn's v8 defaults... nothing found
Searching for Lion Worm default files and dirs... nothing found
Searching for RSHA's default files and dir... nothing found
Searching for RH-Sharpe's default files... nothing found
Searching for Ambient's rootkit (ark) default files and dirs... nothing found
Searching for suspicious files and dirs, it may take a while... 
/usr/lib/perl5/site_perl/5.6.1/i386-linux/auto/DBD/Oracle/.packlist
Searching for LPD Worm files and dirs... nothing found
Searching for Ramen Worm files and dirs... nothing found
Searching for Maniac files and dirs... nothing found
Searching for RK17 files and dirs... nothing found
Searching for Ducoci rootkit... nothing found
Searching for Adore Worm... nothing found
Searching for ShitC Worm... nothing found
Searching for Omega Worm... nothing found
Searching for Sadmind/IIS Worm... nothing found
Searching for MonKit... nothing found
Searching for Showtee... nothing found
Searching for OpticKit... nothing found
Searching for T.R.K... nothing found
Searching for Mithra... nothing found
Searching for OBSD rk v1... nothing found
Searching for LOC rootkit ... nothing found
Searching for Romanian rootkit ... nothing found
Searching for HKRK rootkit ... nothing found
Searching for anomalies in shell history files... nothing found
Checking `asp'... not infected
Checking `bindshell'... not infected
Checking `lkm'... nothing detected
Checking `rexedcs'... not found
Checking `sniffer'... 
eth0 is not promisc
Checking `wted'... nothing deleted
Checking `scalper'... not infected
Checking `slapper'... not infected
Checking `z2'... 
nothing deleted

Under suspicious files and directories, we've got one entry. All sorts of hidden files and directories can show up here. Let's check this one.

[root@sketchy chkrootkit-0.40]# cd /usr/lib/perl5/site_perl/5.6.1/i386-linux/auto/DBD/Oracle
[root@sketchy Oracle]#/mnt/tmp/bin/head  .packlist 
DBD::Oracle.3pm
DBD::Oraperl.3pm
Oracle.bs
Oracle.h
Oracle.pm
Oracle.so
Oraperl.pm
dbdimp.h
mk.pm
ocitrace.h

This system looks good. We can continue our system audit with a high degree of confidence that there are no rootkits installed because we used our clean tools. If further investigation is desired, we can use our clean tools to poke around.Who's logged on? Use your statically linked w command. What connections are open on this machine? Use your statically linked netstat. You could also put a statically linked version of tcpdump and other networking utilities in your audit toolkit.

Now we're going to finish our audit so we can go hug some trees.



This article comes from NetAdminTools:
http://www.netadmintools.com/

The URL for this story is:
http://www.netadmintools.com/art279.html

Copyright 1997-2012 NetAdminTools.com. Read our Terms of Use.