hardening icon indicating copy to clipboard operation
hardening copied to clipboard

Hardening Ubuntu. Systemd edition.

image::logo/horizontal.png[Ubuntu Hardening]

= Hardening Ubuntu. Systemd edition. :icons: font

A quick way to make a Ubuntu server a bit more secure.

Use the newly installed and configured system as a reference, or golden, image. Use that image as a baseline installation media and ensure that any future installation comply with benchmarks and policies using a configuration management tool, e.g https://www.ansible.com/[Ansible] or https://puppet.com/[Puppet].

Tested on Ubuntu 20.04 Focal Fossa and Ubuntu 22.04 Jammy Jellyfish.

If you're just interested in the security focused systemd configuration, it's available as a link:systemd.adoc[separate document].

If you're interested in testing your host settings, you'll find the link:README.adoc#tests[instructions here].

NOTE: This is a constant work in progress. Make sure you understand what it does. Read the code and do not run this script without first testing in a non-operational environment.

NOTE: There is a https://slsa.dev/[SLSA] artifact present under the https://github.com/konstruktoid/ansible-role-hardening/actions/workflows/slsa.yml[slsa workflow] for file checksum verification.

== Packer template and Ansible playbook A https://www.packer.io/[Packer] template is available in the link:packer/[Packer directory].

An Ansible playbook is available in the https://github.com/konstruktoid/ansible-role-hardening[konstruktoid/ansible-role-hardening] repository.

== Howto . Start the server installation. . Pick language and keyboard layout. . Select "Ubuntu Server (minimized)". . Configure network connections. . Partition the system, see below for recommendations. . Do not install the OpenSSH server, "Featured Server Snaps", or any other packages. . Finish the installation and reboot. . Log in. . If wanted, set a Grub2 password with grub-mkpasswd-pbkdf2. See https://help.ubuntu.com/community/Grub2/Passwords[https://help.ubuntu.com/community/Grub2/Passwords] for more information. . Install necessary packages: sudo apt-get -y install git net-tools procps --no-install-recommends. . Download the script: git clone https://github.com/konstruktoid/hardening.git. . Change the configuration options in the ubuntu.cfg file. . Run the script: sudo bash ubuntu.sh. . Reboot.

=== Recommended partitions and options [source,shell]

/boot (rw) /home (rw,nosuid,nodev) /var/log (rw,nosuid,nodev,noexec) /var/log/audit (rw,nosuid,nodev,noexec) /var/tmp (rw,nosuid,nodev,noexec)

Note that /tmp will be added automatically by the script.

== Configuration options [source,shell]

FW_ADMIN='127.0.0.1' // <1> SSH_GRPS='sudo' // <2> SSH_PORT='22' // <3> SYSCTL_CONF='./misc/sysctl.conf' // <4> AUDITD_MODE='1' // <5> AUDITD_RULES='./misc/audit-base.rules ./misc/audit-aggressive.rules ./misc/audit-docker.rules' // <6> LOGROTATE_CONF='./misc/logrotate.conf' // <7> NTPSERVERPOOL='0.ubuntu.pool.ntp.org 1.ubuntu.pool.ntp.org 2.ubuntu.pool.ntp.org 3.ubuntu.pool.ntp.org pool.ntp.org' // <8> TIMEDATECTL='' // <9> VERBOSE='N' // <10> AUTOFILL='N' // <11> ADMINEMAIL="root@localhost" // <12> KEEP_SNAPD='Y' // <13> CHANGEME='' // <14>

Configuration files

ADDUSER='/etc/adduser.conf' AUDITDCONF='/etc/audit/auditd.conf' AUDITRULES='/etc/audit/rules.d/hardening.rules' COMMONPASSWD='/etc/pam.d/common-password' COMMONACCOUNT='/etc/pam.d/common-account' COMMONAUTH='/etc/pam.d/common-auth' COREDUMPCONF='/etc/systemd/coredump.conf' DEFAULTGRUB='/etc/default/grub.d' DISABLEFS='/etc/modprobe.d/disablefs.conf' DISABLEMOD='/etc/modprobe.d/disablemod.conf' DISABLENET='/etc/modprobe.d/disablenet.conf' FAILLOCKCONF='/etc/security/faillock.conf' JOURNALDCONF='/etc/systemd/journald.conf' LIMITSCONF='/etc/security/limits.conf' LOGINDCONF='/etc/systemd/logind.conf' LOGINDEFS='/etc/login.defs' LOGROTATE='/etc/logrotate.conf' PAMLOGIN='/etc/pam.d/login' PSADCONF='/etc/psad/psad.conf' PSADDL='/etc/psad/auto_dl' RESOLVEDCONF='/etc/systemd/resolved.conf' RKHUNTERCONF='/etc/default/rkhunter' RSYSLOGCONF='/etc/rsyslog.conf' SECURITYACCESS='/etc/security/access.conf' SSHFILE='/etc/ssh/ssh_config' SSHDFILE='/etc/ssh/sshd_config' SYSCTL='/etc/sysctl.conf' SYSTEMCONF='/etc/systemd/system.conf' TIMESYNCD='/etc/systemd/timesyncd.conf' UFWDEFAULT='/etc/default/ufw' USERADD='/etc/default/useradd' USERCONF='/etc/systemd/user.conf'


