Intrusion Detection for the Masses

Set up Tripwire to catch intruders big and small.
A Note about RPMs

Needless to say, it's simpler and faster to install RPMs (but again, note that the most up-to-date version of Tripwire may not be available in this format). The only thing you need to know is that after you run rpm, you'll need to enter /etc/tripwire/ to generate site and local passwords. This script behaves much like the end of the source distribution's script—see the previous paragraph.

Using Tripwire

As useful as Tripwire is, it has a reputation for being difficult to configure (which is, of course, true of most powerful and flexible tools). But it's really not as bad as all that, and by following the simple instructions I'm about to set forth, you can use Tripwire effectively enough to catch yourself some bad guys. So now, let's enter the elite ranks of users who have not only installed, but actually used, Tripwire!

Managing the Configuration File

The first thing we need to do is double-check our configuration file, tw.cfg. Actually, this file was just encrypted by the installation script, but for our convenience a clear-text copy called twcfg.txt should reside in /etc/tripwire. This is the place to change any settings you've had second thoughts about since running the installation script, and the variables are named accordingly.

If you make any changes, re-encrypt the configuration file with the command:

twadmin --create-cfgfile --site-keyfile ./site.key twcfg.txt

where site.key is the name of the site-key created at installation time and twcft.txt is the name of the clear-text configuration file you just edited and wish to encrypt. That may seem obvious given that these are the default names for these files, but you can name them whatever you like. Regardless, don't forget to specify the keyfile, or twadmin will return an error (remember, the point of this exercise is to encrypt the configuration file).

Warning: you should not, as a matter of practice, leave clear-text copies of your Tripwire configuration (tw.cfg) or policy (tw.pol) files on your hard drive. After editing and encrypting them, delete the clear-text versions. You can always retrieve them later with the command:

twadmin --print-cfgfile > mycfg.txt

where, predictably, you can substitute mycfg.txt with whatever you like.

Although I haven't yet described Tripwire binaries in any detail (it's more useful to explain them in context), you've no doubt guessed by now that twadmin is used to manage Tripwire's configuration, key and (initially, at least) policy files.

Managing the Policy File

Like the Tripwire configuration file, policies are edited as text files but are encrypted and signed before being installed. Unlike the configuration file, however, we only use the twadmin command to install a policy file for the first time on a given system; subsequently we'll use the tripwire command in policy-update mode.

In any event, the command to install a policy the first time after installing Tripwire is:

twadmin --create-polfile twpol.txt

where twpol.txt is the name of the clear-text policy file you wish to install.

As with configuration files, you shouldn't leave clear-text policy files on your system. If you need to refer to or edit the policy later, you can retrieve it by typing:

twadmin --print-polfile > mypol.txt

mypol.txt can be whatever you wish to call the clear-text copy of the policy. (See a pattern here?)

Editing or Creating a Policy

And now we begin the serious voodoo. Tripwire's policy file is its brain: it specifies what to look at, what to look for and what to do about it. It's also a little on the user-hostile side, though not nearly so bad in this regard as, say, (but prepare to memorize some abbreviations).

Naturally Tripwire Open Source comes with a default policy file, and naturally you may, if you like, use this as your very own personal Tripwire policy. But since the default policy was created for a Red Hat system running nearly everything in the distribution, you should probably edit this policy heavily rather than use it as is.

First, a word about tuning. If your policy doesn't check enough files or doesn't look closely enough at the ones it does check, Tripwire's purpose is defeated and shenanigans will go undetected. Conversely, if the policy looks too critically at files you expect to change anyhow, Tripwire will generate “false positives” that serve no purpose other than to distract your attention from actual discrepancies.

It's doubtful you'll create a sane baseline the first time around. You'll almost certainly need to adjust your policy on an ongoing basis and especially after the first time you run an integrity-check. Thus, even if you do have a Red Hat system with exactly the same configuration as the one for which the default Tripwire Open Source policy was designed, you still need to learn proper Tripwire policy syntax. Let's get cracking.

I'm going to explain policy file structure and syntax by dissecting a working policy file into manageable chunks. The first chunk we'll look at is from the very beginning of our sample policy file and lists some variable definitions:


We can use these variables to save valuable touch-typing energy. On to the next chunk, some fancier variable definitions:

BINS          = $(ReadOnly) ; # Binaries that should
                                not change
SEC_INVARIANT = +tpug ;       # Dir.s that shouldn't
                                change perms/ownership
SIG_MED       = 66 ;          # Important but not
                                system-critical files
Unlike the first set of variable definitions that involved simple path-shortcuts, these are a bit fancier. The first line shows us how to set one variable to the value of another—similar to bash shell syntax, but note the parentheses around the second variable's name.

The second line defines a “property mask”; property masks are abbreviations of the file properties Tripwire examines. Since property mask strings can be cryptic and unwieldy, most people prefer to use variables to refer to them. In fact, Tripwire comes with a number of predeclared variables set to common property masks, and the first line actually refers to one of these, ReadOnly, a property mask for files that shouldn't change in any way, like binaries. We'll discuss property masks in detail, but all in good time.

The third line creates a name for a severity level. Severity levels can be used to differentiate between rules of varying importance. When the tripwire command is invoked with the --severity N parameter, only rules with assigned severity levels equal to or greater than N will be parsed. If this parameter is not used, all rules will be parsed. Also note that if a rule has no severity level associated with it, the level will be set to zero by default. That is, that rule will only be parsed when the --severity parameter isn't specified.

Now that we've got a feel for policy variables and what they're used for, let's start looking at actual rules:

# Mick's Web Junk
  rulename = "MickWeb",
  severity = $(SIG_MED),
  emailto =
  $(WEBROOT)             -> $(ReadOnly) (recurse=1) ;
  !$(WEBROOT)/guestbook.html ;
  $(CGIBINS)             -> $(BINS)     ;
  /var/log/httpd         -> $(Growing)  ;

This is a very rich chunk, so we'll begin with rule structure. Rules may either stand alone or be grouped together based on common attributes; this listing shows a group of rules (contained within curly brackets) with several shared attributes (in parentheses, above the rules). This group's rulename is “MickWeb”, the group's severity is 66 and reports involving this group will be e-mailed to Note that attributes are separated by commas, whereas each rule ends with a semicolon.

Attributes can also be assigned to individual rules. The first rule in this group has the attribute recurse set to 1, which means that the directory /home/mick/www will be checked down one level (i.e., the directory itself plus everything immediately “below”, but no further). Note that by default, directories will be recursed as far down as they go; in effect, the recurse attribute has a default value of “True”.

Attributes listed in rule statements usually override those listed in parentheses above such rules' group. The exception is the attribute “emailto”, which is cumulative: if a group has a shared emailto string and one of that group's rules has a different emailto string, reports relevant to that rule will be e-mailed to all e-mail addresses in those two strings.

By the way, there are only four attributes: rulename, severity, emailto and recurse. For more detailed information on these see the Resources section.

After the group attributes for MickWeb we have some actual rules. Note the use of variables to specify both objects (the Tripwire term for files and directories) and property masks. In fact, none of the rules uses a “longhand” property mask. This is common practice and perfectly acceptable.

Immediately below the first rule, which tells Tripwire to treat the first level of my WWW directory as read-only, we have a statement beginning with an exclamation point. This statement is called a stop point, and it defines an exception to a rule. In this case, the stop point tells Tripwire to ignore changes to the file /home/mick/www/guestbook.html. Attributes do not apply to (nor may they be assigned to) stop points.

There, that's a complete policy file (technically, at least—it doesn't check any system binaries or configuration files at all—real policies are much longer). Listing 1 shows it in all its non-dissected glory.

Listing 1. Sample Policy File

You may have noticed this entire file only contains one explicit reference to a property mask: the variable declaration in which SEC_INVARIANT is set to “+tpug”. What does that mean?

A property mask is a series of file/directory properties that should be checked or ignored for a given object. Properties following a plus sign are checked; those following a minus sign are ignored. The properties are abbreviated as outlined in Table 1.

Table 1. Property Mask Values

Tripwire's own documentation describes these properties in depth. If you're unfamiliar with some of the more arcane file attributes (e.g., inode reference count) I recommend the paper “Design and Implementation of the Second Extended Filesystem” by Card, Ts'o and Tweedie (see Resources, below). As for hash-types, note that you generally won't want to use more than one or two cryptographic hashes per rule: these are CPU-intensive. On the other hand, do not rely solely on CRC-32 hashes, which are fast but much easier to subvert.

As I mentioned earlier, Tripwire has a number of predefined (hard coded) variables that describe property masks, shown in Table 2.

Table 2. Predefined Tripwire Property Mask Variables

In most cases it's simpler to use these predefined masks than to “roll your own”. Note, however, that you can combine these variables with additional properties, e.g.,

/dev/console  -> $(Dynamic) -u ;
# Dynamic, but UID can change

is the same thing as

/dev/console  -> +pingutd-srlbamcCMSH-u
After you've created what seems like a reasonable policy, you need to install it. Again, the command to install a system's first Tripwire policy is:
twadmin --create-polfile policyfile.txt
The last step in setting up Tripwire is to create (initialize) its database. Important: there's no point in initializing a Tripwire database on a system that's been up and, therefore, has possibly been compromised already! Tripwire installation, configuration and initialization should occur as soon after OS installation as possible.

To initialize the database, we now use the tripwire command: tripwire --init. Doesn't get much simpler than that, does it? But use the --init directive only when creating a new database. If you need to change your Tripwire policy later, it's better to use the following commands:

twadmin --print-polfile > mypolicy.txt
  # dump current installed plcy
vi mypolicy.txt
  # make changes to policy
tripwire --update-policy mypolicy.txt
  # install new policy --