Skip to content

Ubuntu Server Hardening
The Advanced Guide To Server Security

Last updated: May 2022. For advanced users. Solid tech skills required.

Disclaimer

No system is safe. This is the second chapter on server security. While it presents more advanced measures to protect your Ubuntu server from most immediate threats, any skilled hacker or organisation with sufficient resources will probably find a way into the system.

Sudo access

Privileged access should be limited to users of a specific group, as detailed below.

Show me the step-by-step guide

Create a group called sudousers, and add both users gofossroot and gofossadmin (adjust user names according to your own setup):

sudo groupadd sudousers
sudo usermod -a -G sudousers gofossroot
sudo usermod -a -G sudousers gofossadmin

Backup the sudoers configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/sudoers /etc/sudoers-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/sudoers

Add the following line, if it's not already there:

%sudousers   ALL=(ALL:ALL) ALL

Save and close the file (:wq!). Finally, limit access to elevated privileges to the sudousers group:

sudo dpkg-statoverride --update --add root sudousers 4750 /bin/su

Check permissions with the following command, the terminal should display sudousers:

ls -lh /bin/su
Show me the 1-minute summary video


What is server hardening

/proc directory

The /proc directory contains potentially sensitive information about processes. By default, all users can access this directory. Follow the instructions below to continue hardening your server and keep sensitive data hidden from unauthorised users or programs.

Show me the step-by-step guide

Back up the fstab configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --preserve /etc/fstab /etc/fstab-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/fstab

Hide process information by adding the following line at the end of the file:

proc    /proc   proc    defaults,hidepid=2  0   0

Save and close the file (:wq!). Finally, remount the /proc directory:

sudo mount -o remount,hidepid=2 /proc
Show me the 1-minute summary video


Sudo meaning

PAM user authentication

By default, users are free to choose any password. Read on below for more details on how to enforce strong passwords and define quality requirements such as:

  • the maximum number of days a password can be used
  • the minimum number of days before a password can be changed
  • the minimum password length
  • the number of upper and lower case characters as well as digits to be used
Show me the step-by-step guide

Configure account parameters

Back up the login.defs configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --preserve /etc/login.defs /etc/login.defs-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/login.defs

Modify or add the following parameters:

PASS_MAX_DAYS   365
PASS_MIN_DAYS   1
PASS_WARN_AGE   30
SHA_CRYPT_MIN_ROUNDS 1000000
SHA_CRYPT_MAX_ROUNDS 1000000

Save and close the file (:wq!).

Let's apply the same settings to administrator users gofossroot and gofossadmin, which were created before password rules were hardened (adjust usernames according to your own setup):

sudo chage -m 1 -M 365 -W 30 gofossroot
sudo chage -m 1 -M 365 -W 30 gofossadmin

Make sure all changes were correctly applied:

sudo chage -l gofossroot
sudo chage -l gofossadmin

Some additional information on those settings:

Setting Description
PASS_MAX_DAYS Maximum number of days a password may be used.
PASS_MIN_DAYS Minimum number of days allowed between password changes.
PASS_WARN_AGE Number of days a warning is given before a password expires.
SHA_CRYPT_MIN_ROUNDS & SHA_CRYPT_MAX_ROUNDS By default, Linux stores the administrator password using a single, salted SHA-512 hash. To strengthen the password, use multiple rounds of a hash.

Configure PAM

Linux Pluggable Authentication Modules (PAM) is a powerful suite to manage user authentication. Install the following PAM module, which allows to strength-check passwords:

sudo apt install libpam-cracklib

Back up the pam.dconfiguration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/pam.d/common-password /etc/pam.d/common-password-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/pam.d/common-password

Modify or add the following parameters:

password requisite pam_cracklib.so retry=3 minlen=12 ucredit=-1 lcredit=-1 dcredit=-1 difok=3 gecoschec

In the same file, add the shadow option as well as an increased number of rounds in the following line:

password        [success=1 default=ignore]      pam_unix.so obscure use_authtok try_first_pass sha512 shadow rounds=1000000

Save and close the file (:wq!).

Some additional information on those settings:

