How to Harden Linux Server Security Against Shared Library Hijacking by Locking Down Ld_preload and /etc/ld.so.preload on Ubuntu Server
Knowing how to harden Linux server security against shared library hijacking by locking down LD_PRELOAD and /etc/ld.so.preload on Ubuntu Server is essential for any administrator running production workloads. Attackers who gain limited access to a system can exploit these dynamic linker features to inject malicious shared libraries into running processes. This gives them the ability to intercept system calls, steal credentials, or escalate privileges without touching a single binary. In this tutorial, you will learn exactly what these attack vectors are, why they are dangerous, and how to close them down using file permissions, PAM restrictions, and kernel-level controls. By the end, your Ubuntu Server will be significantly more resistant to this class of attack.
Prerequisites for Locking Down Shared Library Hijacking on Ubuntu Server
Before you start, make sure you have the following in place.
Required access and software:
- Ubuntu Server 20.04 or 22.04 LTS (these steps work on both)
- Root or sudo access to the server
- SSH access or direct console access
- Basic familiarity with the Linux command line
- A text editor such as
nanoorvim
Estimated time to complete: 30–45 minutes.
Assumed knowledge level: Intermediate. You should be comfortable editing system files and restarting services. You don’t need to be a security expert, but understanding what shared libraries do will help. The Linux dynamic linker (ld.so) loads shared libraries when a program starts. The LD_PRELOAD environment variable and the file /etc/ld.so.preload tell the linker to load specific libraries before all others. This is a legitimate feature, but it is also a well-known privilege escalation path.
You can read more about how the Linux dynamic linker works in the official ld.so man page on man7.org.
How to Harden Linux Server Security Against Shared Library Hijacking Step by Step
For a related walkthrough, see: How to Build Interactive WordPress Blocks Using the WordPress Interactivity API and Data-wp-* Directives
Work through these steps in order. Don’t skip any of them. Each one closes a different angle of attack.
Step 1: Check the current state of /etc/ld.so.preload
First, check whether this file exists and what it contains.
sudo cat /etc/ld.so.preload
On a clean server, this file is usually empty or absent. If it contains entries you don’t recognize, investigate them immediately before continuing. An unknown entry here is a red flag.
Step 2: Lock down /etc/ld.so.preload with strict permissions
Even if the file is empty, you should restrict who can modify it. Set ownership to root and remove write access for everyone else.
sudo chown root:root /etc/ld.so.preload
sudo chmod 644 /etc/ld.so.preload
This prevents non-root users from adding malicious library paths to the file. Only root can write to it now.
Step 3: Make /etc/ld.so.preload immutable with chattr
Go one step further. Use the chattr command to set the immutable flag. This stops even root from modifying the file without explicitly removing the flag first.
sudo chattr +i /etc/ld.so.preload
To verify the flag was set correctly, run:
sudo lsattr /etc/ld.so.preload
You should see output like ----i---------e-- /etc/ld.so.preload. The i means immutable.
Step 4: Restrict LD_PRELOAD via PAM environment settings
The LD_PRELOAD environment variable is the other major attack surface. You can restrict it using PAM. Open the PAM environment configuration file.
sudo nano /etc/security/pam_env.conf
Add this line at the bottom to unset LD_PRELOAD for all PAM-authenticated sessions.
LD_PRELOAD DEFAULT=""
Save and close the file. This ensures that any user logging in through SSH or a local session starts with an empty LD_PRELOAD.
Step 5: Disable LD_PRELOAD for setuid binaries using sysctl
Linux already ignores LD_PRELOAD for setuid binaries by default. You should confirm this behavior is active. Check your running kernel settings.
sysctl fs.suid_dumpable
You want this set to 0. If it isn’t, set it now.
sudo sysctl -w fs.suid_dumpable=0
Make it permanent by adding it to /etc/sysctl.conf.
echo "fs.suid_dumpable = 0" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Step 6: Audit existing shared library configurations
Check the /etc/ld.so.conf.d/ directory for unexpected entries. Attackers sometimes drop files here to load malicious libraries system-wide.
ls -la /etc/ld.so.conf.d/
cat /etc/ld.so.conf
Review every file in that directory. Remove any entry that doesn’t correspond to a legitimate installed package. After making changes, run:
sudo ldconfig
This rebuilds the linker cache and removes stale or malicious entries.
Step 7: Monitor /etc/ld.so.preload with auditd
Set up file integrity monitoring on the file using auditd. Install it first if you don’t have it.
sudo apt install auditd -y
Add a watch rule for the file.
sudo auditctl -w /etc/ld.so.preload -p rwxa -k ld_preload_watch
Make this rule permanent by adding it to the audit rules file.
echo "-w /etc/ld.so.preload -p rwxa -k ld_preload_watch" | sudo tee -a /etc/audit/rules.d/hardening.rules
sudo systemctl restart auditd
Now any access attempt on that file will be logged. You can review events with:
sudo ausearch -k ld_preload_watch
Step 8: Restrict user namespaces to limit exploit chaining
Unprivileged user namespaces can be used to chain this attack with container escapes. Restrict them.
echo "kernel.unprivileged_userns_clone = 0" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
This closes an additional privilege escalation path that attackers often use alongside library injection.
Troubleshooting Common Issues When Hardening Shared Library Security
Problem: chattr fails with “Operation not permitted”
This usually means you’re on a filesystem that doesn’t support extended attributes, such as a tmpfs mount. Check your mount type with df -T /etc. On ext4 and xfs, chattr works fine.
Problem: Legitimate software breaks after setting LD_PRELOAD to empty
Some monitoring agents or security tools use LD_PRELOAD to inject themselves into processes. Check with your vendor. You may need to set the variable in a specific service unit file using Environment=LD_PRELOAD=/path/to/lib.so inside the [Service] block rather than relying on a global setting.
Problem: /etc/ld.so.preload doesn’t exist
That’s fine. Create an empty file and then lock it down.
sudo touch /etc/ld.so.preload
sudo chattr +i /etc/ld.so.preload
Problem: auditd rules don’t persist after reboot
Make sure you added the rule to /etc/audit/rules.d/hardening.rules and not just ran auditctl interactively. The auditctl command only sets rules for the current session.
For a deeper look at auditing Linux systems, see the Ubuntu Server security auditing documentation.
Conclusion: Keeping Your Linux Server Hardened Against Library Hijacking
You now know how to harden Linux server security against shared library hijacking by locking down LD_PRELOAD and /etc/ld.so.preload on Ubuntu Server. You’ve restricted file permissions, applied the immutable flag, configured PAM to strip the environment variable, audited linker config directories, and set up real-time monitoring with auditd. Each layer you added makes it harder for an attacker to use
