Programming

How can you easily verify the integrity of installed files on a Debian system?

2 minute read

This post is from March 2012. The screenshots show the interface as it was then; today it looks slightly different in places.

When using monitoring tools such as tripwire or rkhunter to monitor changes to installed files, the problem is that these tools cannot detect whether the files were changed by a regular package upgrade or tampered with by an unauthorized person.

For example, if rkhunter reports that the file /usr/bin/ldd has been modified, you must manually check whether the file’s checksum corresponds to the latest version of the Debian package.

There is a tool called debsums that simplifies this task. It can be installed using:

# apt-get install debsums

Once the tool is installed, you can perform the check at the package level:

# debsums file
/usr/bin/file OK
/usr/share/bug/file/control OK
/usr/share/bug/file/presubj OK
/usr/share/doc/file/README.Debian OK
/usr/share/doc/file/README.gz OK
/usr/share/doc/file/changelog.Debian.gz OK
/usr/share/doc/file/changelog.gz OK
/usr/share/doc/file/copyright OK
/usr/share/lintian/overrides/file OK
/usr/share/man/man1/file.1.gz OK

but not at the file level:

# debsums /usr/bin/ldd
debsums: invalid package name ‘/usr/bin/ldd’

First, you need to find out which package the file /usr/bin/ldd belongs to.

# dpkg -S /usr/bin/ldd
libc-bin: /usr/bin/ldd

To avoid having to run the search every time, I have written a small shell script that handles this task and calls debsums with the results:

#!/bin/bash
EC=0
PKGS=$(dpkg -S “$@” | awk -F’:’ ‘{print $1}’ | sed -e ‘s/, /\n/g’ | sort | uniq)
for i in $PKGS; do
debsums “$i” | grep -v OK
dec=$PIPESTATUS
echo -n “=== Package ‘$i’ : ”
if [ $dec -eq 0 ]; then echo OK; else echo MODIFIED; EC=$dec; fi
done
exit $EC

In this example, I have named the script check-inst.sh. It is easy to use:

# ./check-inst.sh /usr/bin/ldd
=== Package ‘libc-bin’ : OK

You can call the script with multiple filenames:

# ./check-inst.sh /usr/bin/file /usr/bin/ldd
=== Package ‘file’ : OK
=== Package ‘libc-bin’ : OK

If you do not use an absolute path, you will get search results for installed packages:

# ./check-inst.sh apache2
=== Package ‘apache2’ : OK
=== Package ‘apache2.2-bin’ : OK
=== Package ‘apache2.2-common’ : OK
=== Package ‘apache2-doc’ : OK
=== Package ‘apache2-mpm-prefork’ : OK
=== Package ‘apache2-suexec’ : OK
=== Package ‘apache2-utils’ : OK
=== Package ‘bash-completion’ : OK
=== Package ‘libapache2-mod-fcgid’ : OK
=== Package ‘libapache2-mod-php5’ : OK
=== Package ‘libapache2-mod-ruby’ : OK
=== Package ‘libapache2-mod-suphp’ : OK

If the results are OK, you can update your monitoring tool with peace of mind. For example, with rkhunter:

# rkhunter –propupd –update

Here is an example output showing the files modified by the user:

# ./check-inst.sh /usr/bin/pear
/usr/bin/pear FAILED
/usr/bin/peardev FAILED
/usr/bin/pecl FAILED
…
/usr/share/php/pearcmd.php FAILED
/usr/share/php/peclcmd.php FAILED
=== Package ‘php-pear’ : MODIFIED

The script returns ExitCode 0 if all checks were successful; otherwise, it returns the error code of the first failed check. This is useful if you are initially only interested in the exit code and want to read the error results from a log file.

Have fun trying it out!
C.