Setting Description
retry = 3 Prompt users 3 times before returning an error.
minlen = 10 Minimum password length.
ucredit = -1 Password must have at least one upper case letter.
lcredit = -1 Password must have at least one lower case letter.
dcredit = -1 Password must have at least one digit.
difok = 3 At least 3 characters from the new password cannot have been used in the old password.
gecoschec Do not allow passwords with the account's name in it.
shadow rounds=1000000 By default, the pam_unix module stores the administrator password using a single, salted SHA-512 hash. To strengthen the password, Linux PAM can use multiple rounds of a hash.

Show me the 2-minute summary video


Sudo apt get update

sysctl network security

The system administration command sysctl allows to fine tune the kernel and can be used to improve network security. More details below.

Show me the step-by-step guide

Back up the sysctl configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /etc/sysctl.conf /etc/sysctl.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/sysctl.conf

Delete the content by typing :%d. Then enter or copy/paste the following content:

# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# Block SYN attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5

# Log Martians
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Ignore ICMP redirects
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Ignore Directed pings
net.ipv4.icmp_echo_ignore_all = 1

Save and close the file (:wq!), and load the new settings:

sudo sysctl -p

Some additional information on those security settings:

Measure Description
Enable IP spoofing protection Protect against IP spoofing where attackers disguise their IP, typically during Denial of Service (DoS) attacks.
Ignore ICMP broadcast requests Avoid that the server participates in a Smurf attack.
Ignore ICMP redirects Protect against forged ICMP redirect packets used by attackers to cause a Denial of Service (DoS) attack.
Disable source packet routing Protect against source routed packets used by attackers to obscure their identity and location.
Block SYN attacks Protect against SYN attacks, a form of Denial of Service (DoS) attack.
Log martians Protect against martian packets. These are spoofed packets with a source address which is obviously wrong. They can be used during Denial of Service (DoS) attacks.
Ignore directed pings The ping command can be used to check the connection status with your server. But it can also be misused to perform attacks.

Show me the 1-minute summary video


Sudo apt update

LMD & ClamAV

Linux Malware Detect (LMD) and ClamAV are open source antivirus and malware scanner solutions. Follow the instructions below to install and configure them on your server.

Show me the step-by-step guide

Malware scanner (LMD)

Install LMD using the following commands:

sudo apt install wget
sudo wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
sudo tar -xvf maldetect-current.tar.gz
cd maldetect-1.6.4
sudo ./install.sh

Back up the maldet configuration file. If something goes wrong, you'll be able to recover the initial settings:

sudo cp --archive /usr/local/maldetect/conf.maldet /usr/local/maldetect/conf.maldet-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /usr/local/maldetect/conf.maldet

Modify or add the following parameters (adjust the administrator user gofossadmin according to your own setup):

# send malware inspection results to local system administrator gofossadmin (adjust accordingly) in /var/mail/gofossadmin

email_alert="1"
email_addr="gofossadmin@localhost"

# move to quarantine & alert if malware is detected
quarantine_hits="1"

# don't automatically delete clean string-based malware injections (in case of false positives, avoid deleting files)
quarantine_clean="0"

# allow suspending users hit by malware
quarantine_suspend_user="1"

#use ClamAVs scanner engine (faster scans)
scan_clamscan="1"

#scan root owned files
scan_ignore_root="0"

Save and close the file (:wq!). Update LMD to the latest version and download the most recent malware definitions:

sudo maldet --update-ver
sudo maldet --update

Antivirus (ClamAV)

Install ClamAV with the following command:

sudo apt install clamav

Check if the software was successfully installed:

clamscan --version

Update the virus signature database:

sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam

Enable ClamAV to be automatically launched after each reboot:

sudo systemctl enable clamav-freshclam

Test LMD and ClamAV

We'll use dummy malware provided by the European Expert Group for IT Security (EICAR) to test the malware scanner and antivirus. Download the files as follows:

cd /var/www/html
sudo wget http://www.eicar.org/download/eicar.com
sudo wget http://www.eicar.org/download/eicar.com.txt
sudo wget http://www.eicar.org/download/eicar_com.zip
sudo wget http://www.eicar.org/download/eicarcom2.zip

