Showing posts with label http. Show all posts
Showing posts with label http. Show all posts

Wednesday, 26 April 2017

Going HTTPS with Cloudflare

Having already made my WCG Online project secure (as detailed in a previous post), it's been on my list for a while to do the same with my main website.  But I'd heard good things about Cloudflare and wanted to give them a try.

Well I'm glad I did, it was so easy and straight forward.  Here's how it went...

  1. Go to Cloudflare to sign up
  2. Enter your chosen email address and a new password
  3. Add your website domain, so for me this was www.rik.onl
  4. Click "Scan for DNS" and you'll get a little video to watch whilst it's processing
  5. Click "Continue" once it's down
  6. You'll then see a list of your DNS records, and which ones Cloudflare are planning to redirect.  Make sure this list is correct! 
  7. Click "Continue" once you're happy
  8. You then need to choose a plan - I was just testing so I went with Free website, but this will depend on what your website is used for and what level of service you require
  9. Click "Continue" when you've selected
  10. You'll then see a couple of new name servers - you'll need to go to your current web hosting platform and change the name servers over to the Cloudflare ones you've been given.
  11. Click "Continue" once you've done this
That's it, you're done.  Give it some time for everything to update, and you'll have an HTTPS version of your site ready to go!

You'll see a number of different sections within Cloudflare that are available to configure.


Overview

That's where you should arrive by default.  This gives you a summary of the status of your account.

Analytics

Initially there won't be anything in here, but over time it will start to show the traffic that Cloudflare has handled and how much of your own web hosting bandwidth has been saved by their caching.

DNS

This shows you the DNS records again, and the nameservers, and from here you can make changes if needed, depending on your plan level.

Crypto