<1> The IP addresses that will be able to connect with SSH, separated by spaces. <2> Which group the users have to be member of in order to acess via SSH, separated by spaces. <3> Configure SSH port. <4> Stricter sysctl settings. <5> Auditd failure mode. 0=silent 1=printk 2=panic. <6> Auditd rules. <7> Logrotate settings. <8> NTP server pool. <9> Add a specific time zone or use the system default by leaving it empty. <10> If you want all the details or not. <11> Let the script guess the FW_ADMIN and SSH_GRPS settings. <12> Add a valid email address, so PSAD can send notifications. <13> If 'Y' then the snapd package will be held to prevent removal. <14> Add something just to verify that you actually glanced the code.

== Functions

=== Function list

==== pre Setup script, sets APT flags and permission checks.

==== firewall Enable ufw, use /etc/sysctl.conf, prepare to psad, and allow port 22 from $FW_ADMIN.

==== disablenet Disable dccp sctp rds tipc protocols.

==== disablemnt Disable cramfs freevxfs jffs2 hfs hfsplus udf file systems.

==== systemdconf Disable coredumps and crash shells, set DefaultLimitNOFILE and DefaultLimitNPROC to 1024.

==== journalctl Compress logs, forward to syslog and make log storage persistent. Ensure rsyslog writes logs with stricter permissions.

==== timesyncd Add four NTP-servers with a latency < 50ms from $NTPSERVERPOOL.

==== fstab Configure /tmp/ and /var/tmp/. Remove floppy drivers from /etc/fstab and add hidepid=2 to /proc.

==== prelink Undo prelinking, and remove prelink package.

==== aptget Configure dpkg and apt-get. apt-get update and upgrade.

==== hosts /etc/hosts.allow and /etc/hosts.deny restrictions.

==== logindefs Modify /etc/login.defs, e.g. UMASK, password age limits and SHA_CRYPT_MAX_ROUNDS.

==== sysctl Update $SYSCTL with $SYSCTL_CONF.

==== limits Set hard and soft limits.

==== adduser Configure useradd and adduser to set /bin/false as default shell, home directory permissions to 0750 and lock users 30 days after password expires.

==== rootaccess Limit /etc/securetty to console, and root from 127.0.0.1 in /etc/security/access.conf.

==== packages Installs acct aide-common apparmor-profiles apparmor-utils auditd audispd-plugins debsums gnupg2 haveged libpam-apparmor libpam-pwquality libpam-tmpdir needrestart openssh-server postfix rkhunter sysstat systemd-coredump tcpd psad update-notifier-common vlock.

Removes apport* autofs avahi* beep git pastebinit popularity-contest rsh* rsync talk* telnet* tftp* whoopsie xinetd yp-tools ypbind.

==== sshdconfig Configure the OpenSSH daemon. The configuration changes will be placed in the directory defined by the Include option if present, otherwise the default sshd_config will be modified.

==== password Configure pam_pwquality.so and pam_tally2.so.

==== cron Allow root to use cron. Mask atd.

==== ctraltdel Disable Ctrl-alt-delete.

==== auditd Configure https://www.man7.org/linux/man-pages/man8/auditd.8.html[auditd], use $AUDITD_RULES and set failure mode $AUDITD_MODE.

==== disablemod Disable bluetooth bnep btusb cpia2 firewire-core floppy n_hdlc net-pf-31 pcspkr soundcore thunderbolt usb-midi usb-storage uvcvideo v4l2_common kernel modules.

Note that disabling the usb-storage will disable any usage of USB storage devices, if such devices are needed USBGuard should be configured accordingly.

==== aide Configure https://aide.github.io/[aide].

