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
Expand...
ποΈ Database Services
ποΈ MariaDB
Expand...
Common Port(s): 3306
ποΈ 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;
π Secure Shell (SSH) 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}...
π Web (HTTP/HTTPS) 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
π 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>
π 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.
π PHP
Expand...
Common Port(s): 80 (HTTP), 443 (HTTPS), 8080 (Alternate HTTP), 8443 (Alternate HTTPS)