There are a number of things you can do to make a server more secure whilst protecting your hosted entities and their users. Here are just three of the many things I do on every new server I commission. I hasten to add that these are not necessarily the most effective or at the top of my list - they are just that: 3 things I set on new servers.

Prevent framing

One method of attempting to fool users into interacting with a website is by loading it into an iframe on the attackers page. More formally known as Clickjacking; this technique involves overlaying the iframe with a different user interface.

As you can imagine this makes it possible for the attacker to mask the actions of the user. They think that they are using the attacker supplied interface when in actual fact they are performing actions on the background application in the iframe.

There are a couple of techniques that can be employed to combat this threat and protect your users. At the server level and as javascript in the web pages themselves.

On the server you can set the X-Frame-Options header, which tells the web browser how to treat the page when it is framed. It is possible to set this header to DENY, which blocks all loading of the page via frames. By setting it to SAMEORIGIN you can relax the restrict and only allow framing by pages on the same domain.

On the Apache webserver this directive is set like so (on Debian/Ubuntu servers this is /etc/apache2/apache2.conf):

Header always append X-Frame-Options SAMEORIGIN

Alternatively if you are using nginx then you can implement it in the following way:

add_header X-Frame-Options SAMEORIGIN;

Do not forget of course that Apache configuration changes require an Apache server reload or restart.

Unfortunately this header is only supported on more recent browsers with the following minimum requirements:

  • Firefox 3.6.9
  • Chrome 4.1.249.1042
  • Internet Explorer 8
  • Opera 10.50
  • Safari 4.0

In addition to the two aforementioned settings there is also ALLOW-FROM to whitelist a certain domain.

Header always append X-Frame-Options ALLOW-FROM http://foo.com

There are at least three problems with this particular option though:

  1. It is only (currently) supported in Firefox 18 and above as it is a relatively new addition to the specification in 2012.
  2. For some reason it was not foreseen that someone implementing this directive would want to list a number of domains to be allowed to frame the content so you can only specify one domain.
  3. Why add a hyphen between the words when SAMEORIGIN does not? Maybe there is a technical reason, but from the outside it just creates an inconsistency.

When any of these options are set and an invalid framing occurs Firefox will show a blank page, but Internet Explorer rather more helpfully will display an error for the user.

Now for legacy browsers you will need to drop back to using a JavaScript framebusting code. It goes without saying however that this can be circumvented by a potential attacker through techniques such as double framing and exploiting cross site scripting filters in some browsers.

if (top != self) {
  top.location = self.location;
}

The latest recommendation from The Open Web Application Security Project (OWASP) is to include the following code in the <head> section of your web page:

<style id="antiClickjack">
  body {
    display: none !important;
  }
</style>
<script type="text/javascript">
  if (self === top) {
    var antiClickjack = document.getElementById("antiClickjack");
    antiClickjack.parentNode.removeChild(antiClickjack);
  } else {
    top.location = self.location;
  }
</script>

This works by disabling the whole page using the CSS style at the beginning and then later on in the javascript checking to see that the page is not framed. It then removes the style from the pages HTML thereby revealing the content. If it is framed then it sets itself as the parent page.

It should be noted that if the user has JavaScript turned off or it does not run due to an error then they will not be able to see anything of the page.

HTTP TRACE

Apache responds to debugging requests via the HTTP TRACE method with the exact request that was received. In general this does not appear harmful, but it can be used to find out information about a users request. An attacker will attempt to trick a user into making a TRACE request and then obtain information about session cookies or authentication from the response. The information can then be used to exploit other potential vulnerabilities such as cross site scripting.

It is possible to disable this helpful debug functionality in production by setting the TraceEnable Apache directive in the following fashion:

TraceEnable Off

Do not forget of course that Apache configuration changes require a server restart.

If you do not have access to the main Apache configuration then you can still block TRACE requests using mod_rewrite:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]

You will note the addition of a rule to prevent TRACK requests as well, which is a similar debugging method.

For the nginx users out there; you have no need to worry as from version 0.5.17 all TRACE requests are rejected with a 405 error and it has no concept of a TRACK request. To debug this server you are expected to have access to the logs on disk.

Hide your versions

Another super simple, but often overlooked adjustment to make is to prevent the server from broadcasting too much information about itself. Whilst attackers maybe able to source the information in other ways the harder we make it the more likely potential attackers are to give up and move onto a softer target. It is similar to introducing yourself to someone and giving them specific details about yourself such as “I rarely lock the back window when I pop into town”.

Firstly, let us silence the Apache server a little. Gag it with the following configuration changes:

ServerSignature Off
ServerTokens ProductOnly

nginx servers can be muffled by setting the following directives in the configuration after installing the module:

server_tokens off;

# Install HttpHeadersMoreModule first for this one
more_set_headers 'Server: Nginx';

Secondly, PHP is also being too noisy about its presence. Put a sock in it by editing the core php.ini file (typically /etc/php5/apache2/php.ini on Debian/Ubuntu servers):

expose_php Off

Once again do not forget of course that Apache and PHP configuration changes require an Apache server restart.

Join in the conversation about this article on Hacker News or reddit.

If you liked this post then you might also like my follow up post Improve PHP session security.