This checklist is a personal reference tool for me, as well as a useful tool if you got a penetration test report saying vague stuff like โsecure configurationโ and โhardeningโ and you want to actually find out what to type into your keyboard.
๐๏ธ Servers
The most basic, bread-and-butter starting point and the first step to harden a server is to make sure its operating system and packages are up to date and currently supported. Running only supported operating systems is the bare minimum requirement for having a secure server network.
โ If youโre running unsupported operating systems, you are actively accepting the risks and vulnerabilities associated with it. However, realistically, there are always going to be those random outdated systems that are absolutely necessary for some business process to run, or that canโt be brought up for one reason or another. Ideally, those servers should be taken off the public Internet and only be accessible internally while you work on upgrading or replacing them.
- Packages: Linux server installations will come with a package manager, i.e.
apt
oryum
, and package updates can be applied to the server by runningapt update
/apt upgrade
oryum update
regularly. I personally use a maintenance script on our Ubuntu servers that runs bothapt update
/apt upgrade
andapt autoclean
/apt autoremove
to also clean up obsolete or unnecessary packages. There are also open-source solutions (i.e. Ansible) and commercial RMMs (i.e. Atera, Kaseya, NinjaOne, Ubuntu Pro) that allow you to remotely manage packages and update them. - Operating System: If you need to upgrade an unsupported Linux operating system or kernel to a supported version, Ubuntu LTS provides
apt dist-upgrade
anddo-release-upgrade
, and other Linux server distributions have similar commands and procedures.
The sublists below are specific security changes that apply to services.
๐ง Services
The specific configuration changes listed below should be applied to any services that a server, well, serves - whether that service is internal-only or externally facing. These configuration changes are extremely common findings in penetration tests that use Nessus scanners and other misconfiguration/vulnerability scanners.
Expand...
๐๏ธ Services: Database Services
Expand...
๐๏ธ Services: Database Services: MariaDB
Expand...
Common Port(s): 3306
๐๏ธ Services: Database Services: MySQL
Expand...
Common Port(s): 3306
The best way to quickly harden a MySQL installation is to run the built-in mysql_secure_installation
script and follow all the instructions it gives you, but manual hardening steps are provided below.
๐ Disable Remote Root Login
Expand...
๐ง Debian/Ubuntu:
sudo mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host!='localhost'; FLUSH PRIVILEGES;"
๐ Remove Anonymous Accounts
Expand...
๐ง Debian/Ubuntu:
mysql -u root -p
SELECT User, Host FROM mysql.user WHERE User = '';
DELETE FROM mysql.user WHERE User = '';
FLUSH PRIVILEGES;
exit;
๐ Set Strong Root Password
Expand...
๐ง Debian/Ubuntu:
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '{password}';
FLUSH PRIVILEGES;
exit;
๐ Services: Secure Shell Services
Expand...
๐ Services: Secure Shell Services: OpenSSH Server
Expand...
Package Name(s): openssh-server (apt)
Common Port(s): 22 (SSH)
Unless otherwise stated, most of the configuration changes below will require you to reload or restart the service to fully apply them.
๐ Disable Insecure Ciphers
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/ssh/sshd_config
MACs hmac-sha2-256,hmac-sha2-512,umac-64-etm@openssh.com,umac-128-etm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,chacha20-poly1305@openssh.com
๐ Disable Root Login
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/ssh/sshd_config
PermitRootLogin no
๐ Enforce Strong Passwords
Expand...
You can enforce strong SSH passwords using PAM.
๐ง Debian/Ubuntu:
Install the PAM package:
apt install libpam-pwquality
Then enable PAM in the SSH configuration file:
(editor) /etc/ssh/sshd_config
UsePAM yes
PasswordAuthentication yes
Then set your password requirements in the PAM configuration file:
(editor) /etc/pam.d/common-password
password requisite pam_pwquality.so retry=3 minlen={minimum length} ucredit=-{number of uppercase letters} lcredit=-{number of lowercase letters} dcredit=-{number of digits} ocredit=-{number of special characters}
Make sure the settings also match in this configuration file:
(editor) /etc/security/pwquality.conf
minlen = {minimum length}
ucredit = -{number of uppercase letters}
lcredit = -{number of lowercase letters}
dcredit = -{number of digits}
ocredit = -{number of special characters}
You can also block common passwords like this:
(editor) /etc/pam.d/common-password
password requisite ... dictcheck=1 (add to the end of the existing line)
(editor) /etc/security/pwquality.conf
dictcheck = 1
dictpath = /usr/share/dict/cracklib-small (or a custom wordlist you made)
Some recommended โbad passwordsโ to block if you make a custom wordlist are:
1234
123456
admin
letmein
password
qwerty
โ Verification: Change a userโs password with passwd (sudo passwd {user}) and verify that you canโt set a password that does not conform to the configured requirements.
๐ Whitelist Access
Expand...
The OpenSSH service should only be accessible to a limited range of IP addresses, ideally off a whitelist that is enforced by the local firewall and/or by the OpenSSH service configuration file. You can use the AllowUsers
and AllowGroups
directives to make access as granular as possible.
๐ง Debian/Ubuntu:
(editor) /etc/ssh/sshd_config
Match Address {ip,ip,ip...}
AllowUsers {user} {user} {user}...
๐ Services: Web Services
Expand...
๐ Services: Web Services: Apache HTTP
Expand...
Package Name(s): apache2 (apt), httpd (yum)
Common Port(s): 80 (HTTP), 443 (HTTPS), 8080 (Alternate HTTP), 8443 (Alternate HTTPS)
Unless otherwise stated, most of the Apache configuration changes below will require you to reload or restart Apache to fully apply them, i.e.:
service apache2 restart
systemctl restart apache2
File locations may also vary depending on how you set up your web server. You may also need to install or enable certain modules (mod_headers, mod_rewrite, mod_status) using a2enmod
where needed.
๐ Disable SSLv2/SSLv3/TLSv1/TLSv1.1
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/apache2/sites-enabled/(ssl config files)
SSLProtocol all -SSLv3 -SSLv2 -TLSv1 -TLSv1.1
โ Verification: Use nmap with the ssl-enum-ciphers script to scan open HTTP/HTTPS ports (usually 80/443) and verify that these ciphers donโt appear in the response.
๐ Disable TRACE
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/apache2/conf-enabled/security.conf
TraceEnable Off
โ Verification: Use nmap with the http-methods script to scan open HTTP/HTTPS ports (usually 80/443) and verify that the TRACE method doesnโt appear in the list of supported methods.
๐ Enable Custom Error Page
Expand...
The default Apache error page exposes version information and shows exactly what version and build of Apache you have on your server. To conceal this information, you should create a custom error page and set it as the default error page for 403 Forbidden, 404 Not Found, etc. in the Apache configuration file.
๐ง Debian/Ubuntu:
(editor) /etc/apache2/sites-enabled/(config files)
ErrorDocument 403 {file}
ErrorDocument 404 {file}
โ Verification: Browse to a nonexistent directory and verify that you get the custom error page.
๐ Hide Server Information
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/apache2/conf-enabled/security.conf
ServerSignature Off
ServerTokens Prod
โ
Verification: Use nmap with the service detection flag (-sV
) to scan open HTTP/HTTPS ports (usually 80/443) and verify that the banner grab shows โApacheโ instead of โApache x.x.xโ.
๐ Remove Unnecessary Files/Directories
Expand...
Remove or conceal the following dotfile (hidden by default on Linux unless listed with ls -la
) directories and files from /var/www/html
(or whichever file location is tied to your web server setup):
.cache
.config
.env
(can leak hardcoded secrets).eslintrc
.git
(can leak hardcoded secrets)/config
(can leak hardcoded secrets)
.gitattributes
.github
.gitignore
.gitinfo
.gitmodules
.gnupg
(contains PGP information).jshintrc
.nvmrc
.travis.yml
.viminfo
Remove or conceal the following other directories and files:
composer.json
composer.lock
docker-compose.yml
(exposes Docker configuration information and services)Gruntfile.js
npm-shrinkwrap.json
(exposes dependencies and version information)package.json
(exposes dependencies and version information)phpinfo
(exposes PHP version information)phpinfo.php
(exposes PHP version information)
If desired, you can entirely block specific sensitive file types from being browsed in /etc/apache2/conf-enabled/security.conf
(or wherever your Apache configuration files are):
RedirectMatch 404 /\.git
RedirectMatch 404 /\.svn
โ Verification: Browse to these directories and files in any web browser and verify that you receive either a 403 Forbidden or a 404 Not Found response. You can also use curl.
๐ mod_headers: Enforce HTTP Strict Transport Security (HSTS) Header
Expand...
The maximum age value can vary depending on your preferences, but the default value of 31536000 I usually use has never caused any issues.
๐ง Debian/Ubuntu:
(editor) /etc/apache2/sites-enabled/(config files)
Header always set Strict-Transport-Security max-age=31536000
โ Verification: Browse to the site and verify that you receive a Strict-Transport-Security header in the HTTP response, and that it has the configured age value. You can see it using your web browserโs Developer Tools (Network -> Headers), or through nmap and other header grabber tools.
๐ mod_rewrite: Enforce HTTP To HTTPS Rewrite
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/apache2/sites-enabled/(config files)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
๐ mod_status: Restrict Access To Server Status Page
Expand...
๐ง Debian/Ubuntu:
(editor) /etc/apache2/mods-enabled/status.conf
<Location /server-status>
SetHandler server-status
Require local
Require ip {ip ip ip...}
</Location>
๐ Services: Web Services: Apache Tomcat
Expand...
Common Port(s): 80 (HTTP), 443 (HTTPS), 8080 (Alternate HTTP), 8443 (Alternate HTTPS)
Unless otherwise stated, you will usually have to run the Tomcat shutdown and startup scripts (or restart the service if itโs configured as one) to fully apply these changes.
$CATALINA_HOME
on most installations is something like /home/tomcat/
or /opt/tomcat/
(Debian/Ubuntu). If you need to manually tell the server where it is, you can do it like this:
export CATALINA_HOME={directory}
๐ Restrict Access To Manager Application
Expand...
The context.xml
file controls access to the Manager Application that comes bundled with Tomcat. You will usually want to restrict this to only localhost access (127.0.0.1).
๐ง Debian/Ubuntu:
(editor) $CATALINA_HOME/webapps/manager/META-INF/context.xml
<Context antiResourceLocking="false" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1" />
</Context>
If you want to also allow a specific IP address, i.e. [1].[2].[3].[4], format it like [1]\.[2]\.[3]\.[4] and add it to the allow statement with an โorโ operator (|
).
You can also configure a login requirement and a specific user that is authorized to view the page after entering a password:
(editor) $CATALINA_HOME/conf/tomcat-users.xml
<tomcat-users>
<user username="admin" password="{password}" roles="manager-gui"/>
</tomcat-users>
โ
Verification: Browse to /manager/html
on your site and verify that you get a 403 Access Denied error page if you are not on the whitelist.
๐ Services: Web Services: PHP
Expand...
Common Port(s): 80 (HTTP), 443 (HTTPS), 8080 (Alternate HTTP), 8443 (Alternate HTTPS)
๐งฉ Software
This section applies to any software that is not a service being provided by a server (for that, see the first section) and is instead commercially produced user-facing, customer-facing, client-facing, or enterprise software with a user interface that is sold by a vendor and receives patching and support from said vendor, i.e. Office 365, Teams, Zoom, etc.
Most modern security frameworks, such as NIST (SP 800-171 Control 3.4.8), require software whitelisting on workstations as part of your overall posture - that is, controlling what programs employees can install on their laptops and not allowing the installation of unknown or blacklisted programs. As such, this section will focus on common enterprise software and the policies, usage requirements, and configuration you should have for that software in your organization, as well as how to set up and manage updates and patching where needed.
Expand...
Something hereโฆ
๐ฅ๏ธ Workstations
This section covers posture management and configuration management concerns for employee workstations (i.e. laptops and computers) outside of software (for that, see the previous section).