An Intro On HTTP Security
Tags: http, security, owasp, csp
Published: 2018-10-22 22:27:44

---
title: An Intro On HTTP Security
published: true
description: Notes on a talk I recently gave on ways to not get hacked
tags: HTTP, Security, OWASP, CSP
cover_image: https://thepracticaldev.s3.amazonaws.com/i/fc8085qhfmw1zgsghajy.jpg
---

By the time you have read this, I will have given a talk at [WordPress Leeds](https://wpleeds.co.uk/)

_the folks who organise the meetup are fantastic, and you should definitely attend if you are ever in the area_

covering some aspects of HTTP Security and how you can make your websites less hackable.

*I chose the click-baity subtitle of "ways to not get hacked"*

It felt a bit of a shame for the slide deck to only see the light of day during that meetup. So I thought I'd share them with the world. Plus the folks who attended could then sit back and watch me being a wally, rather than frantically taking notes

*even if those notes where on the fact that I was a complete wally*

I wrote the slides using revealjs

*see the readme in the [GitHub repo](https://github.com/GaProgMan/Talks/tree/master/HTTP%20Security%20Intro/) for the deck on how to get it up and running*

and should run on any computer with a browser and connection to the web.

### What This Talk Is Not

![What this talk is not](https://thepracticaldev.s3.amazonaws.com/i/7875ap0mdda07h53m1yd.jpg)

This talk is not designed to be too technical. There are a few easy wins for folks who aren't technical at all (some of which are technology agnostic, and some are WordPress specific). We'll start with the easy wins.

### Security = Catchup (Sometimes)


![Security is catchup sometimes](https://thepracticaldev.s3.amazonaws.com/i/dpp24busk8h3h5m0efge.jpg)

Sometimes security is a game of cat & mouse, as more hacks and vulnerabilities are found, reported, and patched out. It's a full time job staying at the forefront of web security. Just as [Troy Hunt](https://twitter.com/troyhunt) or [Scott Helme](https://twitter.com/scott_helme)

A few days before I gave this talk, [a critical vulnerability](https://nvd.nist.gov/vuln/detail/CVE-2018-9206) in a popular jQuery plugin was reported on. It had been "in the wild"

*that's security talk for "we, kinda, knew about it"*

for three years.

There's also this comment from another article of mine on this very site:

{% devcomment 5eop %}

### Plugins

![plugins](https://thepracticaldev.s3.amazonaws.com/i/fta4pbreiwl5h7mzpmo5.jpg)

We developers know that there's always a library for that. Whether it's an npm package, a NuGet package, or just some code laying around on Stack Overflow

*You don't [copy-paste from Stack Overflow without understanding what the code does first](https://stackoverflow.com/questions/35925494/c-preprocessor-concatenation-outside-of-define/35926150#35926150), do you?*

As such, it is really easy to fall into the trap of having hundreds of lines of code which are required to run your website - most of which is either bloated or indecipherable.

If you need to include someone else's code (via a plugin or whatever), make sure that it is small, short, and sticks to the point. It should, as Charles Emmerson-Winchester III says do:

> One thing at a time. Do it very well. And then I move on

### Single Responsibility Principle

![Single Responsibility is the best ibility](https://thepracticaldev.s3.amazonaws.com/i/602xq3fskke0t6ymnpgg.jpg)

This goes hand-in-hand with the [Principle of Least Privilege ](https://en.wikipedia.org/wiki/Principle_of_least_privilege). Basically, if you need to give someone or something access to your application

*or blog, or website, or black ops site*

give them the **LEAST** possible access; just enough to get the work done, and no more.

In the world of blogging:

- Writers should NOT have admin access
- Editors, too
- Similar to admin best practises for computers and security

### Multi-Factor Auth

![](https://thepracticaldev.s3.amazonaws.com/i/k7ad9ak5gu5604j77yz7.jpg)

Multi-Factor authentication is when you need more than one thing in order to log in. Classic single-factor authentication is a username and password combo - it's a single thing that you know.

Other factors can include something that you have (i.e an authentication app), something that you are (i.e. finger print), etc. The more of these that you enable, the more things that a malicious person will need to have in order to break in. But it will make it harder for a proper user to log in.

I use a combination of [Authy](https://authy.com/) and [YubiKeys](https://www.yubico.com/) to provide a second factor for all of my accounts. These devices us a time-based algorithm to create a one time use code which needs to be entered at login.

Because it's time-based, it's *almost* impossible to brute force

*almost; but it's hundreds of times better than not having it*

### How HTTP Works

![How HTTP Works](https://thepracticaldev.s3.amazonaws.com/i/yhdlpotg9xjeezi33md6.jpg)

As a terribly reduced example, let's imagine that I want to load the homepage for the BBC.

- I tell my browser to go to [https://bbc.co.uk/](https://bbc.co.uk/)
- My browser sends an HTTP request to my Internet Service Provider
- My ISP helps to figure out where the server for the BBC is
- It then forwards my browser's request for the website through a series of routers

*I mean a series of tubes, obviously*

- It finally gets to the server running the BBC website
- The server generates the HTML for the homepage, puts it in an HTTP response, sends it back to me
- The HTML takes the reverse of the same route it took to get there, in order to get back to me

At any point, someone can intercept the request and see the contents. You can do the same with the response. Unless it's encrypted using HTTPS, that is.

If it's not encrypted, then anyone in the chain between me and the BBC server can change the details of the request or the response. This is sometimes called a [Man-in-the-Middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack/).

~~Encrypting the message isn't fool-proof, because the same folks between me and the BBC server can get the keys used to encrypt our messages. But they have to be watching the requests from the very beginning, which isn't easy to do.~~

See the comment by Russ:

{% devcomment 6aco %}

I was slightly wrong in what I'd said, as I was conflating two things together. Whilst it's not possible to intercept and decrypt TLS messages as they fly through the web, it is possible to decrypt them after the fact - given enough compute power and time.

### Let's Encrypt

![Let's Encrypt](https://thepracticaldev.s3.amazonaws.com/i/qhdxqhv4au65tt8v8yi8.png)

Regardless of how you feel about the big name Certificate Authorities, they have made some big mistakes recently. Symantech made [a number of big fouls](https://wiki.mozilla.org/CA:Symantec_Issues/) ups which has meant that they have exited the CS business.

Let's Encrypt is a free service which offers TLS

*no one has used SSL since the 90s, but the acronym has stuck*

certificates to anyone. You need to do a little work to get them to auto-renew, but your hosting provider might be able to help with that. I know that [DreamHost](https://dreamhost.com)

_one of the hosting providers that I use_

can help you to set up auto-renewing certificates.

### Sub-Resource Integrity

![SRI in action](https://thepracticaldev.s3.amazonaws.com/i/yrbo3q37gv67inubk9sk.jpg)

Each time that you access a webpage, a bunch of HTML is sent over to your browser. That HTML

_unless the website is all plain text_

will include some links to external resources (things like images, style sheets and JavaScript usually). Before the browser can display the page, it needs to go get these external resources

_"external" here means external to the browser that you have loaded the website on_

If that external resource is JavaScript, then you need to know whether someone has managed to futz with it, either in transit (when on the way to your browser) or at it's origin (where you are downloading it from). That's where Sub-Resource Integrity comes in.

SRI is essentially a hash of the file contents. When you include a script (or style sheet) in your HTML page, you can tell the browser that it should expect that script to have a specific finger-print (in this case a SHA256 hash). If the downloaded script's has doesn't match the SHA 256 hash, then the browser will not attempt to run it.

_think of "hashing" something as taking it's contents and putting it through a mathematical formula. Everything which goes the formula should produce a different answer to everything else_

### Content Security Policy

![Content Security Policy](https://thepracticaldev.s3.amazonaws.com/i/mk7jpjkovuu8l58iuy4q.jpg)

There's an old programmers joke which goes:

> The three hardest things in computer science are naming things and off by one errors

But that was written before CSP was invented.

Essentially, CSP is a white-list of places that a browser is allowed to load content (HTML, scripts, images, style sheets, etc.) from when loading your website. If your website (or something it loads) attempts to load something from a website not on this list, your browser will stop loading the website.

Just read that last sentence again:

> If your website (or something it loads) attempts to load something from a website not on this list, your browser will stop loading the website.

That's exactly right. CSP can break your website. If you don't get it right

_and there's no way that you'll get it right on the first try_

then you'll stop your website (or web application) from working.

This is a server side thing, and isn't for the faint of heart. It also requires knowledge of how your web-server and reverse proxy work. Each web-server handles this differently, so you'll need to look up how to do this yourself (unfortunately), or find a boffin

_"boffin" is an old British slang term which means: "a person with knowledge or a skill considered to be complex or arcane"_

to help you.

An example of a set of CSP rules are:

``` bash
content-security-policy:
    upgrade-insecure-requests;
    default-src 'self';
    connect-src 'self' https://cdn.jsdelivr.net https://api.unsplash.com;
    script-src 'self' https://cdnjs.cloudflare.com https://code.jquery.com;
    img-src 'self' https://pbs.twimg.com https://imagegen.podchaser.com https://*.unsplash.com https://casper.ghost.org https://*.gravatar.com;
    style-src 'self'  https://cdnjs.cloudflare.com/ https://maxcdn.bootstrapcdn.com; 
    frame-src 'self' https://html5-player.libsyn.com/;
    font-src 'self' https://maxcdn.bootstrapcdn.com;
    object-src 'none'
```

This tells the browser that it can only load the following things from the specified places:

- Scripts
  - the origin of the website (self)
  - https://cdn.jsdelivr.net
  - https://api.unsplash.com
- Images:
  - the origin of the website (self)
  - https://pbs.twimg.com (Twitter)
  - https://imagegen.podchaser.com (Podchaser)
  - https://*.unsplash.com (Unsplash)
  - https://casper.ghost.org (Ghost)
  - https://*.gravatar.com (Gravatar)
- etc.

It also says that the browser should `upgrade-insecure-requests` which means that it should attempt to load everything over HTTPS

### Secure Headers

![Secure Headers](https://thepracticaldev.s3.amazonaws.com/i/wkxyo1gxav0zqfxpfabc.jpg)

These are things added at the web-server or reverse proxy level (like CSP), and are designed to make your websites and web applications more secure for the end user.

We already know a little about CSP.

HTST tells the browser to **always** come to our website using HTTPS, and to never try over HTTP.

Content Type is a way of stopping malicious people from telling the browser that the image it has loaded is a piece of JavaScript (for example), by changing it's [MIME Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)

_MIME types are ways of identifying files without having to rely on the file extension_

XSS Protection helps to stop [Cross Site Scripting attacks](https://en.wikipedia.org/wiki/Cross-site_scripting). This one is a little complex, but one example would be to imagine that you have a comments box where users can leave comments. A malicious user could put some JavaScript into that comment box, and that script would be run on the browser when thee comment is loaded. That's JavaScript we didn't write or want to run on our website.

It's a little more complex than that, but that's the basic gist.

### Links

- [Slide Deck](https://github.com/gaprogman/Http-Security-Intro)
- [Me, on Twitter](https://twitter.com/dotnetcoreblog)
- [CVE-2018-9206](https://nvd.nist.gov/vuln/detail/CVE-2018-9206)
- [Extended Validation Certificates are Dead](https://www.troyhunt.com/extended-validation-certificates-are-dead/) by Troy Hunt
- [OWASP Secure Headers Project](https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers)