In this tutorial, you will learn how to find out who edited files in Linux. Linux provides user space tools for security auditing called auditd
(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.
Finding out who Edited Files in Linux
There is no easy way of finding out who made changes to what files in Linux. However, auditd makes this process a simple one.
Install Audit Packages in Linux
To begin with, install audit packages in Linux.
On RHEL-based distribution:
yum install audit -y
On Debian-based distros;
apt install auditd -y
Audit User-space Tools
Audit Package ships with different user-space tools with different functionalities. These include:
auditd
is the user-space component which is responsible for writing audit records to the disk.ausearch
which is the user-space component for querying audit daemon logs.aureport
which is the user-space component that produces summary reports of the audit system logs.auditctl
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
reads the rules in /etc/audit/audit.rules and load them into the kernel.
Running Auditd Service in Linux
When installed, Audit daemon service is started and enabled to run on system boot;
To check the status;
systemctl status auditd
● auditd.service - Security Auditing Service
Loaded: loaded (/lib/systemd/system/auditd.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2021-12-08 17:52:49 EAT; 25min ago
Docs: man:auditd(8)
https://github.com/linux-audit/audit-documentation
Process: 1336 ExecStart=/sbin/auditd (code=exited, status=0/SUCCESS)
Process: 1340 ExecStartPost=/sbin/augenrules --load (code=exited, status=0/SUCCESS)
Main PID: 1337 (auditd)
Tasks: 2 (limit: 5902)
Memory: 616.0K
CPU: 25ms
CGroup: /system.slice/auditd.service
└─1337 /sbin/auditd
Dec 08 17:52:49 debian11 augenrules[1350]: enabled 1
Dec 08 17:52:49 debian11 augenrules[1350]: failure 1
Dec 08 17:52:49 debian11 augenrules[1350]: pid 1337
Dec 08 17:52:49 debian11 augenrules[1350]: rate_limit 0
Dec 08 17:52:49 debian11 augenrules[1350]: backlog_limit 8192
Dec 08 17:52:49 debian11 augenrules[1350]: lost 0
Dec 08 17:52:49 debian11 augenrules[1350]: backlog 0
Dec 08 17:52:49 debian11 augenrules[1350]: backlog_wait_time 60000
Dec 08 17:52:49 debian11 augenrules[1350]: backlog_wait_time_actual 0
Dec 08 17:52:49 debian11 systemd[1]: Started Security Auditing Service.
Monitor File Changes in Linux using Auditd
Note that there are various audit rules that defines how to track system changes. These include:
Control rules
: Allow the modification of the audit system’s behavior and some of its configuration.File system rules
: allow the auditing of access to a particular file or a directory. These are also known as file watches.System call rules
: Allow logging of system calls that any specified program makes.
We are only interested in file system audit rules as these enables us to monitor file changes in Linux
As stated above, auditctl
utility can be used to configure audit rules.
Configure Runtime File system Audit Rules
You can configure runtime File system audit rules on command line using auditctl
command. The syntax is;
auditctl -w path_to_file -p access_permissions -k filter_key
The options used are:
-w path_to_file
: defines a path to file system object being monitored.-p access_permissions
: (-p [r|w|x|a]
) 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.-k filter_key
: 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.
Take for example we want to watch read/write and attribute changes to the file, /etc/ssh/sshd_config
, then you would define a rule like;
auditctl -w /etc/ssh/sshd_config -p wax -k monitor_sshd_conf
To list the rules;
auditctl -l
Sample output;
-w /etc/ssh/sshd_config -p wxa -k monitor_sshd_conf
To test this rule, try to modify the /etc/ssh/sshd_config
file. As non root user, run the command like this;
echo "AllowUsers kifarunix root" | sudo tee -a /etc/ssh/sshd_config
If you want to stop monitoring the file using auditctl;
auditctl -W /etc/ssh/sshd_config -p wax -k monitor_sshd_conf
Configure Persistent File system Audit Rules
To configure permanent rules that persists across system reboots, you can place the rules under /etc/audit/audit.rules
or place them under /etc/audit/rules.d/
.
Rules on the file, /etc/audit/audit.rules
, are generated from the rules defined under the /etc/audit/rules.d/
directory.
If the rules are placed under /etc/audit/rules.d/
, you need to load them using the augenrules
utility.
For example;
echo "-w /etc/ssh/sshd_config -p wxa -k monitor_sshd_conf" > /etc/audit/rules.d/sshd.rules
Check the if the changes are detected;
augenrules --check
The load the rules;
augenrules --load
This should update the file, /etc/audit/audit.rules
.
Restart auditd service;
systemctl restart auditd
Listing the rules;
auditctl -l
-w /etc/ssh/sshd_config -p wxa -k monitor_sshd_conf
Viewing Audit Rule Logs
There are various ways in which you can view Audit log records.
- Reading the Audit log file,
/var/log/audit/audit.log
.
grep --color monitor_sshd_conf /var/log/audit/audit.log
type=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"
type=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"
- Generate a report using aureport (read more on
man aureport
)
aureport -i -k
Key Report
===============================================
# date time key success exe auid event
===============================================
1. 12/08/2021 20:24:38 monitor_sshd_conf yes ? kifarunix 13
2. 12/08/2021 20:25:57 monitor_sshd_conf yes /usr/bin/tee kifarunix 38
- Search the logs with ausearch command (read more on
man ausearch
).
ausearch -i -k monitor_sshd_conf
----
type=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
----
type=PROCTITLE msg=audit(12/08/2021 20:25:57.760:38) : proctitle=tee -a /etc/ssh/sshd_config
type=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
type=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
type=CWD msg=audit(12/08/2021 20:25:57.760:38) : cwd=/home/kifarunix
type=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
From the ausearch report output, let’s try to interpret the records fields.
- type=PROCTITLE: Record type which gives the full command-line that triggered this Audit event.
- msg=audit(12/08/2021 20:24:38.290:13): Defines a timestamp and a unique ID of the record in the form
audit(time_stamp:ID)
. Time usually shows in EPOCH unless you use option -i.
If time is in EPOCH, e.g 1638984357.760
. then convert using date command;
date -d @1638984357.760
Wed 08 Dec 2021 08:25:57 PM EAT
- proctitle=tee -a /etc/ssh/sshd_config: 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.
- type=PATH: 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.
item=1
: Theitem
field indicates which item, of the total number of items referenced in theSYSCALL
type record, the current record is. a value of 1 means it is the second item.name=/etc/ssh/sshd_config
: 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
file.inode=526305
: Theinode
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:
find / -inum 526305 -print
/etc/ssh/sshd_config
dev=08:01
: The field specifies the minor and major ID of the device that contains the file or directory recorded in this event.- mode=file,644: The mode field records the file or directory permissions, 644 means -rw-r–r– for the /etc/ssh/sshd_config file.
ouid=root
: The ouid field records the object owner’s user ID/username.ogid=root
: The ogid field records the object owner’s group ID/username.rdev=00:00
: 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.nametype=NORMAL
: records the intent of each path record’s operation in the context of a given syscall.cap_fp=none
: The cap_fp field records data related to the setting of a permitted file system-based capability of the file or directory object.cap_fi=none
: The cap_fi field records data related to the setting of an inherited file system-based capability of the file or directory object.cap_fe=0
: The cap_fe field records the setting of the effective bit of the file system-based capability of the file or directory object.cap_fver=0
: The cap_fver field records the version of the file system-based capability of the file or directory object.type=CWD
: records the working directory from which the process that invoked the system call was executed.cwd=/home/kifarunix
: specifies directory in which the system call was invoked.type=SYSCALL
: specifies that the record was triggered by a system call to the kernel.arch=x86_64
: The field contains information about the CPU architecture of the system. Unless option -i is used with auseardh, the value is shown hexadecimal notation.syscall=openat
: 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 theausyscall --dump
command to display a listing of all system calls along with their numbers. For more information, see man ausyscall.success=yes
: The success field records whether the system call recorded in that particular event succeeded or failed. In this case, the call succeeded.- exit=3: The field contains a value that specifies the exit code returned by the system call. This value varies for different system call.
a0=0xffffff9c a1=0x7fffe54487de a2=O_WRONLY|O_CREAT|O_APPEND a3=0x1b6
: 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.items=2
: The items field contains the number of PATH auxiliary records that follow the syscall record.ppid=987
: The ppid field records the Parent Process ID (PPID).pid=988
: The pid field records the Process ID (PID).auid=kifarunix
: 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.uid=root
: 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.gid=root
: The gid field records the group ID of the user who started the analyzed process.euid=root
: The euid field records the effective user ID of the user who started the analyzed process.suid=root
: The suid field records the set user ID of the user who started the analyzed process.fsuid=root
: The fsuid field records the file system user ID of the user who started the analyzed process.egid=root
: The egid field records the effective group ID of the user who started the analyzed process.sgid=root
: The sgid field records the set group ID of the user who started the analyzed process.fsgid=root
: The fsgid field records the file system group ID of the user who started the analyzed process.tty=pts1
: The tty field records the terminal from which the analyzed process was invoked.ses=5
: The ses field records the session ID of the session from which the analyzed process was invoked.comm=tee
: The comm field records the command-line name of the command that was used to invoke the analyzed process.exe=/usr/bin/tee
: The exe field records the path to the executable that was used to invoke the analyzed process.subj=unconfined
: The subj field records the SELinux context with which the analyzed process was labeled at the time of execution.key=monitor_sshd_conf
: The key field records the administrator-defined string associated with the rule that generated this event in the audit log.
From the report;
----
type=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
----
type=PROCTITLE msg=audit(12/08/2021 20:25:57.760:38) : proctitle=tee -a /etc/ssh/sshd_config
type=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
type=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
type=CWD msg=audit(12/08/2021 20:25:57.760:38) : cwd=/home/kifarunix
type=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
It can be seen that:
- the SSH server configuration file,
/etc/ssh/sshd_config
, was updated using thetee
command. - The command was executed from the directory,
/home/kifarunix
. - The changes were made by the user,
kifarunix
as root user (using sudo).
If you want to use Auditbeat and ELK instead, check the guide below;
Detect Changes to Critical Files in Linux using Auditbeat and ELK
Other Tutorials
Install and Configure AIDE on Debian 10
Install OSSEC Agent on Rocky Linux 8
Install Arkime (Moloch) Full Packet Capture tool on Debian 11