Showing posts with label htaccess. Show all posts
Showing posts with label htaccess. Show all posts

Friday, 24 February 2017

Response headers

One thing that you need to decide when creating a site is what response headers to send when someone requests your page.  There are also a couple of different ways of sending them.  

Using .htaccess

  <IfModule mod_headers.c>
    Header set Connection keep-alive
  </IfModule>

Using PHP code

  header("Connection: keep-alive");

So what headers am I setting on my website and why?

1) X-Frame-Options: deny

This is the best way to guard against Clickjacking attacks, but telling the browser that it should never allow the site to be run within an iframe or frameset, and therefore cannot be embedding within another site.

2) X-Content-Type-Options: nosniff

This tells the browser not to try and guess the content type of a response and to always use the one being declared by the server. It reduces exposure to drive-by downloads and the risks of user uploaded content that, with clever naming, could be treated as a different content-type, like an executable.

3) X-Permitted-Cross-Domain-Policies: none

When clients request content hosted on a particular source domain and that content makes requests directed towards a domain other than its own, the remote domain needs to host a cross-domain policy file that grants access to the source domain in order to allow the client to continue the transaction.  I don't have any content like this, so I've set it to "none".

4) X-XSS-Protection: 1; mode=block

This tells the browser to protect against Cross-Site Scripting (XSS) attacks, and to block any attempts instead of trying to sanitise them.  This won't stop all XSS attacks, but it's a good baseline.

Now, if you check out the headers in the Network tab of your browser's Developer Tools, you'll see there are also some extras...



There are two types of extras...

Automatically created by the server - these are useful!
  • Cache-control
  • Content-Encoding
  • Content-Length
  • Content-Type
  • Date
  • Expires
  • Vary
Automatically added by my web host - these are not useful!
  • Server
  • X-Hostname
  • X-Powered-By
These reveal information to an attacker which they may be able to use to assist them, which is not good.  If I figure out how to remove them, I'll let you know in a future post.

Thursday, 23 February 2017

Making WCG Online secure

I'm going to talk about one of my projects - WCG Online.  This project has been online for a couple of years, and it's designed to give you, a valued member of the World Community Grid community, access to some more detailed statistics, as well as some lovely pretty graphs.  I'm hoping to add more functionality soon as well, but for now, that's the gig.

As the internet is slowly but surely turning secure (HTTPS instead of HTTP - check your address bar now!), and this site takes your username and verification code to get your stats - not the end of the world as it's certainly not your password and can only be used to view information, but still, best to be secure.

Having purchased (unfortunately my shared hosting package doesn't support Let's Encryptand installed my certificate, it was possible to access the site via HTTPS - excellent start!  But what about people who have already bookmarked the site as HTTP, or they happened to search for "wcg online" on Google and clicked the first result, in which case they would still get the HTTP page.

Having looked around a bit, I decided the best thing to do would be to change my .htaccess file and create a rewrite condition, like this...

  <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} !=on 
    RewriteRule ^.*$ https://www.wcg.onl%{REQUEST_URI} [R=301,L]   
  </IfModule>

So this is checking if the "HTTPS" variable is not "on" (as in, it's off, therefore HTTP) and then the rule changes the base URL to be HTTPS with the original request URI (the page and query string).  The "R=301" returns a 301 HTTP status to the browser, which caches a permanent redirect, so the browser should always use HTTPS moving forwards.

Unfortunately this didn't work for me (I later discovered my shared hosting package uses the variable "ENV:HTTPS" instead!), and nor did a number of other suggested rewrite rules, such as checking port 80, which is typically used for HTTP.  I ended up adding the following PHP code into the main page of my site...

  if($_SERVER["HTTPS"]!=="on") {
    header("Location: https://www.wcg.onl",true,301);
    exit;
  }

This essentially does the same thing, but it's done within the PHP code, instead of by the webserver layer.  Again, this uses a 301 HTTP status to tell the browser to always use HTTPS.

To back this up, I then added the following header...

  Strict-Transport-Security: max-age=16070400; includeSubDomains

This uses HTTP Strict Transport Security (HSTS), which if you're not aware, essentially tells the browser that it should always use HTTPS for this site.  This means that the browser will now use a 307 Internal Redirect, which is much much quicker as it happens internally instead of hitting the server.

The unfortunate side effect of this is that the site will forget you, when you first switch from HTTP to HTTPS.  This is because the local storage that it uses to store this information, as no information is stored on the server, cannot be access cross-protocol.  I think this is a small price to pay for security though!