This is where the HTTPS magic happens!  By default it is set to "Full", which is good, and will give you the nice green "Secure" message in the address bar (on Chrome, at least).  You can also enable HTTP Strict Transport Security (HSTS) and Automatic HTTPS Rewrites, both of which I would definitely recommend to help ensure users find and continue to use the HTTPS version of your website.  For HSTS you get some sub-options, including the Maximum Age (max-age) which they recommend 6 months, which sounds about right to me.  You can also apply the setting to subdomains, preload (if you wish, but I haven't) and and the "no-sniff" header (X-Content-Type-Options: nosniff), which I would recommend.

Firewall

This section can be used to try and filter out "bad" traffic.  You can do things like rate limit per IP address, and change the challenge page settings, which is where a user gets sent if they are determined as "bad", so they get a chance to prove themselves to actually be "good".  I left all of this as default.

Speed

Here you get the option to do things to speed up your website, such as minifying (I selected Javascript, CSS and HTML).  A lot of these options require a paid plan, but it's worth having a look and seeing what works for you.

Caching

You can set a few different cache options in here, but there are also a couple of really important buttons in here.
  1. Development Mode - if you are in the process of making and testing changes to your website, you're going to want to enable this, so that the cache is bypassed.
  2. Purge Cache - once you've made the change to your website, you're going to want to then purge the Cloudflare cache, to ensure the changes come through, before you disable the Development Mode.
Page Rules

This allows you to change certain settings for different pages, so you can make exceptions.  I've not set any of these, but I think this could prove really useful moving forwards!

Network

Here you can make certain network decisions, such as whether web sockets should be able to link to your original server, and IPv4 vs. IPv6, etc..

Traffic

Here you can control and manage your traffic, as well as seeing any firewall events that have been triggered.

Customize

This allows you to change certain error messages (such as HTTP 429 - Too Many Requests), but none of the options here are available on the free plan.

Apps

You can enable extra functionality here, including...
  • A Better Browser - warns users if their browser is old
  • Google Analytics
  • Google Webmaster Tools
  • Infolinks - monetize your site with ads
  • New Relic Browser - provides insight into the experience your site users are having
  • OpenDyslexic - overrides site fonts with OpenDyslexic
  • Trumpet - lets you put a dismissable message at the top of your site
  • VigLink - helps you earn money from your site's outbound links automatically
Scrape Shield

Cloudflare can scrape your content in order to make certain changes, to help protect you.  For example, it can obfuscate email address, and prevent hotlinking.  


And that's it, all done!  You're ready to go, and they've done all the hard work for you.

There's also an API for all of these settings, so you can make changes automatically if you want to.  However, I've not looked at this side of things yet. 



So now I can run my newly secure website through securityheaders.io and see how I'm doing.  And I get an A!

The only reason that I don't get an A+ is that I'm missing is HTTP Public Key Pinning (HPKP).  This is generally a good thing to do, but can cause problems when using Cloudflare as you're never sure when they're going to update the certificates.  They've suggested waiting until they implement this natively, so I'm going to go with that advice.  To be honest, I don't have a login page or any ecommerce, so no one's going to gain anything by doing a rather complicated attack on my certificates, so there's no risk here for me.

From my experience, I can certainly recommend Cloudflare to anyone, especially if they're looking to make their website secure.

    Wednesday, 8 March 2017

    Response headers - adding Content-Security-Policy

    I recently wrote an update as I continue to work on my response headers, in which I said that I was working on adding content-security-policy, with the help of Scott Helme, who has written a great blog post on this.  He has also created an excellent site called report-uri.io which has a number of tools, including one to help you build your CSP.

    As a refresher, this is used to control what access different content on your site has.  For example, you can control what javascript and stylesheets can be included, inline or from different domains, etc.  This can help to limit the attack surface for things like cross-site scripting attacks.

    So there are lots of parts, but here's how I went about it...


    Default Source (default-src)

    This is the default setting, so to be really secure, I went with "none".  This essentially means don't allow any content at all.  It is then overridden for each content type explicitly.

    Script Source (script-src)

    This is applied to all the javascript files and script tags on the page.  I started with "self", as I wanted everything from my site ("www.rik.onl") to work.  Then I looked through my code and added in the CDN domains that I was using to load the libraries I'm using... "https://code.jquery.com https://maxcdn.bootstrapcdn.com https://cdnjs.cloudflare.com" (space delimited).

    Style Source (style-src)

    This is applied to all stylesheet files and style tags on the page.  Again, I started with "self", and then needed to add "https://maxcdn.bootstrapcdn.com".

    Image Source (image-src)

    You guessed it, this is applied to all the images on the page.  This time I needed "self" and also "https://www.gravatar.com".

    Font Source (font-src)

    I don't load any fonts from my own site here, so I just need to add "https://maxcdn.bootstrapcdn.com".

    Connect Source (connect-src)

    This is applied to things like AJAX requests, web sockets and event sources.  I don't have any of these currently, so I've left this out, which means it will default to the Default Source, which is "none".  I could also explicitly set this to "none".

    Media Source (media-src)

    This is applied to audio and video tags.  I don't have any, so I've left this out.

    Object Source (object-src)

    This is applied to object, applet and embed tags.  I don't have any, so I've left this out.

    Child Source (child-src) and Frame Source (frame-src - deprecated)

    These are applied to frame and iframe tags.  I don't have any, so I've left these both out.  You should use Child Source instead of Frame Source though, as the later is deprecated.

    Worked Source (worker-src)

    This is applied to things like service workers, which I don't have, so I've left this out.

    Frame Ancesters (frame-ancesters)

    This is applied to frame and iframe tags, stating which parents may embed a page.  It replaces the "X-Frame-Options" header, but again, I've left it out.

    Form Action (form-action)

    This is applied to form tags, stating which location they can post to.  I don't have a form, so I've left it out.  In case you've forgotten, this means it defaults to the "Default Source", which is "none".

    Upgrade Insecure Requests (upgrade-insecure-requests) and Block All Mixed Content (block-all-mixed-content)

    My site currently runs on HTTP (non-secure), so I've left these out, but I'll definitely be looking to add them in moving forwards.

    Reflected Cross-Site Scripting (reflected-xss)

    Reflected cross-site scripting is bad!  I've set this to "block".  You can set this to "filter", which means the browser will try to cleanse the script, but I think it's safer to block it completely, if XSS is detected.

    Manifest Source (manifest-src)

    This is applied to manifest files, so I've set this to "self", as I have a manifest for icons.

    Plugin Types (plugin-type)

    This tells the browser which plugins they can invoke, such as the Adobe PDF Viewer.  As I don't think my site needs any, I've left this out.

    Referrer (referrer)

    This directive tells the browser when (and when not) to send the referer [sic] header when fetching content from another domain.  In my last blog post I decided to set the "Referrer-Policy" header to be "no-referrer-when-downgrade", and so I've set this directive to match that.

    Report URI (report-uri)

    This is where the browser will post violation reports to, so you can keep an eye on what content is breaking.  This could be because you've mis-configured your policy, or it could be because someone is trying to hack your site!  Scott Helme's excellent site report-uri.io will allow you to configure a URI which you can set here.


    So now it's ready for testing!  

    To test, instead of setting "Content-Security-Policy", set "Content-Security-Policy-Report-Only".  This means that the browser will report all of the violations, but will continue to load the content anyway, which is perfect until you're sure it's right.  

    This is what I came up with...

    default-src 'none'; script-src 'self' https://code.jquery.com https://maxcdn.bootstrapcdn.com https://cdnjs.cloudflare.com; style-src 'self' https://maxcdn.bootstrapcdn.com; img-src 'self' https://www.gravatar.com; font-src https://maxcdn.bootstrapcdn.com; upgrade-insecure-requests; block-all-mixed-content; reflected-xss block; manifest-src 'self'; referrer no-referrer-when-downgrade; report-uri https://rik.report-uri.io/r/default/csp/reportOnly;

    I then reloaded my site, checked the console, and saw a number of violations!

    This is because I'd forgotten a couple of included scripts that are loaded by Google Analytics.  In fact, they also use an inline script tag, but I really don't want to add "unsafe-inline" to the Script Source, otherwise all inline scripts could be run.  

    Luckily you can fix inline script and style tags that you want to allow by calculating a SHA-256 hash of the contents and including this in the Script Source.  And Scott's got a hash generator tool as well, so that's easy.

    Having fixed these problems, and reloading my site with no violations reported, I'm now ready to start enforcing.  This means that I need to set the "Content-Security-Policy" header, and if you're using report-uri.io then you need to update your Report URI directive as well.

    Note that if you want to support IE11, you also need to set "X-Content-Security-Policy" to the same value.  It's not supported in older versions of IE at all.

    Now that I've added these extra headers, you can check out my live report.  Last I checked, I got an A+ 😃

    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!