Saturday 19 March 2011

Linux File Access Auditing.

Most companies which are required to conform to a certain level of compliance (e.g. PCI) must monitor file access on those particular machines within the compliance scope. In this article I will be explaining how we can set up file system auditing on CentOS/Red Hat Enterprise Linux using the inbuilt tool auditd, what is involved in the logs and how we can produce some basic reporting.

Auditd has 2 configuration files you need to care about:
/etc/audit/auditd.conf - configuration file for audit daemon.
/etc/audit/audit.rules - audit rules to be loaded at startup.
An example configuration rule found in audit.rules would be:
-w /root/ -p rwxa -k pci
This informs the kernel to watch the directory /root/ and any reads, writes, executes and attribute changes to any files found within that directory will be recorded and be tagged as pci.

Breaking down the rule:
-w - Informs the kernel to watch a directory.
/root/ - Is the file directory to be watched.
-p - The permissions filter (what we want to look for).
rwxa - The permissions within scope of the filter - r = reads, w = write, x = execute and a = attribute change.
-k - If the rule has been triggered by an event, it is given a key (like tagging it).
pci - The key name used (can be searched upon (more further down)).
Once an event meets all of your criteria as stated above, the event will then be written to the file:
/var/log/audit/audit.log
You can then simply such read the log (cat|grep|less|more|tail|vi), suck it into your SIEM of choice or use the prebuilt tools ausearch and aureport.
type=SYSCALL msg=audit(1300468311.245:44): arch=c000003e syscall=2 success=yes exit=0 a0=7fffa67a3c3c a1=941 a2=1b6 a3=351e75210c items=2 ppid=3498 pid=3560 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=4 comm="touch" exe="/bin/touch" subj=root:system_r:unconfined_t:s0-s0:c0.c1023 key="pci"

type=CWD msg=audit(1300468311.245:44): cwd="/root"

type=PATH msg=audit(1300468311.245:44): item=0 name="/root" inode=2119521 dev=fd:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0

type=PATH msg=audit(1300468311.245:44): item=1 name="test" inode=2119544 dev=fd:00 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0
As you can see there are 4 events which, when pieced together will illustrate the actions which that user has taken. When we analyse the first event we notice the following:
type=SYSCALL - The type of event.
msg=audit(1300468311.245:44): - Timestamp and unique number to assist in correlating matching events.
arch=c000003e - System architecture x86_64
syscall=2 - System call 2 was executed.
success=yes - Axiomatic.
exit=0 - Exit status of 0 means it was successful.
a0=7fffa67a3c3c - Syscall argument 1.
a1=941 - Syscall argument 2.
a2=1b6 - Syscall argument 3.
a3=351e75210c - Syscall argument 4.
items=2 - Arguments passed to the syscall - checking the 2 PATH events below.
ppid=3498 - The parent processes PID.
pid=3560 - The PID of the process.
auid=0 - The audit ID, this remains even if the user changes username (e.g. sudo|su).
uid=0 - The user ID.
gid=0 - The group ID
euid=0 - Effective user ID.
suid=0 - Set user ID.
fsuid=0 - File system user ID
egid=0 - Effective group ID.
sgid=0 - Set group ID.
fsgid=0 - File system group ID.
tty=pts1 - The terminal which was used.
ses=4 - No Clue
comm="touch" - Name of the program.
exe="/bin/touch" - Full path name of program
subj=root:system_r:unconfined_t:s0-s0:c0.c1023 - Security context - SELinux.
key="pci" - Key assigned to the matching event.
This, once broken down, is not as daunting as it may first seem, the following event then gives us context of what was the current working directory of that user when they triggered that event.
type=CWD - The type of event.
msg=audit(1300468311.245:44): - Timestamp and unique number to assist in correlating matching events (same as previous event).
cwd="/root" - The current working environment of that user.
Finally there is only PATH events left, one for the dirname of the file in question (the containing directories (e.g. /root/)) and the second for the basename of the file (the file name (e.g. ./test)).
type=PATH - The type of event.
msg=audit(1300468311.245:44): - Timestamp and unique number to assist in correlating matching events (same as the two previous events).
item=0 - The first of the arguments passed.
name="/root" - The dirname (containing directory) of the watched file/directory.
inode=2119521 - The inode of the watched dirname.
dev=fd:00 - The device in which the event happened on.
mode=040750 - The file access permissions currently in place on that file/directory (750|rwxr-x---).
ouid=0 - Inode's user ID.
ogid=0 - Inode's group ID.
rdev=00:00 - Block chapter device.
obj=root:object_r:user_home_dir_t:s0 - Security context - SELinux.
Finally we have the object being read/modified.
type=PATH - The type of event.
msg=audit(1300468311.245:44): - Timestamp and unique number to assist in correlating matching events (same as the two previous events).
item=1 - The second of the arguments passed.
name="test" - The basename (actual file/directory) of the watched file/directory.
inode=2119544 - The inode of the watched basename.
dev=fd:00 - The device in which the event happened on.
mode=0100644 - The file access permissions currently in place on file/directory found in the key "name" (644|rw-r--r--).
ouid=0 - Inode's user ID.
ogid=0 - Inode's group ID.
rdev=00:00 - Block chapter device.
obj=root:object_r:user_home_t:s0 - Security context - SELinux.
Finally, we have an entire list of what happened (within reason) to our file/directory. However, we do not know if the file/directory was just read or altered, to determine this we must set different filters and then differentiate them with different keys.
-w /root/ -p r -k read -k pci
-w /root/ -p w -k write -k pci
-w /root/ -p x -k execute -k pci
-w /root/ -p a -k attribute -k pci
However, the key is now:
key=777269746501706369
This is a hash of the two keys (in this case write and pci) which has been amalgamated into one. We can search through these logs and against the multiple keys using ausearch:
ausearch -k pci -k write
Which will result in:
time->Fri Mar 18 19:20:20 2011 
type=PATH msg=audit(1300476020.864:378): item=1 name="test2" inode=2119544 dev=fd:00 mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0 
type=PATH msg=audit(1300476020.864:378): item=0 name="/root" inode=2119521 dev=fd:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0 
type=CWD msg=audit(1300476020.864:378): cwd="/root" 
type=SYSCALL msg=audit(1300476020.864:378): arch=c000003e syscall=2 success=yes exit=0 a0=7fffbb5d0c1a a1=941 a2=1b6 a3=351e75210c items=2 ppid=4476 pid=4700 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4 comm="touch" exe="/bin/touch" subj=root:system_r:unconfined_t:s0-s0:c0.c1023 key=777269746501706369
This is very nice, however auditd hides one more trick up it's sleeve, aureport. Though aureport might not be the best reporting agent for Linux based data, it is however, very nice for quick summaries of your data and is easy to use. It requires the user to pipe the results of ausearch into aureport:
ausearch -k pci -k pci -k write | aureport
Which will produce:
Summary Report
======================
Range of time in logs: 04/17/1493088 16:14:57.8968 - 03/18/2011 19:20:20.864
Selected time for report: 04/17/1493088 16:14:57 - 03/18/2011 19:20:20.864
Number of changes in configuration: 2
Number of changes to accounts, groups, or roles: 0
Number of logins: 0
Number of failed logins: 0
Number of authentications: 0
Number of failed authentications: 0
Number of users: 1
Number of terminals: 1
Number of host names: 0
Number of executables: 3
Number of files: 7
Number of AVC's: 0
Number of MAC events: 0
Number of failed syscalls: 0
Number of anomaly events: 0
Number of responses to anomaly events: 0
Number of crypto events: 0
Number of keys: 2
Number of process IDs: 5
Number of events: 30
Have a good week.

Thomas Knowles

No comments:

Post a Comment