Advanced Linux Server Security
Add intrusion detection and kernel hardening to your Linux server.
Introduction
30 Second Summary
A locked door keeps most intruders out. But what happens if someone picks the lock? Real security means having cameras, motion sensors, and alarms that detect a breach the moment it happens.
In this project, you will add detection and monitoring layers to your hardened Linux server. You'll configure kernel restrictions, deploy file integrity monitoring, and set up security auditing to catch intruders in the act.
What You'll Build
A multi-layered security detection system that hardens your kernel, monitors critical files for unauthorized changes, and logs every privileged action on your server.
By the end of this project, you'll have:
- A kernel-hardened server with a custom sysctl configuration that restricts network stack exposure and limits kernel information leakage.
- A file integrity monitoring system using AIDE that watches critical system files and detects unauthorized changes.
- A security audit framework using auditd that logs privilege escalation attempts, sensitive file access, and suspicious commands.
- Secret Mission: Build an automated daily security check script that runs integrity scans and generates audit summary reports.
Do I need to complete the Harden a Linux Server project first?
Yes. This project builds directly on top of your hardened server from that project. You should already have a non-root sudo user, an active UFW firewall, and hardened SSH configured.
Your original project locked the doors. This project adds the cameras and tripwires that detect when someone gets past them.
Before We Start
Your hardened Linux server from the previous project locks the doors with a firewall, SSH restrictions, and user controls. That stops many attackers at the perimeter.
But what happens if someone gets past those defenses? In this step, you'll install two detection tools that act as your server's alarm system. AIDE monitors file integrity, and auditd tracks privileged actions.
In this step, get ready to:
- Install AIDE and auditd packages on your server.
- Verify both tools are installed and their services are running.
- Remove the default auditd rule that disables all audit processing.
Install AIDE and auditd
Both tools are available in Ubuntu's package repositories. AIDE (Advanced Intrusion Detection Environment) is a file integrity checker. auditd is the Linux kernel's native audit framework for logging system events.
- Open your Ubuntu VM terminal.
- Update your package list and install both tools by running these commands:
sudo apt update
sudo apt install aide auditd -y
What does this command do?
sudo apt update refreshes the list of available packages from Ubuntu's repositories.
sudo apt install aide auditd -y installs both packages. The -y flag automatically confirms the installation prompts.
- Wait for the installation to complete. You should see output ending with a line similar to Processing triggers for man-db.
Seeing a package not found error?
Make sure sudo apt update ran successfully first. If your VM cannot reach the internet, check that your Parallels network adapter is set to Shared or Bridged mode.
Help me troubleshoot package installation on my Ubuntu VM
Verify both tools are installed
AIDE is a command-line tool you run on demand. auditd runs as a background service that starts automatically after installation.
- Confirm AIDE is installed by running:
dpkg -l | grep aide
- You should see lines showing aide and aide-common listed as installed packages.
- Now check that the auditd service is running:
sudo systemctl status auditd
- You should see active (running) in the output. Press q to exit the status view.
Why is there no AIDE service?
AIDE is not a background daemon. It's a scanning tool you run manually or on a schedule (like a cron job). It compares the current state of your files against a saved baseline database.
auditd is different. It runs continuously in the background, intercepting kernel events and writing them to a log file in real time.
auditd not showing as active?
Try enabling and starting it manually:
sudo systemctl enable --now auditd
Then re-run sudo systemctl status auditd to confirm.
Help me get auditd running on my Ubuntu server
Remove the default no-audit rule
On many Ubuntu systems, auditd ships with a default rule file that disables all syscall auditing for performance. This file is called 10-no-audit.rules and it contains a -a task,never directive.
That rule tells the kernel to skip all audit processing for every new process. You need to remove it so your custom audit rules will actually work.
- Check if the no-audit file exists by running:
ls /etc/audit/rules.d/
- If you see 10-no-audit.rules in the listing, remove it by running:
sudo rm /etc/audit/rules.d/10-no-audit.rules
- Now create a base configuration file that sets up proper audit infrastructure by running:
sudo bash -c 'cat > /etc/audit/rules.d/10-base-config.rules << EOF
## First rule - delete all
-D
## Increase the buffers to survive stress events
-b 8192
## This determines how long to wait in burst of events
--backlog_wait_time 60000
## Set failure mode to syslog
-f 1
EOF'
What does this base config do?
- -D clears any existing rules so you start fresh each time rules are loaded.
- -b 8192 sets the audit buffer size to 8192 events, preventing lost events during bursts of activity.
- --backlog_wait_time 60000 controls how long the kernel waits when the buffer is full (in milliseconds).
- -f 1 sets the failure mode to print a warning to syslog if the audit system encounters an error, rather than panicking.
- Load the new rules into the kernel by running:
sudo augenrules --load
- Verify the no-audit rule is gone and your base config is active by running:
sudo auditctl -l
- You should see No rules in the output. This is correct. The -D directive cleared all rules, and you haven't added monitoring rules yet.
How is no rules different from the no-audit rule?
The -a task,never rule actively told the kernel to never audit anything. With that rule gone, the audit system is now ready and waiting for rules.
"No rules" means auditd is listening but has no specific instructions yet. You'll add detection rules in Step 4.
- Confirm the audit system status is enabled by running:
sudo auditctl -s
- Look for enabled 1 in the output. This confirms the audit system is active and ready to process rules.
Still seeing a never,task rule?
Double check that 10-no-audit.rules was actually removed from /etc/audit/rules.d/. Run ls /etc/audit/rules.d/ again to verify. After confirming it's gone, run sudo augenrules --load again to recompile and load the rules.
Help me remove the default no-audit rule from auditd
Your detection tools are installed and ready. Next up, you'll harden the Linux kernel itself with sysctl to reduce what an attacker can do if they get in.
Harden the Kernel with sysctl
Your server now has AIDE and auditd ready to detect changes and log activity. The next layer of defense is reducing what an attacker can actually do if they get past your firewall.
The Linux kernel exposes hundreds of tunable parameters that control networking behavior, memory layout, and process access. Many of these ship with permissive defaults designed for compatibility, not security. In this step, you will lock them down using sysctl, the tool that reads and writes kernel parameters at runtime.
In this step, get ready to:
- Inspect current kernel parameters to see their insecure default values.
- Create a hardening configuration file that restricts the network stack and kernel exposure.
- Apply the new settings and verify they are active.
Inspect current kernel parameters
Before changing anything, check what your kernel currently allows. Most of these parameters default to permissive values that prioritize compatibility over security.
- Check the current network stack parameters by running this command:
sysctl net.ipv4.conf.all.accept_redirects net.ipv4.conf.all.send_redirects net.ipv4.tcp_syncookies net.ipv4.conf.all.rp_filter
- Check the current kernel restriction parameters by running:
sysctl kernel.yama.ptrace_scope kernel.kptr_restrict kernel.randomize_va_space kernel.dmesg_restrict
What do these defaults mean?
If you see net.ipv4.conf.all.accept_redirects = 1, your server currently accepts ICMP redirect messages from any router. An attacker can use these to reroute your traffic through their machine.
If kernel.kptr_restrict = 0, any user on the system can read kernel memory addresses. This makes it easier to write exploits that target specific locations in memory.
Create the hardening configuration file
Instead of setting parameters one at a time (which would reset on reboot), you will create a persistent configuration file. Files in /etc/sysctl.d/ are loaded automatically at boot.
- Create the kernel hardening configuration file by running this command:
sudo tee /etc/sysctl.d/99-hardening.conf << 'EOF'
# Network stack hardening
# Disable ICMP redirects (prevents routing table manipulation)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Enable SYN cookies (prevents SYN flood DoS attacks)
net.ipv4.tcp_syncookies = 1
# Enable reverse path filtering (prevents IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Kernel restriction settings
# Restrict ptrace to parent processes only
kernel.yama.ptrace_scope = 1
# Hide kernel memory addresses from unprivileged users
kernel.kptr_restrict = 2
# Enable full Address Space Layout Randomization
kernel.randomize_va_space = 2
# Restrict kernel log access to root only
kernel.dmesg_restrict = 1
EOF
What does this configuration do?
The network settings protect against three common attack vectors. Disabling ICMP redirects stops attackers from manipulating your routing table. SYN cookies prevent denial-of-service attacks that flood your server with half-open connections. Reverse path filtering drops packets with spoofed source addresses.
The kernel restrictions limit what information unprivileged users can extract. ASLR (kernel.randomize_va_space = 2) randomizes where programs are loaded in memory, making exploits much harder to write reliably.
- Verify the file was written correctly by running:
cat /etc/sysctl.d/99-hardening.conf
You should see all 10 parameter settings printed, matching the configuration above.
Don't see the file content?
Make sure you included the EOF closing marker on its own line. If the heredoc did not close properly, the file may be empty or missing.
Check that you used sudo tee and not just tee. Writing to /etc/sysctl.d/ requires root privileges.
help me troubleshoot why my sysctl hardening file was not created correctly
✔️ Awesome, I've got everything!
Great. Make sure you have saved the file before moving on to apply the settings.
ⓧ I'd like to double check the full code
Here is the complete /etc/sysctl.d/99-hardening.conf file for comparison:
# Network stack hardening
# Disable ICMP redirects (prevents routing table manipulation)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
# Enable SYN cookies (prevents SYN flood DoS attacks)
net.ipv4.tcp_syncookies = 1
# Enable reverse path filtering (prevents IP spoofing)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Kernel restriction settings
# Restrict ptrace to parent processes only
kernel.yama.ptrace_scope = 1
# Hide kernel memory addresses from unprivileged users
kernel.kptr_restrict = 2
# Enable full Address Space Layout Randomization
kernel.randomize_va_space = 2
# Restrict kernel log access to root only
kernel.dmesg_restrict = 1
Apply the configuration and verify
The file exists on disk but the kernel is still running with the old values. You need to tell sysctl to reload all configuration files.
- Apply all sysctl configuration files by running:
sudo sysctl --system
What does this command do?
The --system flag tells sysctl to load settings from all configuration files in /etc/sysctl.d/, /run/sysctl.d/, and /usr/lib/sysctl.d/. You should see each parameter being applied in the output.
- Verify the new values are active by spot-checking a few parameters:
sysctl net.ipv4.conf.all.accept_redirects kernel.kptr_restrict kernel.randomize_va_space
You should see net.ipv4.conf.all.accept_redirects = 0, kernel.kptr_restrict = 2, and kernel.randomize_va_space = 2. These confirm the kernel is now running with your hardened settings.
Still seeing the old values?
Make sure you ran sudo sysctl --system (not just sysctl --system without sudo). Loading system-wide settings requires root privileges.
Check that your file is named 99-hardening.conf with the .conf extension. Files without .conf are ignored by sysctl --system.
help me figure out why my sysctl settings did not apply
Why the number 99 in the filename?
Files in /etc/sysctl.d/ are loaded in lexicographic order. Using 99 as a prefix ensures your hardening file is loaded last, overriding any conflicting defaults from other configuration files.
Your kernel is now locked down. Attackers who get past the firewall will find a much smaller attack surface. Next up, you will set up file integrity monitoring to catch any unauthorized changes to your system files.
Set Up File Integrity Monitoring with AIDE
Your kernel is now hardened, reducing what an attacker can do even if they breach your server. But how would you know if someone changed a critical system file?
That's where AIDE (Advanced Intrusion Detection Environment) comes in. AIDE takes a cryptographic snapshot of your system files and alerts you when anything changes. Think of it as a tripwire for your filesystem.
In this step, get ready to:
- Review the AIDE configuration and understand its monitoring rules.
- Initialize the AIDE database to create a cryptographic baseline.
- Simulate an intrusion and verify AIDE detects it.
Review the AIDE configuration
Before initializing the database, you need to understand what AIDE is monitoring and how it defines its rules. The main configuration file tells AIDE which directories to watch and which file attributes to track.
- View the AIDE configuration file by running this command:
sudo cat /etc/aide/aide.conf
What does this file contain?
The AIDE config defines rule groups that specify which attributes to check for each file. Common attributes include permissions, inode number, ownership, size, and cryptographic checksums (like SHA-256).
You'll see lines that map directories to rule groups. For example, paths like /bin, /sbin, and /etc are monitored with strict rules that track any change to permissions, content, or ownership.
- You can also check the additional rule snippets in the /etc/aide/aide.conf.d directory by running:
ls /etc/aide/aide.conf.d
You should see one or more rule files that extend the main configuration. These snippets are automatically merged into the runtime configuration when AIDE runs.
Why separate config files?
Ubuntu splits AIDE rules across multiple files so that packages can drop their own monitoring rules into /etc/aide/aide.conf.d without editing the main config. The update-aide.conf tool merges everything into a single runtime config automatically.
Initialize the AIDE database
Now that you understand the configuration, you need to create the initial database. This database is the baseline snapshot that AIDE compares against during future checks.
- Initialize the AIDE database by running this command:
sudo aideinit
What does this command do?
The aideinit command scans every file and directory covered by your AIDE rules. For each file, it records permissions, ownership, size, timestamps, and cryptographic checksums.
This process can take a few minutes depending on how many files your system has. When it finishes, the new database is stored at /var/lib/aide/aide.db.new.
Be patient during initialization
AIDE calculates multiple checksums for every monitored file. On a fresh Ubuntu VM this typically takes 1-3 minutes. You'll see it return to your prompt when it finishes.
AIDE stores the newly created database at /var/lib/aide/aide.db.new, but it looks for the active database at /var/lib/aide/aide.db when running checks. You need to move the new database into the active location.
- Move the new database into place by running:
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
- Confirm the database is in place by running:
ls -l /var/lib/aide/aide.db
You should see the aide.db file listed with today's date and a size of several megabytes.
Don't see aide.db?
If the file isn't there, check that aideinit completed successfully. Run ls /var/lib/aide/ to see what files exist. If you see aide.db.new still present, the mv command may not have run. Try the move command again.
help me figure out why my AIDE database wasn't created
Simulate an intrusion and detect the change
Your AIDE database now holds a cryptographic snapshot of your system. To prove it works, you'll simulate an attacker modifying a monitored file, then run AIDE to catch the change.
- Simulate an intrusion by adding a suspicious line to a monitored file:
sudo sh -c 'echo "# simulated malicious change" >> /etc/hosts'
Why modify /etc/hosts?
The /etc/hosts file lives inside /etc, which AIDE monitors. A real attacker might modify this file to redirect traffic to malicious servers. This is a safe way to trigger a detection without breaking anything.
- Now run an AIDE check to see if it catches the modification:
sudo aide.wrapper --check
What does this output mean?
AIDE compares the current state of every monitored file against the baseline database. In the output, you should see /etc/hosts listed as a changed file.
The report shows which attributes changed. For your simulated intrusion, you'll see changes to the file size and checksums. This proves AIDE detected the unauthorized modification.
You should see output that includes a summary of changed files, with /etc/hosts listed in the report. AIDE reports the changed attributes (size, checksums) that differ from the baseline.
AIDE reports no changes?
Make sure you moved the database before running the check. If /var/lib/aide/aide.db doesn't exist, AIDE has nothing to compare against. Also confirm you appended to /etc/hosts after initializing the database, not before.
help me troubleshoot why AIDE is not detecting my file change
- Clean up the simulated intrusion by removing the line you added:
sudo sed -i '/# simulated malicious change/d' /etc/hosts
Why clean up?
You proved that AIDE catches unauthorized changes. Removing the test modification keeps your system clean for the remaining steps. In a production environment, you would investigate the change, then update the database after confirming it's legitimate.
Your file integrity monitoring system is now active. Next up, you'll configure auditd to log exactly who does what on your server, giving you a full audit trail of privileged actions.
Configure Security Auditing with auditd
Your server can now detect unauthorized file changes with AIDE. But what about actions that don't modify files directly? Someone could read /etc/shadow to harvest password hashes, escalate to root, or quietly add a new user account.
This is where auditd comes in. It is the Linux kernel's built-in audit framework that logs specific system activity. You'll write rules that tell the kernel exactly which actions to record, then use search and reporting tools to investigate what happened.
In this step, get ready to:
- Create audit rules that monitor sensitive files and detect privilege escalation.
- Load the rules into the kernel and verify they are active.
- Trigger audit events and investigate them with ausearch and aureport.
Create audit rules to monitor sensitive files and privilege escalation
Audit rules live in /etc/audit/rules.d/ as individual files ending in .rules. The augenrules program compiles them into a single ruleset and loads them into the kernel.
- Create the audit rules file by running this command:
sudo nano /etc/audit/rules.d/hardening.rules
- Paste the following rules into the file:
# Monitor access to the shadow password file
-w /etc/shadow -p rw -k shadow-access
# Monitor access to the passwd file
-w /etc/passwd -p rw -k passwd-access
# Monitor privilege escalation (commands run as root by non-root users)
-a always,exit -F arch=b64 -F euid=0 -F auid>=1000 -F auid!=-1 -S execve -k privesc
# Monitor user and group management commands
-w /usr/sbin/useradd -p x -k user-mgmt
-w /usr/sbin/usermod -p x -k user-mgmt
-w /usr/sbin/groupadd -p x -k user-mgmt
What do these rules do?
Each rule tells the kernel what to watch and how to tag the events:
- -w /etc/shadow -p rw -k shadow-access watches the shadow file for reads (r) and writes (w), tagging events with the key shadow-access.
- -a always,exit -F arch=b64 -F euid=0 -F auid>=1000 -F auid!=-1 -S execve -k privesc catches any program execution where the effective user is root (euid=0) but the original login user was non-root (auid>=1000). This detects sudo usage and other privilege escalation.
- -w /usr/sbin/useradd -p x -k user-mgmt watches the useradd binary for execution. If anyone creates a new user, auditd logs it.
- Save and exit nano by pressing Ctrl+O, then Enter, then Ctrl+X.
Load the rules and verify they are active
Rules sitting in a file do nothing until you load them into the kernel. The augenrules command merges all .rules files in /etc/audit/rules.d/ and pushes the result into the running audit system.
- Load the new rules into the kernel by running:
sudo augenrules --load
- Verify the rules are active by running:
sudo auditctl -l
You should see each of your rules listed in the output, including the file watches on /etc/shadow and /etc/passwd, the execve syscall rule, and the watches on user management commands.
Don't see your rules listed?
- If you see a -a never,task rule in the output, the default no-audit rule is still present. It was removed in Step 1, but double check that 10-no-audit.rules does not exist in /etc/audit/rules.d/.
- Check that your file is named hardening.rules (not .rule without the s). Only files ending in .rules are processed.
- Run sudo augenrules --load again after fixing any issues.
- Help me troubleshoot my auditd rules not loading.
Trigger audit events and investigate with ausearch and aureport
Your rules are now active. Time to generate some events and confirm the audit system is capturing them.
- Trigger a shadow-access event by reading the shadow file:
sudo cat /etc/shadow > /dev/null
- Search for events tagged with the shadow-access key by running:
sudo ausearch -k shadow-access
You should see audit log entries showing the access to /etc/shadow, including the timestamp, the user who triggered it, and the command used.
What does ausearch show you?
Each audit event includes the syscall that triggered it, the file path accessed, the user ID (uid) and audit user ID (auid) of the process, and the key you assigned.
The auid field is especially useful because it shows the original login user even when they have escalated to root via sudo.
- Generate a summary report of all key activity by running:
sudo aureport --key --summary
You should see a table listing each key and the number of times its associated rules have triggered. Your shadow-access key should appear with at least one event.
When would you use ausearch vs aureport?
Use ausearch when you need to investigate a specific incident. It shows full event details filtered by key, time, user, or syscall.
Use aureport when you want a high-level view of what is happening across the system. It summarizes events into readable tables that highlight patterns.
Not seeing any events from ausearch?
- Make sure you ran the trigger command (sudo cat /etc/shadow > /dev/null) after loading the rules, not before. Events are only captured once rules are active.
- Confirm auditd is running with sudo systemctl status auditd. If the service is not active, restart it with sudo systemctl restart auditd.
- Help me figure out why ausearch is not returning any events.
✔️ Awesome, I've got everything!
Great. Double check you have saved your rules file and that auditctl -l shows all your rules loaded.
ⓧ I'd like to double check the full code
Here is the complete hardening.rules file:
# Monitor access to the shadow password file
-w /etc/shadow -p rw -k shadow-access
# Monitor access to the passwd file
-w /etc/passwd -p rw -k passwd-access
# Monitor privilege escalation (commands run as root by non-root users)
-a always,exit -F arch=b64 -F euid=0 -F auid>=1000 -F auid!=-1 -S execve -k privesc
# Monitor user and group management commands
-w /usr/sbin/useradd -p x -k user-mgmt
-w /usr/sbin/usermod -p x -k user-mgmt
-w /usr/sbin/groupadd -p x -k user-mgmt
Your audit framework is now actively logging sensitive file access, privilege escalation, and user management changes. In the next step, you'll put all three detection layers to work against a simulated attack.
Test Your Detection Pipeline
You now have three independent security layers configured: kernel hardening with sysctl, file integrity monitoring with AIDE, and security auditing with auditd. Each one works on its own, but the real power of defense-in-depth comes from correlating findings across all three.
In this step, you will simulate a realistic attack scenario and then use each tool to detect what happened. This is how security professionals validate their detection capabilities.
In this step, get ready to:
- Simulate an intrusion by creating a suspicious user and modifying a system binary.
- Detect the attack using AIDE, auditd, and sysctl verification.
- Correlate findings across all three detection layers.
Simulate a realistic attack scenario
A real attacker who gains initial access to a system typically does three things: creates a backdoor account, modifies system binaries for persistence, and attempts to escalate their privileges. You will simulate all three actions now.
- Create a suspicious user account by running this command:
sudo useradd -m -s /bin/bash testattacker
What does this command do?
This creates a new user called testattacker with a home directory and a bash shell.
In a real attack, an adversary would create a user like this to maintain access even if their original entry point is closed.
- Modify the permissions on a system binary to simulate a privilege escalation backdoor:
sudo chmod 4755 /usr/bin/find
What does this command do?
The 4755 permission sets the SUID bit on /usr/bin/find. When the SUID bit is set on a binary owned by root, anyone who runs that binary temporarily gets root-level access.
Attackers commonly use this technique because it is hard to notice without file integrity monitoring.
- Attempt privilege escalation by reading a sensitive file as the new user:
sudo -u testattacker cat /etc/shadow
This command attempts to read /etc/shadow (which stores password hashes) as the testattacker user. It will likely be denied, but auditd will log the attempt.
Seeing a permission denied error?
That is expected. The testattacker user does not have sudo privileges, so reading /etc/shadow fails. The important thing is that auditd recorded the attempt.
If you see an error about the user not existing, make sure the useradd command from earlier completed successfully.
Help me troubleshoot my attack simulation
Detect and investigate with all three tools
Now switch from attacker mode to investigator mode. You will query each of your three detection layers to see what they caught.
- Verify your sysctl hardening is still active by checking a key network parameter:
sysctl net.ipv4.conf.all.accept_redirects
- You should see net.ipv4.conf.all.accept_redirects = 0 in the output.
How does sysctl fit into this investigation?
Your sysctl configuration restricts what an attacker can do at the network level. With ICMP redirects disabled and reverse path filtering enabled, the attacker cannot use network-level tricks like routing table manipulation or IP spoofing to move laterally.
While sysctl did not directly catch the simulated attack, it reduced the attack surface. This is the preventive layer working alongside the detection layers.
- Run an AIDE check to detect the modified binary:
sudo aide --check
AIDE compares the current state of monitored files against the baseline database. It will report the permission change on /usr/bin/find.
What should I see?
AIDE will report at least one changed file. The output shows the file path and what changed. You should see permission changes for /usr/bin/find as well as changes in /etc related to the new user account.
The useradd command modifies /etc/passwd and /etc/shadow, so AIDE catches those too.
AIDE showing no changes?
Make sure the AIDE database was initialized before you ran the simulation commands. If you initialized the database after running the simulation, it captured the post-attack state as the baseline.
Help me troubleshoot AIDE detection
- Search the audit logs for user management events by running:
sudo ausearch -k user-mgmt -i
What does this command do?
The -k user-mgmt flag filters audit events to only those tagged with the user-mgmt key from your audit rules. The -i flag interprets numeric values into human-readable text (like converting UIDs to usernames).
- You should see entries showing the useradd command that created the testattacker account.
- Search for privilege escalation attempts by running:
sudo ausearch -k privesc -i
This shows all commands run with elevated privileges that were captured by your privilege escalation audit rule. You should see the command that attempted to read /etc/shadow as testattacker logged here.
- Check for any access attempts on the shadow file by running:
sudo ausearch -k shadow-access -i
This filters events tagged with shadow-access and shows who attempted to read /etc/shadow.
No events found for a key?
If ausearch returns no matches, verify your audit rules are loaded by running sudo auditctl -l. You should see your rules listed with the corresponding key names.
Help me troubleshoot missing audit events
Correlate findings across all three detection layers
Now pull everything together. A real security investigation involves cross-referencing findings from multiple sources to build a complete picture of what happened.
- Generate a key-based audit summary report by running:
sudo aureport --key --summary
This gives you a ranked list of which audit rule keys have been triggering. You should see user-mgmt, privesc, and shadow-access in the output.
How do the three layers fit together?
Here is your full detection timeline for the simulated attack:
- sysctl prevented the attacker from using network-level attack vectors (ICMP redirects, IP spoofing, routing manipulation) to expand their access.
- AIDE detected the unauthorized file modification on /usr/bin/find and changes to /etc/passwd and /etc/shadow.
- auditd logged exactly who created the new account, what commands were run with elevated privileges, and who attempted to read /etc/shadow.
No single tool tells the full story. Together, they give you prevention, detection, and attribution. This is defense-in-depth in action.
- Clean up the test user and restore the binary permissions by running these commands:
sudo userdel -r testattacker
sudo chmod 0755 /usr/bin/find
Why clean up?
Leaving a SUID binary and a backdoor user on your system is a real vulnerability. Always revert simulation changes after testing. Your detection tools will continue to work with the audit logs from the simulation even after cleanup.
Your detection pipeline is working. You proved that sysctl blocks network attack vectors, AIDE catches unauthorized file changes, and auditd logs every privileged action for investigation. Next up, you will automate this detection workflow so it runs without manual intervention.
Secret mission
Build an Automated Security Dashboard
Your detection tools work, but you have to run them manually every time. What if your server could check its own integrity every night and tell you what it found? In this secret mission, you will build a Bash script that automates AIDE scans and auditd reporting, schedule it with cron, and add optional email alerts for detected issues.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely on your local Parallels VM, so there are no ongoing cloud costs.
Resources you used:
- /etc/sysctl.d/99-hardening.conf (kernel hardening configuration).
- AIDE database at /var/lib/aide/aide.db.
- Audit rules at /etc/audit/rules.d/hardening.rules.
- AIDE and auditd packages installed via apt.
- Security check script at /usr/local/bin/security-check.sh (Secret Mission).
- Security reports directory at /var/log/security-reports/ and cron job (Secret Mission).
Keep everything running
No action needed. Choose this if you're still actively building or want your server to keep monitoring itself.
- Your sysctl hardening, AIDE database, and audit rules all persist across reboots.
- The auditd service continues logging privileged actions automatically.
- If you completed the Secret Mission, your cron job runs the security check script daily at 3:00 AM.
Pause - I'll come back to this later
Shut down your Parallels VM to free up memory on your Mac. All configurations are saved inside the VM and will be active when you start it again.
- In Parallels, click the stop button or run this inside your VM:
sudo shutdown now
When you start the VM again, all your sysctl settings, AIDE database, audit rules, and cron jobs will resume automatically.
Delete - I don't want to use this again
Remove all project resources and return to your base hardened server state from the previous project.
- Remove the kernel hardening configuration and reload system defaults by running:
sudo rm /etc/sysctl.d/99-hardening.conf && sudo sysctl --system
- Remove the AIDE and auditd packages by running:
sudo apt remove aide auditd
- Remove the AIDE database and your custom audit rules file by running:
sudo rm -rf /var/lib/aide /etc/audit/rules.d/hardening.rules
- If you completed the Secret Mission, remove the security check script, reports directory, and cron job by running:
sudo rm /usr/local/bin/security-check.sh
sudo rm -rf /var/log/security-reports/
sudo crontab -l | grep -v 'security-check.sh' | sudo crontab -
Your server is now back to the base hardened state from the previous project.
Nice Work!
Nice Work!
You've just built a complete security detection system on top of your hardened Linux server. Your server no longer just blocks attackers at the door. It detects them if they get in, tracks what they do, and alerts you to unauthorized changes.
You've learned how to:
- Harden the Linux kernel with sysctl to reduce your server's attack surface at the OS level, restricting network stack exposure and limiting kernel information leakage.
- Deploy AIDE for file integrity monitoring that creates cryptographic baselines of critical system files and catches unauthorized changes.
- Configure auditd to log privilege escalation attempts, sensitive file access, and user management changes for forensic investigation.
- Secret Mission: Automate security checks with a daily reporting script and cron scheduling that generates a color-coded security dashboard.
Ready to quiz yourself?