Many people install Linux and think it is safe from hackers, but that is not true. When you install a fresh Linux, it have a tool called auditd but this tool is sleep and do not log anything that is useful for us. If someone hack your system, you will not know what they do because the default config is very empty. We need to put custom audit rules so we can watch files, see when people make new users, see when someone change time, and see if they load bad kernel modules. We will put this rules inside a file called /etc/audit/rules.d/cfg-hardening.rules so the system can watch everything and tell us when bad thing happen.
To start doing this, you must open your terminal on your Linux machine. You need to have root access or use sudo because we are changing very deep system files. First, we will create and open the rule file using the vi editor.
Run this command in your terminal:
sudo vi /etc/audit/rules.d/cfg-hardening.rules
If you do not like vi editor because it is hard to use, you can also use nano editor, but vi is always there on every Linux server. When the file is open, you must copy all the lines below and paste them inside the file.
# Watch critical config files
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/sshd_config.d/ -p wa -k sshd_config
-w /etc/selinux/ -p wa -k selinux_config
-w /etc/audit/ -p wa -k auditd
# User/group modifications
-w /usr/sbin/useradd -p x -k user_mgmt
-w /usr/sbin/userdel -p x -k user_mgmt
-w /usr/sbin/usermod -p x -k user_mgmt
-w /usr/sbin/passwd -p x -k user_mgmt
# Time changes
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change
# Mount events
-a always,exit -F arch=b64 -S mount,umount2 -F auid>=1000 -F auid!=unset -k mount
# Unauthorized access attempts
-a always,exit -F arch=b64 -S openat,truncate,ftruncate -F exit=-EACCES \
-F auid>=1000 -F auid!=unset -k unauthed_access
-a always,exit -F arch=b64 -S openat,truncate,ftruncate -F exit=-EPERM \
-F auid>=1000 -F auid!=unset -k unauthed_access
# Module load/unload
-w /sbin/insmod -p x -k module_load
-w /sbin/rmmod -p x -k module_load
-w /sbin/modprobe -p x -k module_load
-a always,exit -F arch=b64 -S init_module,delete_module -k module_load
After you paste this inside the file, you must save it. If you use vi, you press Escape key, then type :wq and then press Enter key.
Now, I will explain what every part of this rules do because it is very important to understand.
The first part of the rules is for watching critical configuration files. You can see the -w option, this means we want to watch a specific file or folder path. The -p wa option is very important because w means write and a means attribute change. This means if someone try to modify the file or change its permissions, auditd will write it in logs. The -k option is a key tag, we use it like a label so we can search for it easily later. We watch /etc/passwd, /etc/shadow, and /etc/group because this is where Linux save users and passwords. If a hacker make a new user or change password, we will see it under the key tag identity. We also watch /etc/sudoers and its folder because that is where admin privileges are. If someone give himself admin access, we see it under actions key. We watch SSH config and SELinux config because hackers love to turn off security and open SSH doors.
The second part is user and group modifications. Here we watch binaries like /usr/sbin/useradd, /usr/sbin/userdel, /usr/sbin/usermod, and /usr/sbin/passwd. We use -p x here. The x means execute. We want to know when someone run this commands. If a bad guy try to add new user using the command line, auditd will catch them and put the tag user_mgmt on the log.
The third part is for time changes. Why we need to watch time changes? Because clever hackers often change the system time to make logs look confusing. If they do bad things today, they can change system clock to three years ago so the admin cannot find the logs easily. The rule use -a always,exit which means we want to log the system call when it finishes. The -F arch=b64 means we are looking at 64-bit architecture system. The -S is for system calls like adjtimex, settimeofday, and clock_settime. When any process try to change time, it will be logged with key time_change.
The fourth part is about mount events. If someone insert a USB drive or mount a secret disk partition to steal data, we must know about it. The rule watch for mount and umount2 system calls. We use -F auid>=1000 because we do not want to watch system processes that have low ID. Normal users have ID 1000 or more. The -F auid!=unset means we only watch real users, not processes that don’t have a real user ID. This keeps our logs clean.
The fifth part is for unauthorized access attempts. This is very good for finding if someone is scanning your system or trying to read files they are not allowed to read. We look for system calls like openat, truncate, and ftruncate. We check if the exit code of the system call is -EACCES which means permission denied, or -EPERM which means operation not permitted. If a normal user try to open a root file, auditd will make a log with the tag unauthed_access.
The last part is about kernel modules. Hackers use kernel modules to install rootkits which are very silent and dangerous. We watch /sbin/insmod, /sbin/rmmod, and /sbin/modprobe with -p x to know when they are executed. We also watch the system calls init_module and delete_module so if they load module in another way, we still catch them under module_load tag.
Now that we have written the file, we must load the rules into the active auditd system. By default, auditd does not read new files automatically. We have to tell it to load them. Run this command:
sudo augenrules --load
This command will read all files inside /etc/audit/rules.d/ and put them together to make the active rules. If there is no error, it will say it loaded successfully.
Next, we must verify if our rules are really active in the system. We can list the active rules using the auditctl command. We can pipe it to head command to see the first ten rules to check if they look correct.
Run this command:
sudo auditctl -l | head -10
You should see some of the rules we wrote, like the ones watching /etc/passwd or /etc/shadow.
To make sure all rules are loaded, we can count the lines of active rules. We do this by sending the output to the wc -l command, which counts lines.
Run this command:
sudo auditctl -l | wc -l
The count should show a number around 22. This is because some syscall rules expand to show more details when they are loaded in the system memory. If you see a number like that, it means your configuration is active and working.
After some time, you will want to search your logs to see if something bad happened. You do not need to open the raw log file with cat because it is very hard to read. Instead, you can use the ausearch tool which is made for this.
For example, if you want to see if anyone touched the identity files like /etc/passwd, you run this command:
sudo ausearch -k identity
This command will look for the tag identity we made in our rules and show only those events.
If you want to see a quick summary of what happened on your system without reading too much text, you can use the aureport tool. It can make a nice report for you.
Run this command:
sudo aureport --summary
This will show you how many users failed to login, how many config changes happened, and other useful events.
In conclusion, setting up custom audit rules is very important for keeping your Linux server safe. Without these rules, auditd is running but it does not write down the important things we need when we try to investigate a security problem. By watching files like /etc/shadow, tracking user creation, and logging unauthorized access, we make it much easier to see what a hacker did. It is a simple thing to do but it makes your system much more secure than before.
