Table of Contents
Linux Hardening Guide - sysctl
The Linux kernel is flexible, and can be modified on the fly by dynamically changing some of its parameters using the sysctl command.
- sysctl allows the viewing and changing of kernel settings on a running system.
- The parameters available are those listed under /proc/sys/.
- Changes take effect immediately.
- The related /etc/sysctl.conf file is used to ensure that the settings persist after a reboot.
Sysctl changes can be:
- temporary - Using sysctl -w $tunable = $value.
- permanent - Add entries to change into /etc/sysctl.conf or the corresponding files within /etc/sysctl.d.
- at boot - Using the sysctl.$tunable=$value boot parameter.
- This seems to be better, as it is set at the beginning of the boot process, without depending on a user space service to read the values from configuration files.
IMPORTANT NOTE: Editing the sysctl.conf file might break the system - this is for advanced users only.
Make a backup of the existing /etc/sysctl.conf file
sudo cp /etc/sysctl.conf /etc/sysctl.conf.orig
NOTE: This is for safety reasons to allow switching back to the original.
Recommended sysctl settings to change for Kernel self-protection
kernel.kptr_restrict=2
A kernel pointer points to a specific location in kernel memory.
- These can be very useful in exploiting the kernel, but kernel pointers are not hidden by default — it is easy to uncover them by, for example, reading the contents of /proc/kallsyms.
- This setting aims to mitigate kernel pointer leaks.
- Alternatively, you can set kernel.kptr_restrict=1 to only hide kernel pointers from processes without the CAP_SYSLOG capability.
kernel.dmesg_restrict=1
dmesg is the kernel log.
- It exposes a large amount of useful kernel debugging information, but this can often leak sensitive information, such as kernel pointers.
- Changing the above sysctl restricts the kernel log to the CAP_SYSLOG capability.
NOTE: Capabilities:
- In the Linux kernel, “root privileges” are split up into various different capabilities.
- This is helpful in applying the principle of least privilege — instead of giving a process total root privileges, you can grant them only a specific subset instead.
- For example, if a program simply needs to set your system time, then it only needs CAP_SYS_TIME rather than total root.
- This could limit the potential damage that can be done; however, you must still be cautious with granting capabilities, as many of them can be abused to gain full root privileges anyway.
kernel.printk=3 3 3 3
Despite the value of dmesg_restrict, the kernel log will still be displayed in the console during boot.
- Malware that is able to record the screen during boot may be able to abuse this to gain higher privileges.
- This option prevents those information leaks.
- This must be used in combination with certain boot parameters described below to be fully effective.
kernel.unprivileged_bpf_disabled=1 net.core.bpf_jit_harden=2
eBPF exposes quite large attack surface
- As such, it must be restricted.
- These sysctls restrict eBPF to the CAP_BPF capability (CAP_SYS_ADMIN on kernel versions prior to 5.8) and enable JIT hardening techniques, such as constant blinding.
dev.tty.ldisc_autoload=0
This restricts loading TTY line disciplines to the CAP_SYS_MODULE capability to prevent unprivileged attackers from loading vulnerable line disciplines with the TIOCSETD ioctl, which has been abused in a number of exploits before.
vm.unprivileged_userfaultfd=0
The userfaultfd() syscall is often abused to exploit use-after-free flaws.
- Due to this, this sysctl is used to restrict this syscall to the CAP_SYS_PTRACE capability.
kernel.kexec_load_disabled=1
kexec is a system call that is used to boot another kernel during runtime.
- This functionality can be abused to load a malicious kernel and gain arbitrary code execution in kernel mode, so this sysctl disables it.
kernel.sysrq=4
The SysRq key exposes a lot of potentially dangerous debugging functionality to unprivileged users.
- Contrary to common assumptions, SysRq is not only an issue for physical attacks, as it can also be triggered remotely.
- The value of this sysctl makes it so that a user can only use the secure attention key, which will be necessary for accessing root securely.
- Alternatively, you can simply set the value to 0 to disable SysRq completely.
kernel.unprivileged_userns_clone=0
User namespaces are a feature in the kernel which aim to improve sandboxing and make it easily accessible for unprivileged users.
- However, this feature exposes significant kernel attack surface for privilege escalation, so this sysctl restricts the usage of user namespaces to the CAP_SYS_ADMIN capability.
- For unprivileged sandboxing, it is instead recommended to use a setuid binary with little attack surface to minimise the potential for privilege escalation.
- This topic is covered further in the sandboxing section.
NOTE: This sysctl only exists on certain Linux distributions, as it requires a kernel patch.
- If your kernel does not include this patch, you can alternatively disable user namespaces completely (including for root) by setting user.max_user_namespaces=0.
kernel.perf_event_paranoid=3
Performance events add considerable kernel attack surface and have caused abundant vulnerabilities.
This sysctl restricts all usage of performance events to the CAP_PERFMON capability (CAP_SYS_ADMIN on kernel versions prior to 5.8).
NOTE: This sysctl also requires a kernel patch that is only available on certain distributions.
- Otherwise, this setting is equivalent to kernel.perf_event_paranoid=2, which only restricts a subset of this functionality.
Recommended sysctl settings to change for Networks
net.ipv4.tcp_syncookies=1
This helps protect against SYN flood attacks, which are a form of denial-of-service attack, in which an attacker sends a large amount of bogus SYN requests in an attempt to consume enough resources to make the system unresponsive to legitimate traffic.
net.ipv4.tcp_rfc1337=1
This protects against time-wait assassination by dropping RST packets for sockets in the time-wait state.
net.ipv4.conf.all.rp_filter=1 net.ipv4.conf.default.rp_filter=1
These enable source validation of packets received from all interfaces of the machine.
- This protects against IP spoofing, in which an attacker sends a packet with a fraudulent IP address.
net.ipv4.conf.all.accept_redirects=0 net.ipv4.conf.default.accept_redirects=0 net.ipv4.conf.all.secure_redirects=0 net.ipv4.conf.default.secure_redirects=0 net.ipv6.conf.all.accept_redirects=0 net.ipv6.conf.default.accept_redirects=0 net.ipv4.conf.all.send_redirects=0 net.ipv4.conf.default.send_redirects=0
These disable ICMP redirect acceptance and sending to prevent man-in-the-middle attacks and minimize information disclosure.
net.ipv4.icmp_echo_ignore_all=1
This setting makes your system ignore all ICMP requests to avoid Smurf attacks, make the device more difficult to enumerate on the network and prevent clock fingerprinting through ICMP timestamps.
net.ipv4.conf.all.accept_source_route=0 net.ipv4.conf.default.accept_source_route=0 net.ipv6.conf.all.accept_source_route=0 net.ipv6.conf.default.accept_source_route=0
Source routing is a mechanism that allows users to redirect network traffic.
- As this can be used to perform man-in-the-middle attacks in which the traffic is redirected for nefarious purposes, the above settings disable this functionality.
net.ipv6.conf.all.accept_ra=0 net.ipv6.conf.default.accept_ra=0
Malicious IPv6 router advertisements can result in a man-in-the-middle attack, so they should be disabled.
net.ipv4.tcp_sack=0 net.ipv4.tcp_dsack=0 net.ipv4.tcp_fack=0
This disables TCP SACK.
- SACK is commonly exploited and unnecessary in many circumstances, so it should be disabled if it is not required.
Recommended sysctl settings to change for User Space
kernel.yama.ptrace_scope=2
ptrace is a system call that allows a program to alter and inspect another running process, which allows attackers to trivially modify the memory of other running programs.
- This restricts usage of ptrace to only processes with the CAP_SYS_PTRACE capability.
- Alternatively, set the sysctl to 3 to disable ptrace entirely.
vm.mmap_rnd_bits=32 vm.mmap_rnd_compat_bits=16
ASLR is a common exploit mitigation which randomises the position of critical parts of a process in memory. This can make a wide variety of exploits harder to pull off, as they first require an information leak. The above settings increase the bits of entropy used for mmap ASLR, improving its effectiveness.
The values of these sysctls must be set in relation to the CPU architecture. The above values are compatible with x86, but other architectures may differ.
fs.protected_symlinks=1 fs.protected_hardlinks=1
This only permits symlinks to be followed when outside of a world-writable sticky directory, when the owner of the symlink and follower match or when the directory owner matches the symlink's owner.
- This also prevents hardlinks from being created by users that do not have read/write access to the source file.
- Both of these prevent many common TOCTOU races.
fs.protected_fifos=2 fs.protected_regular=2
These prevent creating files in potentially attacker-controlled environments, such as world-writable directories, to make data spoofing attacks more difficult.
Modify the sysctl file
Add the following entries to the bottom of the /etc/sysctl.conf file to stop some spoofing attacks and enhance other security measures:
- /etc/sysctl.conf
... ... # Network Security. net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # IPv6 Security (if enabled). net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_source_route = 0 net.ipv6.conf.default.accept_source_route = 0 # Process Security. kernel.randomize_va_space = 2 kernel.kptr_restrict = 2 kernel.dmesg_restrict = 1 kernel.perf_event_paranoid = 3 kernel.yama.ptrace_scope = 2 kernel.panic_on_oops = 1 kernel.panic = 60 kernel.sysrq = 0 # File System Security. fs.protected_hardlinks = 1 fs.protected_symlinks = 1 fs.suid_dumpable = 0 fs.protected_fifos = 2 fs.protected_regular = 2 # Additional Security Measures. #dev.tty.ldisc_autoload = 0 #kernel.modules_disabled = 1 kernel.core_uses_pid = 1 kernel.panic_on_unrecovered_nmi = 1 kernel.panic_on_io_nmi = 1 kernel.unprivileged_bpf_disabled = 1 net.core.bpf_jit_harden = 2
Save the /etc/sysctl.conf file.
Activate the kernel settings that have been modified
This reloads the sysctl parameters:
sudo sysctl -p