Weekend Project: Intrusion Detection on Linux with AIDE



Front-line measures like firewalling, strong authentication, and staying on top of security updates are mandatory steps to keeping your system secure. But you also need to check your system’s health frequently and make sure a compromise didn’t slip past you unnoticed. A good place to start is with an intrusion detection system (IDS) that monitors your machine’s resources and flags any changes that might indicate an intruder or a rootkit. The Advanced Intrusion Detection Environment (AIDE) is an open source IDS that you can set up in a weekend.

Before we get started, though, it’s vital to understand how an IDS like AIDE functions. AIDE is a host-based IDS, which basically means that it scans the filesystem and logs the attributes of important files, directories, and devices. Each time it runs, it compares its findings against the previous, “known good” data, and alerts you if something has changes. But the downside is that if your system is already compromised before you install and run AIDE initially, you won’t be able to detect it.

Of course, the odds that your system is already compromised aren’t high, but the fact remains that the only way to guarantee that it is clean is to install and run AIDE right after you install the OS, but before you connect to the network. Put that on your to-do list when deploying new machines from now on, and as for your existing Linux boxes, make do as best as you can.

AIDE runs on Linux and most other Unix-like operating systems. It is provided by most of the distributions, but you may want to consider grabbing the code from the project’s Web site and compiling from source — there are a few advanced options that are only available at compile-time via the ./configure script. If you’ve already installed an AIDE binary, run aide -v, which will dump out the version number and the compile-time options used. For now, though, we’ll talk about the basic installation and usage.

Setup and First-Run

AIDE works its magic by reading in a configuration file that contains both a list of directories and files to scan, and the attributes of each entry to log. It then works its way through the tree of nodes to be scanned, and writes out a database of the attributes found. There are currently thirteen attributes that AIDE can log — including permissions, owner, group, size, all three timestamps (atime, ctime, and mtime), plus lower-level stuff like inode, block count, number of links, and so on.

On top of those, AIDE supports multiple has algorithms with which it can generate checksums for each file. By default, the list includes MD5, SHA-1, SHA-256, SHA-512, RMD-160, Tiger, HAVAL, and CRC-32. If you compile AIDE with the mhash option to the configuration script, you can also use GOST and Whirlpool hashes.

Binary packages probably include a decent example configuration file in /etc/aide/aide.conf — in a bit, we’ll explain why you might want to use a different location, but for the moment, open the file in an editor, and take a look at the configuration directives.

Near the top are rule definitions, which are just user-supplied names followed by an equal sign and a list of attributes and hashes. For example:

SizeOnly = s+b
SizeAndChecksum = s+b+md5+sha1
ReallyParanoid = p+i+n+u+g+s+b+m+a+c+md5+sha1+rmd160+tiger+whirlpool

The first line activates just the size (s) and block count (b) attributes. The second adds MD5 and SHA-1 hashes, and the third logs just about every supported feature, including inode (i), timestamps (m, a, and c) and a fistful of additional hashes.

Below these rule definitions you’ll find a lines listing the directories and files to check, using regular-expression based formulas. For example:

/etc SizeAndChecksum
/sbin ReallyParanoid
/var Size

The first three lines are “positive” expressions, which tell AIDE to include everything that matches the regular expression. The leading exclamation point on the last two indicate a “negative” expression, which in this case says to exclude the rapidly-changing /var/log/ and /var/spool/ directories. As you can see, each positive expression is followed by the name of one of the rule definitions. You could also use a literal string instead of a rule name here, such as /var/www/intranet p+s+b+a+sha256 — the rule names are just for easier reading.

Correctly defining your regular expressions and rules is the trickiest part of using AIDE. Too many files and directories, and you can end up with extremely long logs to read through on every integrity check. Too narrow of a set, and you risk missing an intruder. It’s also not trivially easy to get the right balance of regular expression syntax when you want to match some files in a directory hierarchy, but not others. It’s a good idea to consult the AIDE user manual and read man aide.conf for help combining wildcards with positive and negative expressions.

Of course, there’s no substitute for actually trying out your configuration with a real run. Run sudo aide --init, and AIDE scans the designated files and directories, writing its findings to a database. The location of the database is determined by a line of the form database=URL in the configuration file. The data is also copied to stdout, so you can watch the process from a terminal window. If you’re missing some files and need to tweak your expressions, you can do so and re-run the process before proceeding.

Comparing Subsequent Checks

Now comes the important (and potentially confusing) part. Time goes by, and whenever you feel it’s prudent, you decide to run another scan with sudo aide --check. Except that unless you specify otherwise, AIDE looks for a configuration file in the current working directory — which raises the question of where you should keep that all-important configuration file.

At first glance, it might seem like you should store it in a standard location like /etc/aide/, but that’s actually a bad idea, because if your system ever was cracked, intruders could not only read your AIDE configuration and look for directories that you’ve elected to ignore, but they could alter the URL of the output database in order to trick subsequent AIDE scans.

So the best plan is, in fact, to store the aide.conf file on removable media (preferably read-only), that you mount just before running a scan. For similar reasons, the safest place to store AIDE’s output database is also on this removable media, so inside the configuration file the database line might be database=/media/AIDE_CD_012345/aide.db. You tell AIDE where the configuration file is with the –config command-line parameter.

Thus, the correct scan command to run is (in this example) sudo aide --check --config=/media/AIDE_CD_012345/aide.conf.

If someone replaces your copy of /sbin/fsck, the second scan should notice it and report it to you on stdout. On the other hand, you may have good reason to alter a system file like /etc/pam.conf yourself, in which case you don’t need AIDE throwing a red flag every time you run a scan. You can invoke AIDE as sudo aide --update --config=/path/to/your/aide.conf to both run a scan and output an updated copy of the database. AIDE will save the new database at the URL you specify in the configuration file after database_out=. If you’re following proper protocol, this will be someplace mounted read-write, and you will subsequently copy the new database to your read-only media.

So how often should you run scans? It depends on the machine. On the plug-computer that runs your house’s lighting control and sprinkler system, rarely. On the company’s Internet gateway, daily at least.

Extra Credit: ACLs, SELinux, and Database Signing

As you’ve probably realized, all AIDE can do is alert you to changed files. The ball is in your court to recognize whether the change is a sign of a security breach. Some system files should never change; some (such as tty devices) change owner and permissions during regular operation. You have to get to know your system.

Depending on your system, you may not find the generic AIDE binaries supplied by your distribution up to the task. That is because there are a few attributes that AIDE can monitor only if they are configured as compile-time options, such as support for SELinux‘s security contexts, access control lists, and extended file attributes. If you need any of those features, you’ll want to compile AIDE yourself from source. Luckily it’s not hard; the standard GNU compiler chain is all that is required.

As mentioned above, the compile-time options also include support for additional hash algorithms. Which you prefer is largely a matter of personal mathematical preference. But there is also one other compile-time option that you should consider if you want a really secure setup. Configuring AIDE with HMAC (hash-based message authentication code) support allows you to cryptographically sign both the configuration file and the output database.

This is a compile-time option, not a run-time option, because adding it in prevents the aide binary from running a scan in the event that the signature of the config file or database doesn’t match. That’s what you want: a binary that cannot be tricked into using a compromised database. Because let’s face it — the read-only media you’re using is only as secure as the locker you store it in. To configure AIDE with HMAC support, read the final section of the AIDE online manual. You’ll need to pick a pair of encryption keys, but otherwise it’s a fairly simple process. After that, it’s sit back and scan-as-usual.