Most Linux distributions include a package manager. Package managers are a huge step up from the past. You used to have to manually download software’s source code, build it, and deal with library and third-party tool dependencies on your own.
Most mainstream distributions use RPM or dpkg-based package managers, but there are also a handful of other package formats.
One often-overlooked feature that most package managers include is a summary of the checksums for each of the files included in a particular package. This can be used to verify the integrity of your systems.
These scenarios are suspicious and should be investigated:
- If a file in a directory typically in $PATH (/bin, /sbin, /usr/bin, /usr/sbin, …) has a different hash than what was provided by its package.
- If a library’s hash differs from what was provided by a package.
- If configuration files differ from what was provided by the package and the changes can’t be accounted for.
- If a binary or library isn’t provided by a package. Example: /bin/fsck.reiserfs exists but wasn’t put there by a package.
dpkg(deb)-Based Systems
Debian, Ubuntu, Mint, Kali, and several others use dpkg to manage packages.
Verifying a package
Scenario: you suspect a package has been tampered with. For demonstration purposes, let’s say that you believe an attacker has modified /bin/netstat to hide network connections.
You can test your suspicions if you know the package name that provides /bin/netstat. To look this value up, use the -S option. In this case, the package which provides /bin/netstat is net-tools. Verify net-tools with the -V flag:
% dpkg -S /bin/netstat net-tools: /bin/netstat % dpkg -V net-tools
There was no output, indicating that netstat was not tampered with. Here, we will demonstrate that this actually works by tampering with netstat and trying again:
% cp /bin/netstat . % sudo -s # echo garbage >>/bin/netstat # dpkg -V net-tools ??5?????? /bin/netstat # cp ./netstat /bin/netstat # chown root.root /bin/netstat # ls -l /bin/netstat -rwxr-xr-x 1 root root 119624 Feb 24 16:44 /bin/netstat* # dpkg -V net-tools
After netstat was modified, dpkg -V showed that its checksum differed (the ??5?????? column. See ). Replacing netstat with its original copy yielded no output. An explaination of the fields in this column is found in dpkg’s man page:
--verify-format format-name Sets the output format for the --verify command (since dpkg 1.17.2). The only currently supported output format is rpm, which consists of a line for every path that failed any check. The lines start with 9 characters to report each specific check result, a ‘?’ implies the check could not be done (lack of support, file permissions, etc), ‘.’ implies the check passed, and an alphanumeric character implies a specific check failed; the md5sum verification failure (the file contents have changed) is denoted with a ‘5’ on the third character. The line is followed by a space and an attribute character (currently ‘c’ for conffiles), another space and the pathname.
All packages can be verified with a 1-liner:
# for pkg in $(dpkg -l | grep ^ii | awk {'print $2'}); do dpkg -V $pkg; done
debsums
debsums is a tool that you can install which allows you to validate all packages with one easy command. To install it:
# apt install debsums
Example usage:
# debsums -c /usr/x86_64-linux-gnu/security/pam_unix.so /bin/ps /bin/netstat
You should read the man page for debsums for more examples.
Files not provided by a package
A decent Indicator of Compromise (IoC) is when files in directories such as /bin, /sbin, /lib, … contain files NOT provided by a package. This occurs when someone places files in these directories manually.
# find /bin/ -exec dpkg -S {} \; 2>&1 |grep "no path found matching" dpkg-query: no path found matching pattern /bin/backdoor
Where the checksums are stored
Checksums for these files are located in /var/lib/dpkg/info/*.md5sums
The format is self-explanatory if you look at any of these files:
# cat /var/lib/dpkg/info/at.md5sums 507610d547edc3e7b98777cd1d5ad084 lib/systemd/system/atd.service 2c0733b064a62cb0c4cbbbd531465120 usr/bin/at 03265a0c11d5b695529f629b1e860eb1 usr/bin/batch 50fd51201dda267285da1d0eadd50736 usr/sbin/atd 38c61cea8340b1d2191535464235fd6a usr/share/doc/at/Problems fb98b5905a0ec916dd6277268f86dd10 usr/share/doc/at/README ...snip...
This is useful for writing scripts that go above and beyond what is offered by dpkg and debsums. Be advised that attackers can modify these files. For example, in the last section, /bin/backdoor wasn’t provided by a package. An entry can be added to one of these .md5sums files and its accompanying .lists file to make it appear like a legitimate element of a package:
# md5sum /bin/backdoor d41d8cd98f00b204e9800998ecf8427e /bin/backdoor # vi /var/lib/dpkg/info/at.list # vi /var/lib/dpkg/info/at.md5sums # dpkg -S /bin/backdoor at: /bin/backdoor # dpkg -V at # grep backdoor /var/lib/dpkg/info/at.* /var/lib/dpkg/info/at.list:/bin/backdoor /var/lib/dpkg/info/at.md5sums:d41d8cd98f00b204e9800998ecf8427e bin/backdoor
The moral of this story is to take outputs of tools with a grain of salt. Bring your own verified good tools and hash sets to forensic/incident response engagements.
If you suspect the md5sums files on disk were tampered with
As noted in the previous section, an attacker can add bogus entries to dpkg’s database, masking their activity. You should curate your own lists of hashes for systems that you maintain. If possible, you should keep installed packages handy on read-only media to serve as a source of truth. You may have to search the internet for package mirror sites that provide the specific version of the package you are investigating.
Be prepared!
RPM-Based Systems
RHEL, CentOS, SuSE, and others are RPM-based. These techniques should work on these distributions.
Verifying a package
Scenario: you think that someone has tampered with /bin/date. You can figure out which package provides date and verify it:
$ rpm -q --whatprovides /bin/date coreutils-8.22-23.el7.x86_64 $ rpm -V coreutils
There was no output because the hashes in the RPM database match what is on disk. Let’s mess up /bin/date to trigger this check:
# cp /bin/date . # echo garbage >>/bin/date # rpm -V coreutils S.5....T. /usr/bin/date # cp ./date /bin/date cp: overwrite ‘/bin/date’? y # rpm -V coreutils .......T. /usr/bin/date
dpkg mimics rpm’s output format for verification. In the first run of rpm -V, it indicates that the Size, MD5, and Timestamp are different. After replacing the date with its original copy, only the timestamp differs.
Verifying all packages is simple:
$ rpm -Va
Files not provided by a package
Files not provided by a package in directories such as /bin, /sbin, etc are suspicious. This one-liner will search for these files:
$ find /bin/ -type f -exec rpm -q --whatprovides {} \; |grep "is not owned by any package"
Where the checksums are stored
/var/lib/rpm/ contains a set of Berkeley DB files that are full of package metadata. I was unsuccessful in trying to hex edit these files to tamper with file hashes, but I’m sure its possible.
Extracting RPMs without installing them
You may wish to examine the contents of an RPM without installing it. To do this, you need the rpm2cpio utility:
$ mkdir scratch $ cp whatever.rpm scratch $ cd scratch $ rpm2cpio whatever.rpm | cpio -idmv
Honorable Mentions
Here are some other package types that aren’t as common as dpkg or rpms and some brief observations.
Slackware
Slackware packages are gzipped tarballs. From what I can tell, they do not include checksum information.
Arch
Arch packages are xzipped tar files. These .txz files contain a gzipped .MTREE file which includes sha256 hashes of files provided by each package. paccheck appears to be a tool able to verify these packages.
FreeBSD pkg
FreeBSD packages are xzipped tar files. The +MANIFEST file included within each package contains a JSON object containing sha256 hashes of each file included in the package. It appears that you can verify packages with pkg check -s|–checksums.
FreeBSD includes the mtree utility, which creates a database of hashes. These databases can be copied to another system or read-only media and compared to what is actually on disk at a later date.