Wednesday, October 25, 2006

Post-Install package verification revisited

Some time ago I wrote an article on how to verify the md5 checksums of installed packages on a Gentoo system. Since that time the required package gentoolkit has changed and it no longer provides qpkg in a useful location. To update that article, since I no longer work there, I've put together something for the blog here.

Verification of installed files on a system is an important part of administration. Thankfully, we have tools like tripwire to make that task much easier. These tools allow us to determine which, if any, files have been altered on a system. These tools require that they have been setup to monitor files before the need to verify them comes up though. What can administrators do to find this information out if they were unable to setup something like Tripwire in advance ?

Enter equery. Equery is a multi-purposed application provided by app-portage/gentoolkit. It has so much functionality that many users I've spoken to find it somewhat complicated to get the hang of.


Usage: equery command
where is one of
-q, --quiet - minimal output
-C, --nocolor - turn off colours
-h, --help - this help screen
-V, --version - display version info
-N, --no-pipe - turn off pipe detection
where command(short) is one of
belongs(b) files... - list all packages owning files...
changes(c) - not implemented yet
check(k) pkgspec - check MD5sums and timestamps of pkgspec's files
depends(d) pkgspec - list all direct dependencies matching pkgspec
depgraph(g) pkgspec - display a dependency tree for pkgspec
files(f) pkgspec - list files owned by pkgspec
glsa(a) - not implemented yet
hasuse(h) useflag - list all packages with useflag
list(l) pkgspec - list all packages matching pkgspec
size(s) pkgspec - print size of files contained in package pkgspec
stats(t) - not implemented yet
uses(u) pkgspec - display USE flags for pkgspec
which(w) pkgspec - print full path to ebuild for package pkgspec


For this purpose, we'll only be making use of two equery functions: list and check.

First order of business is to determine what packages are installed on the system. Knowing this is useful in general and something you might want to monitor anyway. This step is very straight forward.


# equery -i list
[ Searching for all packages in all categories among: ]
* installed packages
[I--] [ ] app-admin/addpatches-0.2 (0)
[I--] [M ] app-admin/perl-cleaner-1.01 (0)
[I--] [ ] app-admin/php-toolkit-1.0-r2 (0)
[I--] [ ] app-admin/procinfo-18-r1 (0)
[I--] [ ] app-admin/sudo-1.6.8_p9-r2 (0)
[I--] [ ] app-admin/syslog-ng-1.6.9 (0)
--SNIP--


The first thing you'll notice is the output contains colors etc. To remove them, you'll want to use the -C flag. Another gotcha you'll encounter for this exercise will be the need to hand this output to a pipe. By default equery doesn't produce pipe-friendly output. In order to get the output to traverse a pipe, you'll also need the -N flag.


# equery -N -C -i list


Now that we're able to produce a list of installed software, we need to use equery to check these packages. There's two ways you can do this: You can manually hand equery the package name.


# equery check sqlite
[ Checking dev-db/sqlite-2.8.16-r4 ]
* 22 out of 22 files good
[ Checking dev-db/sqlite-3.3.5-r1 ]
* 22 out of 22 files good


Or, you can make use of awk and xargs to directly hand the equery list output to equery check.

For example:


# equery -N -C -i list | awk '{print $4}' | xargs -i equery check ={}
[ Checking app-admin/addpatches-0.2 ]
* 3 out of 3 files good
[ Checking app-admin/perl-cleaner-1.01 ]
* 7 out of 7 files good
[ Checking app-admin/php-toolkit-1.0-r2 ]
* 12 out of 12 files good
[ Checking app-admin/procinfo-18-r1 ]
* 15 out of 15 files good
[ Checking app-admin/sudo-1.6.8_p9-r2 ]
!!! /etc/sudoers has incorrect md5sum
* 34 out of 35 files good
--SNIP--


This command string will verify the checksums of all software installed on the system using portage. As you'll see, it's quite a bit of output. Since our application of this tool is to determine just what files have been altered, you might want to pull out just those lines starting with !!!

For example:

# equery -N -C -i list | awk '{print $4}' | xargs -i equery -N -C check ={} | grep ^\!\!\!
!!! /etc/sudoers has incorrect md5sum
!!! /etc/init.d/syslog-ng has incorrect md5sum
!!! /etc/syslog-ng/syslog-ng.conf has incorrect md5sum
--SNIP--


Now we have just the output we're interested in. From here there's a few things you might do. First, you'll probably want to keep a know "good" copy of this output as it contains some false positives for packages that checksum their default configuration files. With this you might make use of the diff command to determine what new packages no longer have good checksums.

Finally, should you identify a file with a bad checksum and are unsure as to what package provided that file you can make use of the equery function belongs. I know that I said we'd just be covering two equery functions. I lied.

So, for example we want to find out what package provided /etc/sudoers from our example above.


# equery belongs /etc/sudoers
[ Searching for file(s) /etc/sudoers in *... ]
app-admin/sudo-1.6.8_p9-r2 (/etc/sudoers)


That's it. You can now take advantage of these features to determine what things have changed on your system. This method is two things. It's Ugly, but it's also unexpected. Unexpected is advantageous to you as an admin. If someone gains access to your system, you can bet they'll check to see if you use tripwire. You can also bet that they'll most likely have no idea this method of checksumming even exists.

No comments: