auditd<\/a><\/code><\/strong> (Audit daemon). auditd keeps track of all the changes happening on the system and generate logs that can be analyzed so as to get an insight into system security posture. This include finding out who edit what files at what specific time.<\/p>\n\n\n\nFinding out who Edited Files in Linux<\/h2>\n\n\n\n
There is no easy way of finding out who made changes to what files in Linux. However, auditd makes this process a simple one.<\/p>\n\n\n\n
Install Audit Packages in Linux<\/h3>\n\n\n\n
To begin with, install audit packages in Linux.<\/p>\n\n\n\n
On RHEL-based distribution:<\/p>\n\n\n\n
yum install audit -y<\/code><\/pre>\n\n\n\nOn Debian-based distros;<\/p>\n\n\n\n
apt install auditd -y<\/code><\/pre>\n\n\n\nAudit User-space Tools<\/h3>\n\n\n\n
Audit Package ships with different user-space tools with different functionalities. These include:<\/p>\n\n\n\n
\nauditd<\/code><\/strong> is the user-space component which is responsible for writing audit records to the disk.<\/li>\n\n\n\nausearch<\/code><\/strong> which is the user-space component for querying audit daemon logs.<\/li>\n\n\n\naureport<\/code><\/strong> which is the user-space component that produces summary reports of the audit system logs.<\/li>\n\n\n\nauditctl<\/code><\/strong> which is the program is used to configure kernel options related to auditing, to see status of the configuration, and to load discretionary audit rules. When system boots, auditctl<\/code><\/strong> reads the rules in \/etc\/audit\/audit.rules and load them into the kernel.<\/li>\n<\/ul>\n\n\n\nRunning Auditd Service in Linux<\/h3>\n\n\n\n
When installed, Audit daemon service is started and enabled to run on system boot;<\/p>\n\n\n\n
To check the status;<\/p>\n\n\n\n
systemctl status auditd<\/code><\/pre>\n\n\n\n\u25cf auditd.service - Security Auditing Service\n Loaded: loaded (\/lib\/systemd\/system\/auditd.service; enabled; vendor preset: enabled)\n Active: active (running) since Wed 2021-12-08 17:52:49 EAT; 25min ago\n Docs: man:auditd(8)\n https:\/\/github.com\/linux-audit\/audit-documentation\n Process: 1336 ExecStart=\/sbin\/auditd (code=exited, status=0\/SUCCESS)\n Process: 1340 ExecStartPost=\/sbin\/augenrules --load (code=exited, status=0\/SUCCESS)\n Main PID: 1337 (auditd)\n Tasks: 2 (limit: 5902)\n Memory: 616.0K\n CPU: 25ms\n CGroup: \/system.slice\/auditd.service\n \u2514\u25001337 \/sbin\/auditd\n\nDec 08 17:52:49 debian11 augenrules[1350]: enabled 1\nDec 08 17:52:49 debian11 augenrules[1350]: failure 1\nDec 08 17:52:49 debian11 augenrules[1350]: pid 1337\nDec 08 17:52:49 debian11 augenrules[1350]: rate_limit 0\nDec 08 17:52:49 debian11 augenrules[1350]: backlog_limit 8192\nDec 08 17:52:49 debian11 augenrules[1350]: lost 0\nDec 08 17:52:49 debian11 augenrules[1350]: backlog 0\nDec 08 17:52:49 debian11 augenrules[1350]: backlog_wait_time 60000\nDec 08 17:52:49 debian11 augenrules[1350]: backlog_wait_time_actual 0\nDec 08 17:52:49 debian11 systemd[1]: Started Security Auditing Service.\n<\/code><\/pre>\n\n\n\nMonitor File Changes in Linux using Auditd<\/h3>\n\n\n\n
Note that there are various audit rules that defines how to track system changes. These include:<\/p>\n\n\n\n
\nControl rules<\/code><\/strong>: Allow the modification of the audit system’s behavior and some of its configuration.<\/li>\n\n\n\nFile system rules<\/strong><\/code>: allow the auditing of access to a particular file or a directory. These are also known as file watches.<\/li>\n\n\n\nSystem call rules<\/strong><\/code>: Allow logging of system calls that any specified program makes.<\/li>\n<\/ul>\n\n\n\nWe are only interested in file system audit rules as these enables us to monitor file changes in Linux<\/p>\n\n\n\n
As stated above, auditctl<\/strong><\/code> utility can be used to configure audit rules.<\/p>\n\n\n\nConfigure Runtime File system Audit Rules<\/h4>\n\n\n\n
You can configure runtime File system audit rules on command line using auditctl<\/code><\/strong> command. The syntax is;<\/p>\n\n\n\nauditctl -w path_to_file<\/em><\/strong> -p access_permissions<\/em><\/strong> -k filter_key<\/em><\/strong><\/code><\/pre>\n\n\n\nThe options used are:<\/p>\n\n\n\n
\n-w path_to_file<\/em><\/code><\/strong>: defines a path to file system object being monitored.<\/li>\n\n\n\n-p access_permissions<\/em><\/strong><\/code>: (-p [r|w|x|a]<\/code><\/strong>) Describe the permission access type that a file system watch will trigger on. r=read, w=write, x=execute, a=attribute change. Note that these are not the standard file permissions, but rather the kind of syscall that would do this kind of thing.<\/li>\n\n\n\n-k filter_key<\/em><\/strong><\/code>: defines an arbitrary string of text that can be up to 31 bytes long. It can uniquely identify the audit records produced by a rule.<\/li>\n<\/ul>\n\n\n\nTake for example we want to watch read\/write and attribute changes to the file, \/etc\/ssh\/sshd_config<\/code>, then you would define a rule like;<\/p>\n\n\n\nauditctl -w \/etc\/ssh\/sshd_config -p wax -k monitor_sshd_conf<\/code><\/pre>\n\n\n\nTo list the rules;<\/p>\n\n\n\n
auditctl -l<\/code><\/pre>\n\n\n\nSample output;<\/p>\n\n\n\n
-w \/etc\/ssh\/sshd_config -p wxa -k monitor_sshd_conf<\/code><\/pre>\n\n\n\nTo test this rule, try to modify the \/etc\/ssh\/sshd_config<\/code><\/strong> file. As non root user, run the command like this;<\/p>\n\n\n\necho \"AllowUsers kifarunix root\" | sudo tee -a \/etc\/ssh\/sshd_config<\/code><\/pre>\n\n\n\nIf you want to stop monitoring the file using auditctl;<\/p>\n\n\n\n
auditctl -W<\/strong> \/etc\/ssh\/sshd_config -p wax -k monitor_sshd_conf<\/code><\/pre>\n\n\n\nConfigure Persistent File system Audit Rules<\/h4>\n\n\n\n
To configure permanent rules that persists across system reboots, you can place the rules under \/etc\/audit\/audit.rules<\/strong><\/code> or place them under \/etc\/audit\/rules.d\/<\/strong><\/code>.<\/p>\n\n\n\nRules on the file, \/etc\/audit\/audit.rules<\/strong><\/code>, are generated from the rules defined under the \/etc\/audit\/rules.d\/<\/strong><\/code> directory.<\/p>\n\n\n\nIf the rules are placed under \/etc\/audit\/rules.d\/<\/code>, you need to load them using the augenrules<\/code><\/strong> utility.<\/p>\n\n\n\nFor example;<\/p>\n\n\n\n
echo \"-w \/etc\/ssh\/sshd_config -p wxa -k monitor_sshd_conf\" > \/etc\/audit\/rules.d\/sshd.rules<\/code><\/pre>\n\n\n\nCheck the if the changes are detected;<\/p>\n\n\n\n
augenrules --check<\/code><\/pre>\n\n\n\nThe load the rules;<\/p>\n\n\n\n
augenrules --load<\/code><\/pre>\n\n\n\nThis should update the file, \/etc\/audit\/audit.rules<\/strong><\/code>.<\/p>\n\n\n\nRestart auditd service;<\/p>\n\n\n\n
systemctl restart auditd<\/code><\/pre>\n\n\n\nListing the rules;<\/p>\n\n\n\n
auditctl -l<\/code><\/pre>\n\n\n\n-w \/etc\/ssh\/sshd_config -p wxa -k monitor_sshd_conf<\/code><\/pre>\n\n\n\nViewing Audit Rule Logs<\/h4>\n\n\n\n
There are various ways in which you can view Audit log records.<\/p>\n\n\n\n
\n- Reading the Audit log file,
\/var\/log\/audit\/audit.log<\/strong><\/code>.<\/li>\n<\/ul>\n\n\n\ngrep --color monitor_sshd_conf \/var\/log\/audit\/audit.log<\/code><\/pre>\n\n\n\ntype=CONFIG_CHANGE msg=audit(1638984278.290:13): auid=1000 ses=3 subj==unconfined op=add_rule key=\"monitor_sshd_conf\" list=4 res=1AUID=\"kifarunix\"\ntype=SYSCALL msg=audit(1638984357.760:38): arch=c000003e syscall=257 success=yes exit=3 a0=ffffff9c a1=7fffe54487de a2=441 a3=1b6 items=2 ppid=987 pid=988 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=5 comm=\"tee\" exe=\"\/usr\/bin\/tee\" subj==unconfined key=\"monitor_sshd_conf\"ARCH=x86_64 SYSCALL=openat AUID=\"kifarunix\" UID=\"root\" GID=\"root\" EUID=\"root\" SUID=\"root\" FSUID=\"root\" EGID=\"root\" SGID=\"root\" FSGID=\"root\"\n<\/code><\/pre>\n\n\n\n\n- Generate a report using aureport (read more on
man aureport<\/strong><\/code>)<\/li>\n<\/ul>\n\n\n\naureport -i -k<\/code><\/pre>\n\n\n\n\nKey Report\n===============================================\n# date time key success exe auid event\n===============================================\n1. 12\/08\/2021 20:24:38 monitor_sshd_conf yes ? kifarunix 13\n2. 12\/08\/2021 20:25:57 monitor_sshd_conf yes \/usr\/bin\/tee kifarunix 38\n<\/code><\/pre>\n\n\n\n\n- Search the logs with ausearch command (read more on
man ausearch<\/code><\/strong>).<\/li>\n<\/ul>\n\n\n\nausearch -i -k monitor_sshd_conf<\/code><\/pre>\n\n\n\n----\ntype=CONFIG_CHANGE msg=audit(12\/08\/2021 20:24:38.290:13) : auid=kifarunix ses=3 subj==unconfined op=add_rule key=monitor_sshd_conf list=exit res=yes \n----\ntype=PROCTITLE msg=audit(12\/08\/2021 20:25:57.760:38) : proctitle=tee -a \/etc\/ssh\/sshd_config \ntype=PATH msg=audit(12\/08\/2021 20:25:57.760:38) : item=1 name=\/etc\/ssh\/sshd_config inode=526305 dev=08:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 \ntype=PATH msg=audit(12\/08\/2021 20:25:57.760:38) : item=0 name=\/etc\/ssh\/ inode=523877 dev=08:01 mode=dir,755 ouid=root ogid=root rdev=00:00 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0 \ntype=CWD msg=audit(12\/08\/2021 20:25:57.760:38) : cwd=\/home\/kifarunix \ntype=SYSCALL msg=audit(12\/08\/2021 20:25:57.760:38) : arch=x86_64 syscall=openat success=yes exit=3 a0=0xffffff9c a1=0x7fffe54487de a2=O_WRONLY|O_CREAT|O_APPEND a3=0x1b6 items=2 ppid=987 pid=988 auid=kifarunix uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts1 ses=5 comm=tee exe=\/usr\/bin\/tee subj==unconfined key=monitor_sshd_conf \n<\/code><\/pre>\n\n\n\nFrom the ausearch report output, let’s try to interpret the records fields.<\/p>\n\n\n\n
\n- type=PROCTITLE<\/strong>: Record type which gives the full command-line that triggered this Audit event.<\/li>\n\n\n\n
- msg=audit(12\/08\/2021 20:24:38.290:13)<\/strong>: Defines a timestamp and a unique ID of the record in the form
audit(time_stamp<\/em>:ID<\/em>)<\/code>. Time usually shows in EPOCH unless you use option -i<\/strong>.<\/li>\n<\/ul>\n\n\n\nIf time is in EPOCH, e.g 1638984357.760<\/code>. then convert using date command;<\/p>\n\n\n\ndate -d @1638984357.760<\/code><\/pre>\n\n\n\nWed 08 Dec 2021 08:25:57 PM EAT<\/code><\/pre>\n\n\n\n\n- proctitle=tee -a \/etc\/ssh\/sshd_config<\/strong>: The field records the full command-line of the command that was used to invoke the analyzed process. Without option -i, this would have been displayed in hexadecimal.<\/li>\n\n\n\n
- type=PATH<\/strong>: record type PATH records the path that is passed to the system call as an argument, in this case the path is \/etc\/ssh\/sshd_config.<\/li>\n\n\n\n
item=1<\/strong><\/code>: The item<\/code> field indicates which item, of the total number of items referenced in the SYSCALL<\/code> type record, the current record is. a value of 1 means it is the second item.<\/li>\n\n\n\nname=\/etc\/ssh\/sshd_config<\/strong><\/code>: The records the path of the file or directory that was passed to the system call as an argument. In this case, it was the \/etc\/ssh\/sshd_config<\/code> file.<\/li>\n\n\n\ninode=526305<\/strong><\/code>: The inode<\/code> field contains the inode number associated with the file or directory recorded in this event. The following command displays the file or directory that is associated with the 526305 inode number:<\/li>\n<\/ul>\n\n\n\nfind \/ -inum 526305 -print<\/code><\/pre>\n\n\n\n\/etc\/ssh\/sshd_config<\/code><\/pre>\n\n\n\n\ndev=08:01<\/strong><\/code>: The field specifies the minor and major ID of the device that contains the file or directory recorded in this event.<\/li>\n\n\n\n- mode=file,644<\/strong>: The mode field records the file or directory permissions, 644 means -rw-r–r– for the \/etc\/ssh\/sshd_config file.<\/li>\n\n\n\n
ouid=root<\/code><\/strong>: The ouid field records the object owner’s user ID\/username.<\/li>\n\n\n\nogid=root<\/code><\/strong>: The ogid field records the object owner’s group ID\/username.<\/li>\n\n\n\nrdev=00:00<\/code><\/strong>: The rdev field contains a recorded device identifier for special files only. In this case, it is not used as the recorded file is a regular file.<\/li>\n\n\n\nnametype=NORMAL<\/code><\/strong>: records the intent of each path record’s operation in the context of a given syscall.<\/li>\n\n\n\ncap_fp=none<\/code><\/strong>: The cap_fp field records data related to the setting of a permitted file system-based capability of the file or directory object.<\/li>\n\n\n\ncap_fi=none<\/code><\/strong>: The cap_fi field records data related to the setting of an inherited file system-based capability of the file or directory object.<\/li>\n\n\n\ncap_fe=0<\/code><\/strong>: The cap_fe field records the setting of the effective bit of the file system-based capability of the file or directory object.<\/li>\n\n\n\ncap_fver=0<\/code><\/strong>: The cap_fver field records the version of the file system-based capability of the file or directory object.<\/li>\n\n\n\ntype=CWD<\/strong><\/code>: records the working directory from which the process that invoked the system call was executed.<\/li>\n\n\n\ncwd=\/home\/kifarunix<\/strong><\/code>: specifies directory in which the system call was invoked.<\/li>\n\n\n\ntype=SYSCALL<\/code><\/strong>: specifies that the record was triggered by a system call to the kernel.<\/li>\n\n\n\narch=x86_64<\/code><\/strong>: The field contains information about the CPU architecture of the system. Unless option -i is used with auseardh, the value is shown hexadecimal notation.<\/li>\n\n\n\nsyscall=openat<\/code><\/strong>: The syscall field records the type of the system call that was sent to the kernel. When option -i is used with ausearch, the values are interpreted, otherwise numeric values are shown. Use the ausyscall --dump<\/code><\/strong> command to display a listing of all system calls along with their numbers. For more information, see man ausyscall<\/strong>.<\/li>\n\n\n\nsuccess=yes<\/code><\/strong>: The success field records whether the system call recorded in that particular event succeeded or failed. In this case, the call succeeded.<\/li>\n\n\n\n- exit=3<\/strong>: The field contains a value that specifies the exit code returned by the system call. This value varies for different system call.<\/li>\n\n\n\n
a0=0xffffff9c a1=0x7fffe54487de a2=O_WRONLY|O_CREAT|O_APPEND a3=0x1b6<\/code><\/strong>: The a0 to a3 fields record the first four arguments, encoded in hexadecimal notation, of the system call in this event. These arguments depend on the system call that is used.<\/li>\n\n\n\nitems=2<\/code><\/strong>: The items field contains the number of PATH auxiliary records that follow the syscall record.<\/li>\n\n\n\nppid=987<\/code><\/strong>: The ppid field records the Parent Process ID (PPID).<\/li>\n\n\n\npid=988<\/code><\/strong>: The pid field records the Process ID (PID).<\/li>\n\n\n\nauid=kifarunix<\/code><\/strong>: The auid field records the Audit user ID, that is the loginuid. This ID is assigned to a user upon login and is inherited by every process even when the user’s identity changes, for example, by switching user accounts.<\/li>\n\n\n\nuid=root<\/code><\/strong>: The uid field records the user ID of the user who started the analyzed process. The user ID can be interpreted into user names when -i option is used with ausearch. You can also interpret with the following command: ausearch -i –uid UID.<\/li>\n\n\n\ngid=root<\/code><\/strong>: The gid field records the group ID of the user who started the analyzed process.<\/li>\n\n\n\neuid=root<\/strong><\/code>: The euid field records the effective user ID of the user who started the analyzed process.<\/li>\n\n\n\nsuid=root<\/strong><\/code>: The suid field records the set user ID of the user who started the analyzed process.<\/li>\n\n\n\nfsuid=root<\/code><\/strong>: The fsuid field records the file system user ID of the user who started the analyzed process.<\/li>\n\n\n\n