==== rhosts Remove hosts.equiv and .rhosts.

==== users Remove games gnats irc list news sync uucp users.

==== suid Remove suid bits from the executables listed in link:misc/suid.list[this document].

==== umask Set bash and /etc/profile umask.

==== apparmor Enforce present apparmor profiles.

==== path Set root path to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, and user path to /usr/local/bin:/usr/bin:/bin.

==== logindconf Configure systemd/logind.conf and use KillUserProcesses.

==== resolvedconf Configure systemd/resolved.conf.

==== rkhunter Configure https://sourceforge.net/projects/rkhunter/[rkhunter].

==== issue Update /etc/issue /etc/issue.net /etc/motd.

==== apport Disable apport, ubuntu-report and popularity-contest.

==== lockroot Lock the root user account.

==== coredump Disable coredumps with systemd/coredump.conf.

==== postfix Configure https://www.postfix.org[postfix]. Disable the VRFY command, configure smtpd_banner, smtpd_client_restrictions and inet_interfaces.

==== motdnews Disable motd-news.

==== usbguard Install and configure https://usbguard.github.io/[usbguard].

==== compilers Restrict compiler access.

==== kernel Set lockdown=confidentiality if /sys/kernel/security/lockdown is present.

==== sudo Configure sudo with use_pty, logfile, !visiblepw, !pwfeedback, passwd_timeout and timestamp_timeout.

Restrict su to the sudo group.

==== psad Configure https://www.cipherdyne.org/psad/[psad].

==== systemddelta If verbose, show systemd-delta.

==== post Ensure secureboot-db is installed, update grub and ensure strict permissions on boot files.

==== reboot Print if a reboot is required.

=== Function execution order [source,shell]

f_pre f_kernel f_firewall f_disablenet f_disablefs f_disablemod f_systemdconf f_resolvedconf f_logindconf f_journalctl f_timesyncd f_fstab f_prelink f_aptget_configure f_aptget f_hosts f_issue f_sudo f_logindefs f_sysctl f_limitsconf f_adduser f_rootaccess f_package_install f_psad f_coredump f_usbguard f_postfix f_apport f_motdnews f_rkhunter f_sshconfig f_sshdconfig f_password f_cron f_ctrlaltdel f_auditd f_aide f_rhosts f_users f_lockroot f_package_remove f_suid f_restrictcompilers f_umask f_path f_aa_enforce f_aide_post f_aide_timer f_aptget_noexec f_aptget_clean f_systemddelta f_post f_checkreboot

== Tests There are approximately 760 https://github.com/bats-core/bats-core[Bats tests] for most of the above settings available in the link:tests/[tests directory].

[source,shell]

sudo apt-get -y install bats git clone https://github.com/konstruktoid/hardening.git cd hardening/tests/ sudo bats .

=== Test automation using Vagrant Running bash ./runTests.sh will use https://www.vagrantup.com/[Vagrant] to run all above tests, https://github.com/CISOfy/Lynis[Lynis] and https://www.open-scap.org/[OpenSCAP] with a https://www.cisecurity.org/benchmark/ubuntu_linux[CIS Ubuntu benchmark] on all supported Ubuntu versions.

The script will generate a file named TESTRESULTS.adoc and CIS report in HTML-format.

=== Testing a host Running bash ./runHostTests.sh, located in the link:tests/[tests directory], will generate a TESTRESULTS-<HOSTNAME>.adoc report.

== Recommended reading https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux[Canonical Ubuntu 20.04 LTS STIG - Ver 1, Rel 3] + https://www.cisecurity.org/benchmark/distribution_independent_linux/[CIS Distribution Independent Linux Benchmark] + https://www.cisecurity.org/benchmark/ubuntu_linux/[CIS Ubuntu Linux Benchmark] + https://www.ncsc.gov.uk/collection/end-user-device-security/platform-specific-guidance/ubuntu-18-04-lts[EUD Security Guidance: Ubuntu 18.04 LTS] + https://wiki.ubuntu.com/Security/Features + https://help.ubuntu.com/community/StricterDefaults +

== Contributing Do you want to contribute? That's great! Contributions are always welcome, no matter how large or small. If you found something odd, feel free to https://github.com/konstruktoid/hardening/issues/[submit a new issue], improve the code by https://github.com/konstruktoid/hardening/pulls[creating a pull request], or by https://github.com/sponsors/konstruktoid[sponsoring this project].

Logo by https://github.com/reallinfo[reallinfo].