This section explains how to specify in the configuration file, which files or directories should be monitored, and which monitoring policy should be used.
samhain offers several pre-defined monitoring policies. Each of these policies has its own section in the configuration file. Placing a file in one of these sections will select the respective policy for that file.
The available policies (section headings) are:
All modifications except access times will be reported for these files.
Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, checksum, size, mtime, ctime.
Modifications of timestamps, file size, and signature will be ignored.
Checked: owner, group, permissions, file type, device number, hardlinks, links, inode.
Modifications of timestamps, and signature will be ignored. Modification of the file size will only be ignored if the file size has increased.
Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, size >= previous_size, checksum(file start up to previous size) equals previous checksum.
If the size has shrunk (e.g. because of log rotation), samhain will look for a file with the same inode as before and check whether it has a size >= previous_size, and checksum(file start up to previous size) equals previous checksum. No report will be issued if this check succeeds. Thus log rotation will be handled gracefully as long as the inode is kept (i.e. the old file is moved rather than copied) and the first rotated file is not compressed (the logrotate tool can be told to compress only after the second cycle, and on Debian this seems to be standard anyway).
Only modifications of ownership, access permissions, and device number will be checked.
Checked: owner, group, permissions, file type, device number.
No modifications will be reported. However, the existence of the specified file or directory will still be checked.
All modifications, including access time, but excluding ctime, will be reported - checking atime and ctime would require to play with the system clock.
Checked: owner, group, permissions, file type, device number, hardlinks, links, inode, checksum, size, mtime, atime.
Initialized to: report all modifications.
Initialized to: report all modifications.
Initialized to: report all modifications.
Initialized to: report all modifications.
Initialized to: report all modifications.
Modifications of timestamps, size, and inode will be ignored Checksums will be verified by calling /usr/sbin/prelink --verify . This policy is intended for verification of prelinked executables/libraries and/or directories containing such files. For details and further configuration options see Section 4.8 .
Checked: owner, group, permissions, file type, device number, hardlinks, links, checksum.
Each policy can be modified in the config file
Misc with entries like
This must come before any file policies are used in the config file.
Entries for files have the following syntax:
Entries for directories have the following syntax:
The specification of a (numerical) recursion depth is optional (see Section 4.5 ). (Do not put the recursion depth in brackets — they just indicate that this is an optional argument!).
Wildcard patterns ('*', '?', '[...]') as in shell globbing are supported for paths. The leading '/' is mandatory. Since version 2.7.1, it is allowed to enclose the value of the directive (i.e. the path for files, the optional recursion depth and the path for directories) within matching single or double quotes, which allows to have trailing blanks ( note: it is not neccessary to escape quotes in between - the algorithm does not scan forward to find the matching quote, rather it uses the last character). Also since version 2.7.1, C quoting style is supported ('\a' [bell], '\b' [backspace], '\f' [form feed], '\n' [newline], '\r' [carriage return], '\t' [horizontal tab], '\v' [vertical tab], '\\' [backslash], '\'' [single quote], '\"' [double quote], '\nnn' [dree digit octal value], \xNN' [two digit hexadecimal value]). Example:
[ReadOnly] # valid examples dir = /u01/oracle/archive00 dir = 7/u01/oracle/archive02 dir = "7/u01/oracle/archive03 " dir = "7/u01/oracle/archi"ve" dir = /u01/oracle/archive\v04 dir = /u01/oracle/archive\\04 dir = /u01/oracle/archive\076 file = '/u01/oracle/archive\x0a' # valid (no quote at start, thus quote at end # is considered part of filename) file = /u01/oracle/archive_0" #invalid (no matching quote at end) file = "/u01/oracle/archive_0 #invalid (\03 is bad, must be 3 digits [octal] # or \x03 for hexadecimal) file = /u01/oracle/archive_\03 #invalid (\g is undefined escape sequence) file = /u01/oracle/archive_\g
|Note on directories|
A directory is (a) a collection of files, with (b) a directory special file where a listing of all files in the directories is kept. This directory special file will be modified in case of a file addition, removal, or renaming. Depending on the chosen policy, samhain will report on such modifications of the directory special file.
The addition and/or deletion of files from a directory modifies the directory special file (mtime/ctime). The addition/deletion of subdirectories will also modify the number of hardlinks of the directory special file. A modification of a file may modify a directory special file (mtime/ctime), if this modification is done by first creating a temporary file, followed by renaming this temporary file to the original one.
For the file check, samhain does not follow symlinks. If the argument for a file=... directive is a symlink, then the symlink itself is checked, not the location it points to.
The argument for a dir=... directive must be a directory. Using a symlink to a directory as argument is incorrect.
Precedence is given to the most specific location in the filesystem regardless of the order listed in the config file. I.e.,
a policy for a specific file overrides the policy for its directory
a policy for a subdirectory overrides the policy for its parent directory
if a directory or file path are explicitly listed twice in two different policy sections, Samhain will print a warning and honor only the first stanza processed. "First matching rule wins." Note however that it is perfectly ok to list a directory both as file=/path and dir=/path (see next rules).
Checking a directory with dir=... will check both the content of the directory as well as the directory special file itself, honoring a local and global recursion depth, giving local preference.
Using a directory as argument for both a file=... and a dir=... directive will have the effect that
the file=... directive will override the dir=... directive for the directory special file itself,
while the dir=... directive remains in effect for the directory content.
The presence of a file=
/parent/subdir, which is more specific of a path entry than that of the parent directory in another policy section with a "deeper" recursion depth as dir=
N/parentwill not prevent Samhain from descending into
/parent/subdirand applying the higher level directory with the "deeper" recursion policy to the contents of
/parent/subdirThe more-specific rule will only apply to the directory special file and does not "truncate" the higher level policy in any way.
To determine if you config file syntax is working as expected, increase the verbosity of debugging when running samhain with "-t init" using "-p info" or even "-p debug".
Example 1: If you only want to check files in a directory, but not the directory inode itself, use:
[ReadOnly] dir = /u01/oracle/archive00 [IgnoreAll] file = /u01/oracle/archive00 # Note: /u01/oracle/archive00/archive01.dbf -> archive99.dbf *should* be # mounted in the DB as a read-only tablespace and should never be # changed, however, the DBA thinks he's God and does not need to consult # with the Admin, so he may be adding new, deleting, or renaming the # DBFs using SQLPlus without consulting with the admin, so tell me about # changes to the files inside that we know about at Samhain INIT but # such as when he adds a file.
Example 2: If you want to monitor a directory, but not the dynamic contents inside it:
[Attributes] file = /var/spool/mqueue file = /tmp [IgnoreAll] dir=-1/var/spool/mqueue dir=-1/tmp
Example 3: If you want to monitor a directory special file, while ensuring no files within are removed but not the actual attributes of those files:
[Attributes] file = /root [IgnoreAll] dir=0/root
Thanks to Brian A. Seklecki for his effort to clarify these rules and provide examples.
If you want to suppress messages about the creation
of certain files (e.g. rotated log files), you can use the
be placed in the [Misc] section of the configuration files.
If you want to add more regular expressions, you can use
these options multiple times. Since transient files might
get modified during their lifetime, there is also the
The argument to IgnoreAdded , IgnoreMissing , and IgnoreModified must be a regular expression that matches the full path. In particular, it has to start with a forward slash.. To test your regex before putting in samhain, you do something like this:
# This regex matches all files added by logrotate # (e.g: messages.1 or messages.2.gz, etc.) cd /var/log for file in *; do echo $file| \ egrep "(cron|messages|rpmpkgs|secure|up2date|wmtp)\.[0-9](\.gz)?$"; done
Once it's work this way, you can add it to your samhainrc file, but don't forget to add the full path. e.g:
IgnoreAdded = your_tested_regex
This tip has been provided by jim at aegis hyphen corp dot org.
If a directory is added to [Attributes] as a file=/dir, then only the directory special file is monitored for permissions/ownership. The advantage is that additions/removals of files to that subdirectory can happen without recourse, but the integrity of that directory is defended. Assuming the administrator doesn't want to get granular level of detail.
Good for such directories as:
This tip has been provided by Brian A. Seklecki
samhain reads the file signature database at startup and creates an in-memory copy. This in-memory copy is then dynamically updated to reflect changes in the file system.
I.e. for each modified/disappeared/new file you will receive an alarm, then the in-memory copy of the file signature database is updated, and you will only receive another alarm for that file if it is modified again (or disappears/appears again).
Note that the on-disk file signature database is not updated (if you have signed it, the daemon could not do that anyway). However, as long as the machine is not rebooted, there should be no need to update the on-disk file signature database.
If files disappear after initialization, you will get an error message with the severity specified for file access errors ( except if the file is placed under the IgnoreAll policy, in which case a message of SeverityIgnoreAll— see Section 1.1 — is generated).
If new files appear in a monitored directory after initialization, you will get an error message with the severity specified for that directory's file policy ( except if the file is placed under the IgnoreAll policy, in which case a message of SeverityIgnoreAll— see Section 1.1 — is generated).
The special treatment of files under the IgnoreAll policy allows to handle cases where a file might be deleted and/or recreated by the system more or less frequently.
Directories can be monitored up to a maximum recursion depth of 99 (i.e. 99 levels of subdirectories. The recursion depth actually used is defined in the following order of priority:
The recursion depth specified for that individual directory ( Section 4 ). As a special case, for directories with the policy IgnoreAll, the recursion depth should be set to 0, if you want to monitor (the existence of) the files within that directory, but to -1, if you do not want samhain to look into that directory.
The global default recursion depth specified in the configuration file. This is done in the configuration file section Misc with the entry SetRecursionLevel=
The default recursion depth, which is zero.
As of version 1.8.4, samhain will by default compare
the number of hardlinks of a directory to the number of its
subdirectories (including "." and ".."). Normally, these
numbers should be equal. The idea here is that a (kernel)
rootkit may hide a directory, but fail to "fix" the parent
directory hardlink count (actually, I am not aware of any
kernel rootkit that would care to fix the hardlink count of
the parent directory). This is an experimental feature; if
there are any problems, it can be disabled with the option
no in the [Misc]
section of the configuration file.
Errors will be reported at the same severity as
directory access errors option
severity in section
This feature is not supported on MacOS X (because the resource fork is implemented as an invisible directory, it modifies the parent directory hardlink count.)
Some filesystems do not always follow the rule
mentioned above (directory hardlink equals number of
subdirectories). E.g. the root directory of reiserfs
partitions generally seems to have two additional
hardlinks. To account for such exceptions, you can
specify exceptions with the option
/path in the [Misc]
section of the configuration file. Here, N is the
numerical offset (actual - expected hardlinks) for
/path. For multiple exceptions, use this
options multiple times (note that '/path N:/path2' would
itself be a valid path, so using the option only once
with multiple exceptions on the same line would be
Please note that samhain will not check for an exception if the standard rule (offset = 0) is true for a directory. Thus it will not warn if a directory that once was exceptional is not anymore.
for weird filenames (containing control/nonprintable
characters, newlines or tabs) and warns about them at a
severity level that is set with
severity in section
[EventSeverity]. The rationale is: most of the time, such
names are either the result of user errors, buggy scripts,
or questionable activity.
If you want to add characters to the set of 'good'
ones, you can do so with the option:
N1, N2, ... in the
[Misc] section of the configuration file. Nn should be the
unsigned byte value of the character(s) in hex (leading
'0x': 0xNN), octal (leading zero: 0NNN), or decimal.
To specify that filenames are UTF-8 rather than ASCII, use FileNamesAreUTF8=yes . Samhain will check for invalid UTF-8 sequences, and for filenames ending with invisible characters.
This check will not be performed for files under the IgnoreAll policy. To completely disable this check, use AddOKChars=all .
prelink is a tool available on modern Linux systems that can significantly reduce the startup time of applications. It does this by performing some of the work of the dynamic linker in advance. As this changes both executables and shared libraries, file integrity verification will fail unless prelink is supported, in particular as prelinking has to be redone if libraries are updated (so initializing the checksum database after prelinking may not be good enough).
The disadvantage is that prelinking modifies libraries and executables, and may need to be redone (potentially modifying all or many executables again) if a library is updated. This is a major problem for file integrity checkers.
Version 2.0 of samhain and later support prelink. To use this support, you need to place prelinked executables and libraries (or directories holding them) under the [Prelink] policy rather than under the (e.g.) [ReadOnly] policy. For all files under the [Prelink] policy, inode, size, and timestamps will be ignored (prelinking changes them). In addition, for ELF binaries under the [Prelink] policy, /usr/sbin/prelink --verify will be used to compute checksums (i.e. the checksum will be computed on the output of this command). For other files, checksums are computed as usual.
Obviously, invoking prelink results in a significant overhead, and slows down file integrity checking (tests indicate a factor of three - your mileage may vary).
|Verification failures (zero checksum)|
It seems that prelink --verify fails if the dependencies of a prelinked binary have changed. This results in a zero checksum, and can be fixed by re-prelinking the affected binary.
There are two configuration options in the [Misc] section that can are relevant for prelink support:
fullpath sets the path
prelink executable. The default is
checksum sets the
TIGER192 checksum for the
prelink executable. You can compute this with
/usr/sbin/prelink (remove whitespace from the
computed checksum). If the checksum is set,
prelink executable immediately before using
prelink will be
used without this special precaution.
|Note for users of SQL database logging|
You need to update the database scheme before using this feature, if you are upgrading from a version below 2.3.0. See Section 12.1 for details.
As of version 2.3, samhain supports checking and verifying of SELinux attributes and/or Posix ACLs, if the operating system supports these features. SELinux attributes are a Linux-specific feature, while Posix ACLs are supported by multiple operating systems.
These features will only get compiled if the required development environment is available on the host where samhain is compiled (e.g. on Debian Linux, packages libattr1-dev and libacl1-dev).
For backward compatibility, these features are disabled by default, even if they are compiled in. To enable them, use the configuration directives:
[Misc] UseACLCheck = yes UseSelinuxCheck = yes
As of version 1.8.2, reports about modified files include a short code in the message field to describe which properties have been modified. The codes are: 'C' for 'checksum', 'L' for (soft) 'link', 'D' for 'device number', 'I' for 'inode', 'H' for (number of) 'hardlinks', 'M' for 'mode', 'U' for 'user' (owner), 'G' for 'group' (owner), 'T' for 'time' (any), and finally 'S' for 'size'.
As an example, 'C--I----TS' would indicate that a file has been replaced by one with different checksum, inode, timestamp, and size, but (e.g.) same mode (type and access permissions) and same ownership.
If files are added to, or removed from a directory,
or modified by writing a temporary file and renaming it to
report the changed file as well as the changed directory
inode. If you regard the report on the directory inode as
redundant, you can suppress it with the option:
true in the [Misc]
section of the configuration file. This will cause
samhain to ignore
modified directory inodes if nothing else but size and
timestamps has changed.
This is discussed in Section 20 .
First of all, the UID of the user who changed or created a file is not stored in the file metadata, and hence in general not available. However, some operating systems may have non-standard security enhancements to log such information.
In particular, sufficiently recent versions of the Linux kernel provide an audit subsystem that can be used to gather such information if the required userspace tools are installed and the system is properly configured.
It should be noted that the Linux audit subsystem does NOT audit every file access by default. Rather, files are only audited if a watch is placed on them. What Samhain can do is making sure that watches are indeed placed on all files of interest for you (as defined in the Samhain configuration file), and collecting relevant information in case of an event.
Samhain supports the Linux audit system insofar as it can automatically mark files of interest for logging, and automatically collects and reports the log information after a change has been detected. This implies that you don't need to maintain two separate configurations (one for Samhain and one for the audit daemon).
If you compile a Samhain standalone or client executable on a Linux system, support for the Linux audit system will be compiled in automatically if the required development packages for libaudit and libauparse are present (Debian: libaudit-dev, RedHat: audit-libs-devel).
To verify that the compiled executable has audit support, use samhain --version, which should list "optionally report auditd record of changed file".
|Not supported with static compiling|
This extension is incompatible with static compiling, i.e. it is not available if '--enable-static' has been used for compiling.
(1) If you want Samhain to report who changed a file, you need to have the Linux audit daemon (Debian: auditd, RedHat: audit) installed. You also need to have the libaudit and libauparse libraries installed.
The audit daemon must be running. You can check that with the command auditctl -s , which should show a non-zero PID for the audit daemon. If it says 'pid=0', you need to enable the audit daemon. First, make sure the daemon will autostart on boot: on RedHat/CentOS use chkconfig auditd on , on Debian/Ubuntu use update-rc.d auditd defaults . Second, start the daemon with /etc/init.d/auditd start .
(2) You are most likely interested in the auid, i.e. the audit UID which tracks the login user. This UID is only set correctly if you are using the pam_loginuid PAM module, and in a correct way even. Please read the man page for pam_loginuid carefully, and add the line
session required pam_loginuid.so
to the files
Do NOT add this line to
that will set auid=0 and hence erase the track of the
If your system has a
file, don't add it
there if that file is included by the
(3) The audit daemon enables the audit system in the kernel. Therefore all processes starting earlier than the audit daemon itself may get an auid=4294967295 (unknown). To avoid this problem, add audit=1 to the kernel boot parameters.
(4) Because Samhain
needs to fetch the audit information from the audit log, this
log needs to be current. I.e. in the audit deamon configuration
/etc/audit/auditd.conf on Ubuntu),
the parameter 'flush' must be set to DATA or SYNC, otherwise
it might happen that the log entry has not been written yet
when Samhain tries
to fetch it.
In order to activate this feature for some particular file or directory, you have to add the AUDIT flag to the policy under which you place the file or directory (see Section 4.1 ). Note that placing an audit rule on a directory will cause the whole file hierarchy under that directory to be audited. Also note that you cannot place an audit rule on the root directory itself. This is a limitation of the Linux audit system itself, not of Samhain. You have to place audit rules on the individual directories in the root directory.
[Misc] RedefReadOnly = +AUDIT # [ReadOnly] file = /etc/login.defs dir = /bin
By default, Samhain
will set the flags "wa" (write|attribute change) on
which the watch will trigger. If you want to use other flags
(e.g. "r" for read), you can do so with the
r|w|x|a (i.e. any
combination of these four characters, see also
man 8 auditctl). Please note that order
matters (as with Redef... directives), i.e. this will
affect only files/directories specified afterwards in the
The rules set by Samhain are flagged with samhain, i.e. you can check them with auditctl -l -k samhain, and delete them manually with auditctl -D -k samhain. See the man page of the auditctl command for further reference.
If you want to verify that the audit system works properly, you can e.g. use ausearch -k samhain to see all audit log entries generated by rules flagged with 'samhain', i.e. inserted by Samhain.
|Persistance of audit rules|
If Samhain runs in the foreground, it will not delete the inserted rules upon exit. This is to ensure that file changes are still audited as desired when Samhain is run only occasionally or at fixed intervals (e.g. as a cron job). If you want to delete the rules, use the command auditctl -D -k samhain .
Checksumming can put a high I/O load on a machine, and in some cases one might want to skip this for particular files. As of version 2.8.2, Samhain allows to specify certain conditions for which checksumming of a file should be skipped. These are:
- match_prefix( string )
Skip checksumming if the full path of the file starts with the given string (e.g.: /home/someuser).
- match_regex( regular_expression )
Skip checksumming if the full path of the file matches the given POSIX regular expression (e.g.: .*\.mpg$).
- size_exceeds( bytes )
Skip checksumming if the filesize exceeds the given size (in bytes).
- match_permission( octal_perm )
Skip checksumming if the file permissions exactly match the given one (as octal number, e.g. 0755 for rwxr-xr-x, or 4755 for rwsr-xr-x).
- have_permission( octal_perm )
Skip checksumming if the file permissions include the given one (as octal number, e.g. 0100 for execute by owner).
- match_filetype( filetype )
Skip checksumming if the file is of some particular type. See appendix for a list of supported file types.
Files that should
not be checksummed are specified with
list of conditions in
the [Misc] section of the configuration file. The following
To negate a condition, place an exclamation mark ('!') in front of it.
All conditions in the given list are and ed, i.e. checksumming for a file is skipped only if all conditions in the list are true. E.g. you can place a match_prefix(string) condition at the start of the list to avoid evaluation of the following condition(s) for files that should not be skipped.
If more than one SkipChecksum=... directives are given, then they are or ed, i.e. checksumming for a file is skipped if one of the directives matches.
It is possible to add (at most 16) user-defined
filetype descriptions to the compiled-in list. This can
be done with the directive
description where the
description is 8 fields, separated by
The 8 fields are offset:type:length:G1:G2:G3:Name:Teststring, which describe:
An optional offset into the file, can be at most 3072-length. Counting starts at 0, thus '6' would mean the 7th byte of the file.
Type is 0 for a C string, 1 if binary, i.e. if the teststring contains NULL bytes,
Length should be 0 if the type is 0, othewise the length of the teststring if it is of type 1 (binary).
G1, G2, G2 give the filetype as GENERIC:MORE_SPECIFIC:EXACT, e.g. IMAGE:COMPRESSED:JPG
The name field is currently unused and should hold a human-understandable description, e.g. 'Jpeg image'
The teststring is a string or byte pattern that is found at the given offset in files of this type. You can use quoted-printable (qp) encoding (which is often used for e-mail) for arbitrary binary patterns. A qp-encoded character (byte) consists of 3 characters: a "=" followed by the two-digit hexadecimal value if the byte. Please note that NULL bytes MUST be qp-encoded as '=00', and the equal sign ('=') MUST be qp-encoded as '=3D'.
A valid example would be
Jpeg:JFIF (this one is already
compiled in). This would recognize any file with the
string 'JFIF' starting at the 7th byte (counting starts
at '0') as a Jpeg image.
Growing log files should be placed under the [GrowingLogFiles] policy which (as of 3.0.11+) uses the following logic to handle log rotation:
If the size has shrunk (e.g. because of log rotation), samhain will look for a file with the same inode as before and check whether it has a size >= previous_size, and checksum(file start up to previous size) equal to the previous checksum. No report will be issued if this check succeeds. Thus log rotation will be handled gracefully as long as the inode is kept (i.e. the old file is moved rather than copied) and the first rotated file is not compressed (the logrotate tool can be told to compress only after the second cycle, and on Debian this seems to be standard anyway).
Samhain will report on files that are unowned (i.e. belong to a UID/GID that is not associated with an existing user or group. The rationale is that this is a security risk. An administrator (or administrative script) may get tricked into creating a user/group for that UID/GID, thus allowing the freshly created user/group to hijack the unowned files.
As of version 4.3.0, on Linux Samhain will ignore unowned files
if the UID/GID is mapped in a user namespace
/etc/subgid files respectively.