/harden.sh

Slackware hardening script

Primary LanguageShell

harden.sh

This is a script and a set of patch files to harden your Slackware Linux installation.

Why I made this

  • No Bastille for Slackware (and it's not updated anymore anyway)
  • Not a member of CIS, so no downloading of the ready made scripts
  • For learning
  • For minimizing the effort needed to tweak fresh installations
    • Also for consistency

How does it work?

The script is divided (well kinda) into dynamic and static changes. The static changes are applied with patch files and the dynamic modifications happen usually with certain commands.

Static changes

The generic etc patch assumes that you have at least the following packages installed:

  • network-scripts
  • sysvinit-scripts
  • etc
  • shadow
  • logrotate
  • sysklogd

Then there's separate patch files for different services/daemons. See the services section for more information.

What does it do?

DISCLAIMER: This is not a complete list.

Harden user accounts

  • Properly locks down system accounts (0 - SYS_UID_MAX && !root)
    • Lock the user's password
    • Sets shell to /sbin/nologin
    • Expire the account
    • Adds the accounts to /etc/ftpusers
  • Sets restrictions for normal users
    • Sets the maximum number of processes available to a single user (ulimit -u)
    • Sets the maximum size of core files created (ulimit -c)
    • Sets a session timeout (TMOUT) in certain conditions
    • Sets a maximum number of failed login attempts (faillog)
    • Sets stricter umask in all the following locations:
      • /etc/login.defs
      • /etc/limits
      • /etc/profile
  • Configures shells
    • Creates an option to use restricted shell (rbash)
      • Also sets it as default for new users
    • Restricts the number of available shells
    • Removes "unnecessary" shells
    • Creates .bash_logout to /etc/skel with few cleanups
  • Restricts logins
    • /etc/login.access
    • /etc/porttime
    • /etc/limits
    • /etc/login.defs
      • Disallow logins if home dir does not exist
    • SSH AllowGroups users
  • Sets useradd defaults
    • INACTIVE days to lock accounts after the password expires
    • rbash as default shell
  • Configures a bit better password policy to login.defs
  • Changes the hashing mechanism to SHA512 and more crypt rounds
  • Disallow the use of at
  • Removes user daemon from group adm (as we will take use of the adm group)
  • Fix gshadow with grpck

Groups

You can also utilize the above grsec groups with sudo, so the allowed users don't have the permissions by default:

ADMINS ALL=(:grsec_tpe) NOPASSWD: /usr/bin/newgrp

Configures services

  • Removes unnecessary services
    • xinetd (/etc/inetd.conf)
    • Goes through /etc/rc.d/rc.* and disables plenty of those
    • atd from rc.M
  • X11 -nolisten tcp

Enable some security and auditing related services

Hardens few specific services

  • SSH
  • Sendmail
    • Listen only on localhost by default
    • Disable the MSA
    • Don't show the version on the banner
  • sudo
    • Don't cache the password (timestamp_timeout) (should also mitigate against CVE-2013-1775)
    • Always require password with sudo -l (listpw)
    • noexec as default
    • Require root's password instead of user's
    • Send alerts on most errors
    • Additional logging to /var/log/sudo.log
  • PHP
  • Apache httpd

File system related

  • Hardens mount options (creates /etc/fstab.new)
    • Also, mount /proc with hidepid=2
  • Removes a bunch of SUID/SGID bits
    • at
    • chfn + chsh
    • uucp package
    • floppy package (/usr/bin/fdmount)
    • ssh-keysign
  • Sets more strict permissions on certain files that might contain secrets or other sensitive information
    • btmp & wtmp
    • Removes world-readibility from /var/www
    • Removes world-readibility from home directories
  • Enables RAID state monitoring with mdadm --monitor

TODO: Add a table about file ownership & permission changes. At least the most relevant ones.

Network related

  • Creates and enables a basic firewall
  • IP stack hardening through sysctl.conf
  • Enables TCP wrappers
    • NOTE: OpenSSH dropped support for TCP wrappers in 6.7 (and here's a good argument why this was a bad move!)
  • Optional static ARP cache through /etc/rc.d/rc.static_arp

Other controls

  • Restrict the use of su (prefer sudo instead)
    • /etc/suauth
    • /etc/porttime
    • /etc/login.defs:SU_WHEEL_ONLY
  • Modifies crontab behaviour a bit
    • Users in the wheel group are able to create cronjobs (as described in /usr/doc/dcron-4.5/README)
    • Increase cron's logging from notice to info
    • Notice that Dillon's cron does not support the /etc/cron.{allow,deny} lists
  • Clear /tmp on boot (also recommended in FHS)
    • TODO: is it redundant to have it both in rc.M and rc.S?
  • Removes unnecessary / potentially dangerous packages
    • netkit-rsh
    • uucp
    • floppy
  • Sets dmesg_restrict
  • Make installpkg store the MD5 checksums
  • Reduce the amount of trusted CAs
  • "Fix" the single-user mode to use su-login instead of agetty

Periodic checks

Some things are added to cron: TODO

sysstat

From sysstat.crond:

# Run system activity accounting tool every 10 minutes
*/10 * * * * if [ -x /usr/lib64/sa/sa1 ]; then /usr/lib64/sa/sa1 -S DISK 1 1; elif [ -x /usr/lib/sa/sa1 ]; then /usr/lib/sa/sa1 -S DISK 1 1; fi
# 0 * * * * /usr/lib/sa/sa1 -S DISK 600 6 &
# Generate a daily summary of process accounting at 23:53
53 23 * * * if [ -x /usr/lib64/sa/sa2 ]; then /usr/lib64/sa/sa2 -A; elif [ -x /usr/lib/sa/sa2 ]; then /usr/lib/sa/sa2 -A; fi

PGP

The import_pgp_keys() function imports a bunch of PGP keys to your trustedkeys.gpg keyring, so you can verify downloaded files/packages with gpgv. The keys that are imported are listed in the PGP_URLS[] and PGP_KEYS[] arrays.

Physical security related

Wipe

WARNING: This is a highly experimental and dangerous feature (and completely optional)! Use at your own risk!

This is something that has been cooking for a while now. It's a self-destruct sequence for your server :)

The patch creates a new runlevel (5) to your Slackware, which when activated, will remove LUKS headers from your disk and copies them inside the encrypted disk. So if anything should happen, the server is not restorable anymore, as the disk encryption keys are gone. When the runlevel is switched back (to say 3), the headers are written back to where they belong.

So to wipe LUKS headers, you just switch to runlevel 5: telinit 5 and to restore just switch back to 3: telinit 3.

There is still some issues, such as some services will be started again (such as crond) when returning to runlevel 3. This is because rc.M doesn't really consider users switching back and forth between runlevels. So this is a work-in-progress.

As a workaround, there is also a new runlevel 2 that can be used to safely return from runlevel 5. Now we don't need to care about daemons starting over and over again from rc.M (runlevel 3).

Logging

  • Makes default log files group adm readable (as in Debian)
    • Notice that this takes place only after logrotate. The ownerships/permissions of the existing logs are not modified.
  • Use shred to remove rotated log files
  • Enable process accounting (acct)
    • Log rotation for process accounting (pacct), since these files will grow huge
  • Enable system accounting (sysstat)
  • Enables the use of xconsole (or makes it possible). You can use it with sudo as follows: ADMINS ALL=(:adm) NOPASSWD: /usr/bin/xconsole
  • Enables bootlogd
  • Makes certain log files append only
  • Configures basic auditing based on stig.rules if audit is installed
    • NOTE: non-PAM systems don't set the loginuid properly, so some of the rules don't work when they have -F auid!=4294967295
  • Increase the default log retention period to 26 weeks
  • Increase wtmp log size through logrotate

Principle of least privilege

  • You can use the adm group to view log files, so you don't need to be root to do that. Just add a user to the adm group, or configure sudo as follows:
    • ADMINS ALL=(:adm) NOPASSWD: /bin/cat
    • View bad logins with: ADMINS ALL=(:adm) NOPASSWD: /usr/bin/lastb
    • Or recent logins: ADMINS ALL=(:adm) NOPASSWD: /usr/bin/lastlog ""
  • Remove floppy and scanner from CONSOLE_GROUPS
  • Restrict the use of at and cron from regular users

Benchmarks

Lynis benchmarks.

The test is performed against a setup like this:

  • A minimal Slackware installation with some 135 packages installed
    • No additional security related tools installed
    • Running with latest patches
  • One big root partition
    • No LUKS
  • The hardening is done with ./harden.sh -A
    • The system is booted after hardening
  • AUTH-9262 test disabled
Date Slackware version Packages installed Lynis version Tests performed Hardening index (before) Hardening index (after) harden.sh version
24.9.2014 slackware64-14.1 ~135 1.6.2 43 68 (+25) 155ad8536aed9e30197d645031c72d79ad93f3f4
2.7.2016 slackware64-14.2 ~148 2.2.0 171 (174) 53 72 (+19) 24ab7d6afe63ccef06f0434619cafd47db41d820

Notes

  • Rebooting the system after running this is highly recommended, since many startup scripts are modified
  • The script is quite verbose, so you might want to record it with script
  • It is best to run this script on a fresh Slackware installation for best results

Other security software

There is a bunch of security related software that you can find at SBo. You could consider installing these for additional security.

And from other sources than SBo:

Antivirus

I think it's justified and recommended to run an antivirus software on all of your Linux servers. This is because, even though the server's role would not be something like a file sharing server or a mail server, a proper antivirus is able to detect much more than these "traditional" malwares. I'm talking about rootkits, exploits, PHP shells and the like. Something that a malicious user might be holding at their home dirs or maybe some PHP shell was dropped through a vulnerable web application. If you would get an early warning from an antivirus software, it just might save you on that one occasion :)

So consider getting ClamAV from SBo.

grsecurity

You should also consider running grsecurity. Here's few links to get you started:

Bugs discovered during the making :)

Post-hardening checklist

After running the hardening script, the following actions still need to be performed manually:

  • Set LILO/GRUB password
    • Update LILO/GRUB with lilo || update-grub
  • Install at least the following additional software:
    • audit (and run harden.sh -S afterwards)
    • Aide
    • ClamAV
    • arpwatch
  • Make sure NTP is running
  • Configure remote log host
  • Add legit users to:
    • /etc/porttime
    • To the users group

TODO

  • Immutable flags with chattr on certain files
  • X hardening
  • Debian support
  • Some chroot stuff?
  • Logging of the script actions -> partly done
    • User account modifications
    • Get start/stop times and grab /var/log/secure between that range
  • some kernel module configurator thingie for /etc/rc.d/rc.modules
  • LUKS nuke
  • Provide the trustedkeys.gpg PGP keys with this tool?
  • Add some functionality, that compares your current file system against Slackware's MANIFEST (something like Alien's restore_fileperms_from_manifest.sh)
    • Some HIDS baseline generation from MANIFEST would also be really nice
  • Add CCE references?
  • /usr/bin/ch{mod,own} -> from PATH. since Debian has them under /bin
  • Create .preharden backups (only once?)
  • Java's CAs
  • Some kind of make buildworld script to rebuild everything with full RELRO, stack canaries, PIE & -D_FORTIFY_SOURCE=2

Auth/user account related

  • Some variables to read only?
    • From rbash: SHELL, PATH, ENV, or BASH_ENV
    • From system-hardening-10.2.txt: HISTCONTROL HISTFILE HISTFILESIZE HISTIGNORE HISTNAME HISTSIZE LESSSECURE LOGNAME USER
  • faillog for new users?
  • User quotas
  • PAM for Slackware?
    • Two-factor authentication
  • Shadow suite S/Key support (/usr/doc/shadow-4.1.4.3/README)
  • How do we reset faillogs after successful login?
  • Create .gnupg home directories
  • USERDEL_CMD from LOGIN.DEFS(5)
  • Is it possible to enforce password policy for root user also?
  • Use of at when in wheel group?

Guides to read

References

Hardening guides

Some of these documents are quite old, but most of the stuff still applies.

Other docs