Use ClamAV to recursively scan the directory /var/www/html and all its subdirectories for viruses:

sudo clamscan --recursive --infected /var/www/html

The terminal should prompt something similar to:

/var/www/html/eicar_com.zip: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicar.com: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicarcom2.zip: Win.Test.EICAR_HDB-1 FOUND
/var/www/html/eicar.com.txt: Win.Test.EICAR_HDB-1 FOUND

----------- SCAN SUMMARY -----------
Known viruses: 6880642
Engine version: 0.102.2
Scanned directories: 1
Scanned files: 5
Infected files: 4
Data scanned: 0.01 MB
Data read: 0.01 MB (ratio 1.00:1)
Time: 54.632 sec (0 m 54 s)

Next, use LMD to scan the same directory for malware:

sudo maldet --scan-all /var/www/html

The output should contain a scan ID, something similar to 200510-1954.2127 (adjust accordingly). Inspect the detailed report with:

sudo maldet --report 200510-1954.2127

A list of all scan reports can be accessed with:

sudo maldet -e list

Finally, remove all quarantined files:

sudo ls /usr/local/maldetect/quarantine/
sudo rm -rf /usr/local/maldetect/quarantine/*

Schedule LMD scans

The malware scanner LMD is configured to run a daily cron job (/etc/cron.daily/maldet) which updates the malware registry and scans all home directories. That should be sufficient for most use cases. To keep the server load down, disable real time monitoring to avoid scans running every 10 minutes:

sudo rm /etc/cron.d/maldet_pub
sudo maldet -k

Schedule ClamAV scans

The virus signature database is updated by the freshclam service. By default, it fetches updates every hour, you can change the frequency in the /etc/clamav/freshclam.conf file and restart the service with sudo service clamav-freshclam restart.

To schedule antivirus scans, create an empty log file:

sudo touch /var/log/clamav/clamscan.log

Create a cron job to scan for viruses every day:

sudo vi /etc/cron.daily/clamav

Add the following content:

#!/bin/sh

MYLOG=/var/log/clamav/clamscan.log
echo "Scanning for viruses at `date`" >> $MYLOG
clamscan --recursive --infected --max-filesize=100M --max-scansize=100M --exclude=/boot / >> $MYLOG 2>&1

Save and close the file (:wq!). Now, make the script executable:

sudo chmod +x /etc/cron.daily/clamav

Note that we used the following options to run clamscan in the script, which should be adapted to your own needs:

Parameter Description
--recursive Recursively scan directories and sub-directories for viruses.
--infected Only print infected files in the scan report, instead of all scanned files.
--max-filesize=100M, --max-scansize=100M Scan files with a file size of up to 100 MB. By default, ClamAV doesn't scan files larger than 20 MB.
--exclude=/boot In this example, we exclude the directory /boot from the scan. Make sure to adjust this to your own setup, the option can also be used multiple times to exclude multiple directories.
/ Directory which ClamAV is supposed to scan for viruses. In this example, we want to scan the entire root folder /. Of course, you can adapt the target directory according to your own needs.

Test the cron job. Be patient, depending on the size of the target directories the scan can take a while:

sudo bash /etc/cron.daily/clamav
sudo cat /var/log/clamav/clamscan.log

The terminal output should look something like:

----------- SCAN SUMMARY -----------
Infected files: 0
Time: 54.052 sec (0 m 54 s)
Start Date: 2021:05:22 21:05:29
End Date:   2021:05:22 21:06:23
Show me the 4-minute summary video


What is sudo

File and directory permissions

Read on below to find out how to restrict unauthorised access to the system files.

Show me the step-by-step guide
sudo chmod 600 /etc/crontab
sudo chmod 600 /etc/ssh/sshd_config
sudo chmod 700 /etc/cron.d
sudo chmod 700 /etc/cron.daily
sudo chmod 700 /etc/cron.hourly
sudo chmod 700 /etc/cron.weekly
sudo chmod 700 /etc/cron.monthly
sudo chmod 750 /home/gofossroot
sudo chmod 750 /home/gofossadmin
Show me the 1-minute summary video

Tell me more about Linux permissions

umask restricts user access to newly created files or directories. There are three user classes:

User Class Description
User The file's or directory's owner.
Group Users belonging to the file's or directory's group.
Others Users who are neither owner nor member of the file's or directory's group.

And there are three access restrictions:

Access restriction Description Decimal value
Read ( r ) Read or view the file or directory. 4
Write ( w ) Write to, edit or modify the file or directory. 2
Execute ( x ) Execute the file or directory. 1

umask restricts access to newly created files or directories by summing up those three decimal values:

umask Value Restrictions
--- 0 = 0 + 0 + 0 Can read, write & execute.
--x 1 = 0 + 0 + 1 Can read & write, but not execute.
-w- 2 = 0 + 2 + 0 Can read & execute, but not write.
-wx 3 = 0 + 2 + 1 Can read, but not write or execute.
r-- 4 = 4 + 0 + 0 Can write & execute, but not read.
r-x 5 = 4 + 0 + 1 Can write, but not read or execute.
rw- 6 = 4 + 2 + 0 Can execute, but not read or write.
rwx 7 = 4 + 2 + 1 Can't read, write or execute.

umask consists of three values, one for each user class. For example, changing umask from 022 to 027 prevents "others" from reading, writing or executing files and directories:

Umask User restrictions Group restrictions Others restrictions Resulting permissions
022 --- -w- -w- • The file's or directory's owner can read, write & execute.
• Members of the file's or directory's group can read and execute, but not write.
• Users who are neither owner nor member of the file's or directory's group can read and execute, but not write.
• In other words: the file's or directory's owner has full access, the group and others can only read and execute it.
027 --- -w- rwx • The file's or directory's owner can read, write & execute.
• Members of the file's or directory's group can read and execute, but not write.
• Users who are neither owner nor member of the file's or directory's group can't read, write or execute it.
• In other words: the file's or directory's owner has full access, the group can only read and execute it, and others don't have access.

Note that throughout this guide, the chmod command is often used to define permissions for files or directories. Contrary to umask, which sets the default restrictions for newly created files or directories, the chmod command sets permissions for existing files or directories. As such, the values between umask and chmod are somewhat symmetrical.


Core dumps

Core dump

A core dump is a file containing a program's memory when it crashes. That's useful for debugging purposes, but can leak sensitive data. It's safe to disable if you don't do troubleshooting. More details below.

Show me the step-by-step guide

Backup the configuration files:

sudo cp --archive /etc/security/limits.conf /etc/security/limits.conf-COPY-$(date +"%Y%m%d%H%M%S")

sudo cp --archive /etc/sysctl.conf /etc/sysctl.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the first configuration file:

sudo vi /etc/security/limits.conf

Add the following lines at the end:

* soft core 0
* hard core 0

Save and close the file (:wq!).

Open the second configuration file:

sudo vi /etc/sysctl.conf

Add the following lines at the end:

# Disable coredumps
fs.suid_dumpable=0

Save and close the file (:wq!). Finally, apply the changes:

sudo sysctl -p
Show me the 1-minute summary video


Kernel modules

Kernel modules

The Linux kernel is the core of the operating system. It controls the hardware, the memory, tasks and processes, and so on. Kernel modules are pieces of code that extend the kernel's functionality, for example to access new hardware. Having said that, kernel modules can also be misused to load malicious software or gain unauthorised access to the server. To avoid this, disallow the loading of unused kernel modules, as shown below.

Show me the step-by-step guide

Backup the configuration file:

sudo cp --archive /etc/modprobe.d/blacklist.conf /etc/modprobe.d/blacklist.conf-COPY-$(date +"%Y%m%d%H%M%S")

Open the configuration file:

sudo vi /etc/modprobe.d/blacklist.conf

Add the following lines at the end:

# Instruct modprobe to force inactive modules to always fail loading
install cramfs /bin/false
install freevxfs /bin/false
install hfs /bin/false
install hfsplus /bin/false
install jffs2 /bin/false
install udf /bin/false

Save and close the file (:wq!).

Show me the 1-minute summary video


Ubuntu server security