Skip to content

Instantly share code, notes, and snippets.

@mishaturnbull
Last active August 29, 2023 01:46
Show Gist options
  • Save mishaturnbull/c925ce431b327e212f9c461ea86c71ee to your computer and use it in GitHub Desktop.
Save mishaturnbull/c925ce431b327e212f9c461ea86c71ee to your computer and use it in GitHub Desktop.

Debian System Hardening

I'm writing this as my notes on hardening a Kali Linux system running kernel version 5.6.14. This is by no means an exhaustive list of everything that could be done

This is meant for general-purpose, daily-use Linux laptop. Most notably, this is a one-user system. I'm the only user here, so countermeasures for user-infighting are not taken here. I also do a lot of programming (and debugging), so some features such as the kernel Yama module are not turned to their most restrictive settings.

I'm skipping pre- and during-install procedures, such as disk encryption, secure boot, etc.. You should start this process with an already-completed fully-encrypted, passworded install. I'm also assuming some very basic knowledge, such as what constitutes a strong password, and how to edit files.

Almost all of these changes require a reboot to take effect. I'm leaving out how to apply changes on-the-fly here, but expect to reboot after major changes. The etckeeper package may be helpful in rolling back ... unwanted changes.

THIS IS A WORK-IN-PROGRESS! EXPECT FREQUENT CHANGES!

Contents

Prior Arts

This guide is heavily based on several others like it:

Webserver Hardening

Packages to install that do their magic automatically:

  • libapache2-mod-security2: Apache webserver general purpose security hardening
  • libapache2-mod-evasive: Apache webserver anti-DoS/DDoS hardening

Firewalling

Install UFW (picked for ease of use, practicality is an important aspect of security):

sudo apt install ufw

Enable UFW (I recommend doing this while logged onto the system physically, this may interrupt SSH sessions):

sudo ufw enable

Allow necessary ports/services through like

sudo ufw allow SSH    # see app lists like `sudo ufw app list`
sudo ufw allow 18745  # allows port 18745

To see what firewall rules are currently in place:

sudo ufw status verbose		# shows ports and app info
sudo ufw status numbered	# shows with rule numbers (helpful to delete a firewall rule)

On that note, don't run network services when you don't need them. For example, I only ever start sshd when I need to login remotely:

systemctl disable sshd.service	# disables boot-time startup of SSH
systemctl stop sshd.service	# stop ssh if currently running
systemctl start sshd.service	# start ssh (for when needed)

Disable ICMP Ping

If not necessary, it's possible to disable the ability of other machines to ping yours. This can often let you fly under the radar in a network scan, since the default setting on many scanners is to only ping a host to determine if it's online.

Edit /etc/sysctl.conf and add/set the following line:

net.ipv4.icmp_echo_ignore_all=1

Disable uncommon/uneeded network protocols

Several less common network protocols can usually be blacklisted without impact. Edit the /etc/modprobe.conf file and add the following lines on an as-needed basis:

install dccp /bin/true		# blocks DCCP (Datagram Congestion Control Protocol)
install sctp /bin/true		# blocks SCTP (Stream Control Transmission Protocol)
install rds /bin/true		# blocks RDS (Reliable Datagram Sockets)
install tipc /bin/true		# blocks TIPC (Transparent Inter-Process Communication)

Forward root mail to your account

Edit /etc/aliases, and add (if not present) a line like:

# forwards root mail to misha@localhost.  other mails going to accounts that
# get forwarded to root also get forwarded on to misha@localhost
root:	misha@localhost

Disable firewire & thunderbolt

Unless you use them, you should disable Firewire and Thunderbolt kernel modules. Edit /etc/modprobe.d/blacklist-dma.conf:

blacklist firewire-core
blacklist thunderbolt

Rootkit hunters and antivirus

Yes, Linux can get malware too. Many guides recommend rkhunter, but I can't get it to work (updates fail continously with no actual solution available), so I recommend chkrootkit and clamav:

apt install clamav
apt install chkrootkit rkhunter

To run AV definition updates:

sudo rkhunter --update		# rkhunter definition updates
sudo freshclam                  # update clamav definitions

(chkrootkit doesn't seem to offer an update utility)

To use these tools:

sudo rkhunter -c		# run checks for rootkits, rkhunter style
sudo chkrootkit			# run checks for rootkits, chkrootkit style
sudo clamscan /home/misha       # run clamav on the /home/misha directory

If the machine is often left powered on overnight, it may be beneficial to schedule a regular scan with cron:

sudo crontab -e

The following cron jobs will run rkhunter, chkrootkit, and clamav and 1, 2, and 3 AM respectively, and email the results to misha@localhost.

1 * * * * (rkhunter --check 2>&1 | mail -s "cron rkhunter" misha@localhost)
2 * * * * (chkrootkit -q 2>&1 | mail -s "cron chkrootkit" misha@localhost)
3 * * * * (clamscan / 2>&1 | mail -s "cron clamav" misha@localhost)

SSH server securing

A few things to tweak with SSH. Disable the service if necessary, and then edit the /etc/ssh/sshd_config file:

PermitRootLogin no		# disable root login over ssh
PubkeyAuthentication yes	# allows public key authentication
PasswordAuthentication no	# disallow password login
X11Forwarding no		# disallow graphical window forwarding
HostbasedAuthentication no	# disallow host authentication
UsePAM yes			# use pluggable authentication modules
MaxAuthTries 5			# max 5 tries before you get kicked off

NFS securing

Unless NFS is to be used, disable the client daemons:

sudo systemctl disable nfs-blkmap.service
sudo systemctl disable nfs-config.service
sudo systemctl disable nfs-server.service
sudo systemctl disable nfs-utils.service

Sysctl configuration

Open /etc/sysctl.conf and make the following changes:

net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_messages=1
net.ipv4.tcp_syncookies=1
kernel.kptr_restrict = 2
kernel.core_uses_pid = 1
kernel.sysrq = 0
kernel.yama.ptrace = 2

Sysstat configuration

Install sysstat

sudo apt install sysstat

Enable sysstat by editing the file /etc/default/sysstat:

set ENABLED="true"

Update sysstat's cron job by editing /etc/cron.d/sysstat and set it to run as frequently as needed (I used 10min):

*/10 * * * * root command -v debian-sa1 > /dev/null && debian-sa1 1 1

Auditd configuration

Install auditd:

sudo apt install auditd audispd-plugins

Configure auditd by editing /etc/audit/audit.rules. Add the rules as specified in this SO answer.

Lynis Security Auditing package

Install Lynis:

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C80E383C3DE9F082E01391A0366C67DE91CA5D5F
sudo bash -c 'echo "deb [arch=amd64] http://packages.cisofy.com/community/lynis/deb/ jessie main" > /etc/apt/sources.list.d/cisofy-lynis.list'
sudo apt install apt-transport-https
sudo apt update
sudo apt install lynis

To run Lynis:

sudo lynis audit system

It's a useful tool, you may want to run it regularly and/or after system changes.

Tripwire IDS

Install Tripwire, answer yes to all the questions and make sure a strong password is used for both the site and local keys:

sudo apt install tripwire
sudo twadmin --create-polfile /etc/tripwire/twpol.txt

To run Tripwire:

sudo tripwire --check --interactive

USBGuard configuration

USBGuard is somewhat like a firewall for USB devices. It operates on a whitelist for what devices are allowed to connect to the machine, and can completely stop something like a BadUSB or Rubber Ducky in its tracks.

Install with:

sudo apt install usbguard

Don't start the service until the basic policy has been generated! To set up the initial policy:

sudo usbguard generate-policy | sudo tee /etc/usbguard/rules.conf

Start the service with:

sudo systemctl start usbguard

If you want to allow a device in the future, the process I use to whitelist something permanently is:

# make sure the device is plugged in for this part
sudo usbguard generate-policy | sudo tee -a /etc/usbguard/everything.conf
sudo cat /etc/usbguard/everything.conf /etc/usbguard/rules.conf | sort | uniq | sudo tee /etc/usbguard/rules.conf
sudo systemctl restart usbguard
# unplug and replug the device

This removes duplicates and prevents any rules being deleted. Also, if you need to use something in a rush, the default option allows devices that were already plugged in when the daemon is started. You could optionally stop the guard with sudo systemctl stop usbguard and restart it when you're done as well, although I don't recommend this.

Application Sandboxing

To sandbox arbitrary applications without setting up an full VM for each app, firejail is a useful sandboxing application. Install with:

sudo apt install firejail

To use it, start an application with firejail. Example:

firejail <command>

Restricting Mounting

Restrict device mounting on arbitrary partitions

System partitions can be mounted on arbitrary partitions unless specified otherwise with nodev. Open /etc/fstab and follow the flow:

  • For any line which satisfies all of the conditions:
    1. The filesystemtype is ext2, ext3, or ext4
    2. The mountpoint is not /
  • add nodev to the list of mount options in column 4

If any programs are being run in chroot jails, this step may require modification and/or skipping since it can be needed to create device files inside the chroot directory.

Lock down storage media

If there are any storage-only volumes mounted in /etc/fstab, they should have the nosuid and noexec options set in addition to nodev. Only use these options for volumes that store data only, as it will prevent execution of any code stored on those volumes.

Harden GNOME

Gnome does many thing automatically which can be disabled for increased security. As per usual, these result in a slight decrease of overall system friendlieness, and some [WORD] should be applied to determine whether these actions are necessary.

Disable mass storage automounting

Gnome tries to automatically mount storage volumes, such as flash drives. This is likely not a major issue if USBGuard is also installed.

sudo gconftool-2 --direct \
		--config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory \
		--type bool \
		--set /desktop/gnome/volume_manager/automount_media false
sudo gconftool-2 --direct \
		--config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory \
		--type bool \
		--set /desktop/gnome/volume_manager/automount_drives false
# verify changes were applied
sudo gconftool-2 -R /desktop/gnome/volume_manager

Disable GNOME thumbnailers if possible

Gnome's filesystem manager(s), such as Nautilus, use thumbnails to provide previews for files where possible. Some exploits against thumbnailers have been found previously, so if not necessary thumbnailers can be disabled:

sudo gconftool-2 --direct \
		--config-source xml:readwrite:/etc/gconf/gconf.xml.mandatory \
		--type bool \
		--set /desktop/gnome/thumbnailers/disable_all true

Verify File Permissions

Permissions allow for files/directories to conform to system policy, and therefore should be set appropriately.

Verify permissions on files used for authentication

The default permissions should be set for the following files if they have been altered:

cd /etc
sudo chown root:root passwd shadow group gshadow
sudo chmod 644 passwd group
sudo chmod 400 shadow gshadow

Verify world-writable directories have sticky bit

Setting the sticky bit on world-writeable directories will effectively prevent users from deleting each other's files. Such world-writable directories can be found with:

sudo find PART -xdev -type d \( perm -0002 -a ! -perm 1000 \) -print

where PART is a locally-mounted partition, such as /home or /var in many cases.

If the above command produces any output, fix each reported directory /dir with:

sudo chmod +t /dir

Find unnecessary world-writable files

World-writeable files should be kept to a minimum per the principle of least access. Find world-writable files with:

sudo find PART -xdev -type f -perm -0002 -print

where, as before, PART is a local partition.

If the above command produces any output, reduce each file to the minimum necessary permissions. If there is doubt, set permissions as follows:

sudo chmod o-w FILE

Find unnecessary SUID/SGID executables

Allowing SUID/SGID bits set on executables can let unauthorized users execute code above their privilege scope. Find SUID/SGID executables like:

sudo find PART -xdev \( -perm -4000 -o -perm -2000 \) -type f -print

If a file does not require SUID/SGID bits, remove them with:

sudo chmod -s FILE

Some files are expected to have SUID/SGID bits set on Linux. These files are as follows. Disclaimer: this table is likely outdated and may not contain every executable that needs restricting.

File Set ID Subsystem Disable?
/bin/mount uid root filesystems no
/bin/ping uid root networking no
/bin/ping6 uid root networking unless IPv6 is used
/bin/su uid root authentication no
/bin/umount uid root filesystems no
/sbin/mount.nfs uid root NFS unless NFS is used
/sbin/mount.nfs4 uid root NFS unless NFSv4 is used
/sbin/netreport gid root net unless users must modify ifaces
/sbin/pam_timestamp_check uid root PAM auth no
/sbin/umount.nfs uid root NFS unless NFS is used
/sbin/umount.nfs4 uid root NFS unless NFSv4 is used
/sbin/unix_chkpwd uid root PAM auth no
/usr/bin/at uid root cron/at no
/usr/bin/chage uid root passwd expiry unless users must see exp info
/usr/bin/chfn uid root user info unless usrs must chng finger info
/usr/bin/chsh uid root user info unless usrs must chng shell info
/usr/bin/crontab u/gid root cron/at unless users must use cron
/usr/bin/gpasswd uid root group auth no
/usr/bin/locate gid slocate locate db no
/usr/bin/lockfile gid mail procmail unless procmail is used
/usr/bin/newgrp uid root group auth no
/usr/bin/passwd uid root passwd auth no
/usr/bin/rcp uid root rsh yes (rsh is obsolete)
/usr/bin/rlogin uid root rsh yes
/usr/bin/rsh uid root rsh yes
/usr/bin/ssh-agent gid nobody SSH no
/usr/bin/sudo uid root sudo no
/usr/bin/sudoedit uid root sudo no
/usr/bin/wall gid tty console msging unless console messaging is used
/usr/bin/write gid tty console msging unless console messaging is used
/usr/bin/Xorg uid root X11 unless X11 is used
/usr/kerberos/bin/ksu uid root Kerberos auth unless Kerberos is used
/usr/libexec/openssh/ssh-keysign uid root SSH unless sshd uses hostbased auth
/usr/libexec/utempter/utempter gid utmp terminal support no
/usr/lib/squid/pam_auth uid root squid unless squid is used
/usr/lib/squid/ncsa_auth uid root squid unless squid is used
/usr/lib/vte/gnome-pty-helper gid utmp X11, GNOME unless X11 is used
/usr/sbin/ccreds_validate uid root PAM auth unless PAM authcaching is used
/usr/sbin/lockdev gid lock filesystems no
/usr/sbin/sendmail.sendmail gid smmsp sendmail client no
/usr/sbin/suexec uid root apache unless apache is used
/usr/sbin/userhelper uid root PAM auth restrict
/usr/sbin/userisdnctl uid root ISDN unless ISDN is used
/usr/sbin/usernetctl uid root usr net control unless usrs must modify ifaces

Harden User Accounts

The following section relates to hardening of user accounts. Note that while a strong password is an extremely important aspect of account security, I'm skipping over the pam_cracklib options to enforce a strong password and instead trusting that you, dear reader, will choose a suitably strong password in its place.

Set lockouts for failed password attempts

If you want to lock accounts after a number of incorrect login attempts, use pam_tally2.so by editing /etc/pam.d/system-auth:

# put this line at the top of the `auth` lines
auth	required	pam_tally2.so	deny=5 onerr=fail unlock_time=900

# put this line at the top of the `account` lines:
account	required	pam_tally2.so

Adjust the deny and unlock_time arguments as desired.

If you become locked out, and need to unlock your account, login as root and run the command

/sbin/pam_tally2 --user USERNAME --reset

Require authentication for single-user mode

(DISCLAIMER: I HAVE NOT TESTED THIS)

To force root password entry when booted to single-user mode, edit the /etc/inittab file:

~:S:wait:/sbin/sulogin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment