Computer security is a topic that needs constant work. Every day new threats and new security recommendation pop up on the technology radar. I already wrote several posts on this topic.
The current post can be seen as a continuation of Security: Maintaining a secure WordPress blog
So bellow are some updates to the configuration of the blog to increase security and mitigate some new discovered security issues.
Hide Apache server version
The Server
HTTP header in your server responses indicates your Apache version by default.
It will be more difficult for a hacker to attack your website if he does not know the version you use.
For instance, if you are on a Fedora Linux server, you can add the following config to several places.
Add as a general configuration under /etc/httpd/conf/httpd.conf. By doing this it will apply for any website resource you are hosting on that server. As an alternative you can add it to .htaccess or to the specific file as blog.voina.org.conf
You will have to change the ServerSignature and the ServerTokens values, as shown bellow:
# Hide the version from the 'Server' HTTP Header. Display only "Server: Apache"
ServerTokens Prod
# Do not add a trailing footer line under server-generated document,
# containing the server name and its version.
ServerSignature Off
Hide your version of PHP to limit your exposure to attacks and increase your server’s security.
Knowing the version of PHP used on a server helps an attacker to target security holes and exploit vulnerabilities.
To hide your PHP version, you need to find your php.ini configuration file (usually /etc/php.ini) and locate the keyword expose_php
to set its value to off
.
# /etc/php.ini
# expose_php = off
Once the php.ini file modified, you will need to restart your web server
Hide HTTP headers that are used to pass additional information with HTTP response or HTTP requests.
The X-Frame-Options is used to prevent the site from clickjacking attacks.
Add as a general configuration under /etc/httpd/conf/httpd.conf or under .htaccess
<IfModule mod_headers.c>
Header always set X-FRAME-OPTIONS "DENY"
</IfModule>
Disable the auto detection of resource type
Protect yourself from malicious exploitation via MIME sniffing. Internet Explorer and Chrome browsers have a feature called “MIME-Type sniffing” that automatically detects a web resource’s type. This means, for example, that a resource identified as an image can be read as a script if its content is a script. This can be used by malicious actors to force you to execute hidden scripts.
Add as a general configuration under /etc/httpd/conf/httpd.conf or under .htaccess
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
</IfModule>
Add Content Security Policy (optional)
Protect your website from cross-site scripting (XSS) attacks by setting up a restrictive Content-Security-Policy.
Note that you have to be careful because you may use without knowing a lot of off site scripts and your site may no longer work. You should make sure you list in the configuration all the sites from which you use scripts (Google, JetPack, etc. )
Add as a general configuration under /etc/httpd/conf/httpd.conf or under .htaccess
<IfModule mod_headers.c>
Header set Content-Security-Policy "script-src 'self' https://www.google.com"
</IfModule>
This example allows scripts from the same origin (same scheme, host and port) and google.com.
Add expiration headers for mime types.
This is not a security but a performance related configuration. You get better speed rating for the blog if you are instructing the browsers of your visitors what to cache and for how log.
You have to simply add something like the bellow entry to your .htaccess file.
<IfModule mod_expires.c>
ExpiresActive On
# Images
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# Video
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/mpeg "access plus 1 year"
# CSS, JavaScript
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Others
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
</IfModule>
Add compression to the site resources
Another useful speed improvements is to add compression to your site resources. Modern browsers know how to handle compressed pages, scripts, and other mime types if instruicted by the server, reducing the exchanged data size and thus the speed of the site.
Just add the bellow block in your .htaccess file
# compress text, html, javascript, css, xml:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
Deny weak encryption algorithms to avoid malicious actors that downgrade security to broken or weak ciphers
A very useful took here is Mozilla Cipherscan tool. You can analyse your site and see which ciphers are recommended to be removed. Just run the bellow command and a list of recommendations will be displayed.
./analyze.py -t https://blog.voina.be
As a result my SSL directives from the blog.voina.org.conf looks like:
SSLEngine On
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES256-GCM-SHA384:!DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!ECDHE-RSA-AES256-SHA:!ECDHE-RSA-AES128-SHA:!DHE-RSA-AES256-SHA25
6:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES256-SHA:!DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DE
S:!MD5:!PSK:!RC4:!3DES:!AES256-GCM-SHA384:!AES128-GCM-SHA256:!AES256-SHA256:!AES128-SHA256:!AES256-SHA:!AES128-SHA:!AES256-CCM8:!AES256-CCM:!AES128-CCM8:!AES128-CCM:!CAMELLIA256-SHA256:!CAMELLIA128-SHA256:!CAMELLIA256-SHA:!CAMELLIA128-SHA
:!ECDHE-RSA-CAMELLIA256-SHA384:!DHE-RSA-CAMELLIA256-SHA256:!ECDHE-RSA-CAMELLIA128-SHA256:!DHE-RSA-CAMELLIA128-SHA256:!DHE-RSA-CAMELLIA256-SHA:!DHE-RSA-CAMELLIA128-SHA:!ECDHE-RSA-AES256-GCM-SHA384:!ECDHE-RSA-AES128-GCM-SHA256:!ECDHE-RSA-AE
S256-SHA384:!ECDHE-RSA-AES128-SHA256
SSLProtocol all -SSLv2 -SSLv3
Note that I am very restrictive and several old browser clients are not able to connect to my blog.
Block IPs with suspicious actions
This is one of my favourite fun time. You just have to look at /var/log/security or have some script checking it with regularity. Plenty of IPs trying to root ssh or to upload scripts or scan ports.
A simple script like the bollow will take care of them:
#!/bin/bash
iptables -A INPUT -s $1 -j DROP
iptables -L INPUT -v -n
iptables-save
If you want to go mental you can simply block a whole country like China. No legitimate traffic anyway due to the big China firewall that blocks my blog (yes I checked it there is a site were you can do that) but plenty of malicious traffic ( the thousands of soldiers from China cyber-force need to do something ) blindly directed to any top level domain.
The following is a good tutorial with scripts for iptables. How to block a country using iptables?