├── .dccache ├── manuscript ├── backmatter.md ├── frontmatter.md ├── resources │ ├── Figure3-1Next1.png │ ├── Figure3-2Next2.png │ ├── Figure1-3Excercise1.png │ ├── Figure1-4Exercise1.png │ ├── Figure1-5Exercise2.png │ ├── Figure1-6Referer1.png │ ├── Figure2-1StateOfHTTP1.png │ ├── Figure2-1StateOfHTTP2.png │ ├── Figure2-2WebPageTest1.png │ ├── Figure2-2WebPageTest2.png │ ├── Figure2-2WebPageTest3.png │ ├── Figure2-3Lighthouse1.png │ ├── Figure2-3Lighthouse2.png │ ├── Figure2-3Lighthouse3.png │ ├── Figure2-4CheckMyHeaders1.png │ ├── Figure1-1-VisualizingHTTPSMITMAttack.png │ └── Figure1-2-ChromeinternalHSTSconfiguration.png ├── Book.txt ├── about-the-book.md ├── about-the-author.md ├── Chapter-01-Introduction.md ├── Chapter-04-Whats next.md ├── Chapter-03-Testing for Security Headers.md └── Chapter-02-HTTP Security Headers.md ├── CONTRIBUTORS.md └── README.md /.dccache: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /manuscript/backmatter.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /manuscript/frontmatter.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /manuscript/resources/Figure3-1Next1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure3-1Next1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure3-2Next2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure3-2Next2.png -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | An alphabetical listing of people who have contributed to this book: 4 | 5 | * [Liran Tal](https://github.com/lirantal/) -------------------------------------------------------------------------------- /manuscript/resources/Figure1-3Excercise1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-3Excercise1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure1-4Exercise1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-4Exercise1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure1-5Exercise2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-5Exercise2.png -------------------------------------------------------------------------------- /manuscript/resources/Figure1-6Referer1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-6Referer1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-1StateOfHTTP1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-1StateOfHTTP1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-1StateOfHTTP2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-1StateOfHTTP2.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-2WebPageTest1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-2WebPageTest1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-2WebPageTest2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-2WebPageTest2.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-2WebPageTest3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-2WebPageTest3.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-3Lighthouse1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-3Lighthouse1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-3Lighthouse2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-3Lighthouse2.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-3Lighthouse3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-3Lighthouse3.png -------------------------------------------------------------------------------- /manuscript/resources/Figure2-4CheckMyHeaders1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure2-4CheckMyHeaders1.png -------------------------------------------------------------------------------- /manuscript/resources/Figure1-1-VisualizingHTTPSMITMAttack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-1-VisualizingHTTPSMITMAttack.png -------------------------------------------------------------------------------- /manuscript/resources/Figure1-2-ChromeinternalHSTSconfiguration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirantal/learning-http-security-headers-book/HEAD/manuscript/resources/Figure1-2-ChromeinternalHSTSconfiguration.png -------------------------------------------------------------------------------- /manuscript/Book.txt: -------------------------------------------------------------------------------- 1 | frontmatter: 2 | 3 | frontmatter.md 4 | about-the-author.md 5 | about-the-book.md 6 | 7 | mainmatter: 8 | 9 | Chapter-01-Introduction.md 10 | Chapter-02-HTTP Security Headers.md 11 | Chapter-03-Testing for Security Headers.md 12 | Chapter-04-Whats next.md 13 | 14 | backmatter: 15 | 16 | backmatter.md -------------------------------------------------------------------------------- /manuscript/about-the-book.md: -------------------------------------------------------------------------------- 1 | # About The Book 2 | 3 | This book is a follow-up on Liran Tal's [Essential Node.js Security for Express web applications](https://leanpub.com/essential-nodejs-security/) and teaches you hands-on practical use of HTTP security headers as browser security controls to help secure web applications. 4 | 5 | For each HTTP security header that can enhance your web application security, you'll learn what is the overall risk of not implementing it, and what does a proposed solution help with. Finally, you'll learn how to implement and configure the security header with Helmet, a popular and well-maintained Node.js package on npm. 6 | 7 | This book includes 18 Lessons, 8 Quizzes, 30 Code Snippets, and 19 Illustrations to help you level up on your HTTP security headers skills, and includes: 8 | 9 | - Secure web applications using HTTP security headers 10 | - Understand Content Security Policy 11 | - Setup Node.js web applications securely 12 | - Learn how to test and monitor for security headers and vulnerable JavaScript libraries 13 | - Roadmap for future web controls 14 | 15 | ## Requirements 16 | 17 | The source code, and examples through-out this book are based on the [Long Term Support version of Node.js](https://nodejs.org/en/), which at the current edition of the book is Node.js 14. 18 | 19 | ## Source Code 20 | 21 | All the source code examples, and many more variations of them can be found in their complete setup and form in the following GitHub repository inside the _code/_ directory [https://github.com/lirantal/learning-http-security-headers-book](https://github.com/lirantal/learning-http-security-headers-book). 22 | 23 | Feedback and comments are highly appreciated and welcome. If you find any issues, improvements, or room for updates please open a GitHub issue, submit a pull request, or contact the author directly via email (liran.tal@gmail.com), or Twitter (https://twitter.com/liran_tal). -------------------------------------------------------------------------------- /manuscript/about-the-author.md: -------------------------------------------------------------------------------- 1 | # About The Author 2 | 3 | ## Liran Tal 4 | 5 | Liran Tal is a software developer, and a GitHub Star, world-recognized for his activism in open source communities and advancing web and Node.js security. He engages in security research through his work in the OpenJS Foundation and the Node.js ecosystem security working group, and further promotes open source supply chain security as an OWASP project lead. Liran is also a published author of Essential Node.js Security and O'Reilly's Serverless Security. At Snyk, he is leading the developer advocacy team and on a mission to empower developers with better dev-first security. 6 | 7 | At [Snyk](https://snyk.io), he leads the Developer Advocacy team where he engages developers about open source security in various ways, from engineering tools, to education and awareness. Liran also co-authored [O'Reilly's Serverless Security](https://www.oreilly.com/library/view/serverless-security/9781492082538/) with Guy Podjarny, Snyk's co-founder, president and long-time security professional. 8 | 9 | Liran is a seasoned international speaker and greatly enjoys building and engaging communities. He is an ambassador for Romania's [JSHeroes](https://jsheroes.io), and the [DevSecCon](https://www.devseccon.com/) community, among others. 10 | 11 | Previously, Liran held roles as an Engineering Manager for Hewlett Packard Enterprise and Nielsen Marketing Cloud, where he played a key technical role in system architecture and shaped the technology strategy in stacks including Angular, React, and Node.js. 12 | 13 | Liran graduated cum laude in his Bachelor of Business and Information Systems Analysis studies and enjoys spending his time with his beloved wife Tal, and his magical son Ori. Amongst other things, his hobbies include playing the guitar, hacking all things Linux, and continuously experimenting and contributing to open source, and web development projects. 14 | 15 | --- 16 | 17 | You can follow and engage with Liran at https://twitter.com/liran_tal -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Web Security: Learning HTTP Security Headers 2 | 3 | ![https://img.shields.io/badge/lessons-18-blue](https://img.shields.io/badge/lessons-18-blue) 4 | ![https://img.shields.io/badge/quizzes-8-green](https://img.shields.io/badge/quizzes-8-green) 5 | ![https://img.shields.io/badge/code%20samples-30-yellow](https://img.shields.io/badge/code%20samples-30-yellow) 6 | ![https://img.shields.io/badge/illustrations-19-orange](https://img.shields.io/badge/illustrations-19-orange) 7 | 8 | Authored by Liran Tal 9 | 10 | ![GitHub followers](https://img.shields.io/github/followers/lirantal?style=social) 11 | 12 | ![Twitter Follow](https://img.shields.io/twitter/follow/liran_tal?style=social) 13 | 14 | 15 | [![Web Security: Learning HTTP Security Headers](https://d2sofvawe08yqg.cloudfront.net/web-security-learning-http-security-headers/s_hero?1673559565)](https://leanpub.com/web-security-learning-http-security-headers) 16 | 17 | --- 18 | 19 | This book is a follow-up on Liran Tal's [Essential Node.js Security for Express web applications](https://leanpub.com/essential-nodejs-security) and teaches you hands-on practical use of HTTP security headers as browser security controls to help secure web applications. 20 | 21 | For each HTTP security header that can enhance your web application security, you'll learn what is the overall risk of not implementing it, and what does a proposed solution help with. Finally, you'll learn how to implement and configure the security header with Helmet, a popular and well-maintained Node.js package on npm. 22 | 23 | I made this book available and open source on GitHub to spread the knowledge, but you may also get a PDF formatted copy of it via Leanpub here: [Web Security: Learning HTTP Security Headers](https://leanpub.com/web-security-learning-http-security-headers) 24 | 25 | 26 | ## In the book 27 | 28 | 18 Lessons, 8 Quizzes, 30 Code Snippets, and 19 Illustrations to help you learn. 29 | 30 | Takeaway Skills: 31 | 32 | * Secure web applications using HTTP security headers 33 | * Understand Content Security Policy 34 | * Setup Node.js web applications securely 35 | * Learn how to test and monitor for security headers and vulnerable JavaScript libraries 36 | * Roadmap for future web controls 37 | 38 | ## Table of Contents 39 | 40 | - [Frontmatter](./manuscript/frontmatter.md) 41 | - [About the author](./manuscript/about-the-author.md) 42 | - [About the book](./manuscript/about-the-book.md) 43 | - [Chapter 1: Introduction](./manuscript/Chapter-01-Introduction.md) 44 | - [Chapter 2: HTTP Security Headers](./manuscript/Chapter-02-HTTP%20Security%20Headers.md) 45 | - [Chapter 3: Testing for Security Headers](./manuscript/Chapter-03-Testing%20for%20Security%20Headers.md) 46 | - [Chapter 4: What's next](./manuscript/Chapter-04-Whats%20next.md) 47 | 48 | 49 | ## Testimonials 50 | 51 | ![Michael Azimov](https://s3.amazonaws.com/testimonials.leanpub.com/avatars/1142/small/michael-az.jpeg?1632147545) 52 | 53 | Michael Azimov 54 | SOFTWARE DEVELOPER FUNDBOX 55 | > I started reading the book few days ago and I am half way in it, and I must say that although I kinda knew that I should use all these HTTP headers, your book really made me understand why I should use them and what could happen if I dont, and most importantly- if the browsers yells at you, dont just give up and remove the headers 😆 56 | 57 | ![Luke Rasmus](https://s3.amazonaws.com/testimonials.leanpub.com/avatars/1144/small/luke-r.jpeg?1632474709) 58 | 59 | Luke Rasmus 60 | PROGRAMMER/ANALYST 61 | > Absolutely awesome - really. This was targeted at a perfect level for me, as someone who had exposure to these topics, had done some fiddling with helmet previously in node, but this was a great succinct guide to quickly and effectively teach "what" and "why". 62 | 63 | ![Sumit Kumar](https://s3.amazonaws.com/testimonials.leanpub.com/avatars/1145/small/sumit-k.jpeg?1632475832) 64 | 65 | Sumit Kumar 66 | FRONT END ENGINEER AND DESIGNER 67 | > To the point content. Short book - this one is just for me as I like books that are short. I like the interesting facts about technology terms mid-sections. The code examples are good. I like the educational approach of Risk→Solution→Implementation. I like the use of GitHub to serve the example source code. Some topics I found to be complicated, like HTTP Strict Transport Security. 68 | 69 | ## Code Samples 70 | 71 | TBD 72 | 73 | # Author 74 | 75 | > Liran Tal is a software developer, and a GitHub Star, world-recognized for his activism in open source communities and advancing web and Node.js security. He engages in security research through his work in the OpenJS Foundation and the Node.js ecosystem security working group, and further promotes open source supply chain security as an OWASP project lead. Liran is also a published author of Essential Node.js Security and O'Reilly's Serverless Security. At Snyk, he is leading the developer advocacy team and on a mission to empower developers with better dev-first security. 76 | 77 | Liran Tal 78 | 79 | # Contributing 80 | 81 | Corrections and improvements are welcome. 82 | Please fork the repository and submit a merge request. 83 | 84 | When you make a pull request, make sure to add your name to the list of contributors in [CONTRIBUTORS.md](CONTRIBUTORS.md). 85 | 86 | # License 87 | 88 | The book is licensed under CC's BY-NC-ND version 4. 89 | 90 | Creative Commons License 91 | -------------------------------------------------------------------------------- /manuscript/Chapter-01-Introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## Requirements 4 | 5 | If you have a development environment set with Node.js, git, npm, and working Internet connectivity, you're all set to get started! 6 | 7 | Some exercises require work with a valid HTTPS-enabled website, for which we defer to Heroku as the web hosting platform due to its ease of use and supporting simultaneously both HTTP and HTTPS web hosting. 8 | 9 | ### Web knowledge prerequisites 10 | 11 | It is expected that you have basic knowledge of HTTP, such as the meaning of HTTP headers, an HTTP request, and response, and general knowledge of how the web works in terms of the interactions between a web server and a web client (the browser). 12 | 13 | It is also expected that you have Chrome installed, but not mandatory. This book refers to Chrome's DevTools, and includes screenshots using the Chrome browser. If you are using any other browser and can make the parallels yourself, you should be fine moving forward with the book. 14 | 15 | ### A JavaScript and Node.js development environment 16 | 17 | This book uses the Express web application framework for Node.js to create web applications and set headers using open source modules from the npm ecosystem. 18 | 19 | It is expected that you have a working development environment with a supported Node.js version (LTS), along with the `npm` command-line utility. 20 | 21 | You'll also need `git` to clone example repositories used along with the exercises if you wish to practice locally. 22 | 23 | ### Heroku hosting 24 | 25 | While you are free to deploy the Node.js web application provided in the code references to any web hosting you'd like, such as [Vercel](https://vercel.com), or [Netlify](https://www.netlify.com) - the exercises explain how to use a free Heroku account to deploy. 26 | 27 | ## Headers as browser security controls 28 | 29 | What are HTTP security headers? How can they be useful to secure web applications and specially used as low-hanging fruits, which are easy to implement? At the same time, they may break a web application if not applied correctly. 30 | 31 | ### Intro 32 | 33 | Developing web applications means that our application depends on communication protocols that already have a set of standards defined and implemented for how to transfer data and how to manage it in a secure manner. 34 | 35 | Browsers utilize headers sent over HTTP (secure HTTP connections mostly) to enforce and confirm such communication standards as well as security policies. Making use of these HTTP headers to increase security for the code running on the browser client-side is a quick and efficient method to mitigate security vulnerabilities and add defense in depth. 36 | 37 | ### Security headers and Node.js 38 | 39 | In this book, we will introduce browser security controls by implementing HTTP headers for increased security. 40 | 41 | We'll learn about Helmet as a library that can be easily added to any Express project and configure it to provide additional security for Node.js web applications. 42 | 43 | The HTTP security headers that we will review are: 44 | 45 | - `Strict-Transport-Security`: HTTP Strict Transport Security, also known as HSTS, for short. Enforces a secure communication channel to the web server. 46 | - `X-Frame-Options`: X Frame Options header defines the policies of rendering a web page as an HTML frame. 47 | - `Content-Security-Policy`: Content Security Policy, or CSP for short, defines a wide range of security policies for web browsers. 48 | - `X-XSS-Protection`: The Cross-site Scripting protection header instructs the brower to set specific XSS-mitigating policies. 49 | - `X-Content-Type-Options`: The X Content Type Options is a browser-specific header to instruct the browser to apply strict settings to the `Content-Type` value of the response. 50 | 51 | ### Security headers caveats 52 | 53 | Utilizing security headers can be a great strategy to help prevent security vulnerabilities, but a common mistake is to rely solely on them to mitigate such issues. This is because responding to a request with a security header depends on the browser to actually support, implement, and adhere to the specification to enforce it. You may consult the [Strict Transport Security browser compatibility matrix](https://caniuse.com/#feat=stricttransportsecurity) to verify if the browsers used for your web application are supported. 54 | 55 | As such, security headers should be used as a [defense in depth]() security mechanism that helps in adding a security control, but they shouldn't be the only security control to defend against vulnerabilities like Cross-site Scripting. 56 | 57 | I> Defense in Depth 58 | I> 59 | I> A defense in depth is a security concept in which multiple layers of security controls are placed in order to create a better security posture. 60 | 61 | ## Helmet - a Node.js package to set HTTP security headers 62 | 63 | HTTP security headers are a generic tool that can be employed by any technology at the HTTP Protocol Layer, such as load balancers, an API gateway, reverse proxies, or web application frameworks. 64 | 65 | [Helmet](https://helmetjs.github.io) is an open source project which comprises a collection of HTTP middleware functions that configure HTTP headers by setting the HTTP response object accordingly. 66 | 67 | If you're building Node.js web applications with the help of [Express](http://expressjs.com), then Helmet is the go-to npm package to use and all source code examples in the book will follow its usage. If you're using other frameworks, such as Fastify, then consult the source-code example in the follow sub-sections. 68 | 69 | Helmet wrappers for other Node.js web frameworks are available as follows: 70 | 71 | - For Koa refer to the [koa-helmet](https://github.com/venables/koa-helmet) package. 72 | - For Hapi refer to [blankie](https://github.com/nlf/blankie) package. 73 | 74 | ### Helmet and Express 75 | 76 | If you're using an Express web application setup, begin by installing the Helmet module: 77 | 78 | ```bash 79 | npm install --save helmet 80 | ``` 81 | 82 | Then, continue to instantiate an Express application object, and set an application middleware using Helmet. Specifically, in this example, we're setting the X-Frame-Options using Helmet's built-in `frameguard` method: 83 | 84 | ```js 85 | const express = require("express"); 86 | const helmet = require("helmet"); 87 | 88 | const app = express(); 89 | 90 | app.use( 91 | helmet.frameguard({ 92 | action: "sameorigin", 93 | }) 94 | ); 95 | ``` 96 | 97 | ### Helmet and Fastify 98 | 99 | If you're using the [Fastify](https://github.com/fastify/fastify) web application framework, begin by installing the Helmet wrapper module [fastify-helmet](https://github.com/fastify/fastify-helmet): 100 | 101 | ```bash 102 | npm install --save fastify-helmet 103 | ``` 104 | 105 | Then, in a Fastify web application, register the `fastify-helmet` plugin and provide it a configuration object that includes any of the Helmet-supported security headers: 106 | 107 | ```js 108 | const fastify = require("fastify")(); 109 | const helmet = require("fastify-helmet"); 110 | 111 | fastify.register(helmet, { 112 | contentSecurityPolicy: { 113 | directives: { 114 | defaultSrc: ["'self'"], 115 | }, 116 | }, 117 | }); 118 | 119 | fastify.listen(3000, (err) => { 120 | if (err) throw err; 121 | }); 122 | ``` 123 | 124 | By registering the `fastify-helmet` plugin without any configuration, the following default security headers and their values will be set: 125 | 126 | ```json 127 | { 128 | "x-dns-prefetch-control": "off", 129 | "x-frame-options": "SAMEORIGIN", 130 | "x-download-options": "noopen", 131 | "x-content-type-options": "nosniff", 132 | "x-xss-protection": "0" 133 | } 134 | ``` 135 | -------------------------------------------------------------------------------- /manuscript/Chapter-04-Whats next.md: -------------------------------------------------------------------------------- 1 | # What's next? 2 | 3 | ## Establish a CSP and Security Headers standard 4 | 5 | Adopt new browser and HTTP security standards and set a plan to migrate from old HTTP headers. 6 | 7 | ### X-Frame-Options 8 | 9 | We previously reviewed the benefits of using the `X-Frame-Options` as a response HTTP header in helping address click-jacking security vulnerabilities in web applications. That said, practices evolve and browsers rapidly adopt new standards and mechanisms. For example, the `ALLOW-FROM` value for the X Frame Options header has been deprecated and is discouraged from being used because modern browser versions don't support it anymore. 10 | 11 | As a migration path, the Content Security Policy standards create a way to adapt to such new standards. One of which is, CSP's `frame-ancestors` directive. For example, setting its value to `'none'` should be compatible with `X-Frame-Options` setting of `DENY` value. A more complete example of the Content Security Policy in action for click-jacking security controls is: 12 | 13 | ``` 14 | Content-Security-Policy: frame-ancestors 'none'; 15 | ``` 16 | 17 | The above CSP will disallow any URLs of embeddable content in `iframe`, `object`, and other HTML elements which are part of the `frame-ancestors` policy. 18 | 19 | Do note however, that older browsers may not respect Content-Security-Policy and its directives and as such, you may actually cause a degraded security status. To avoid such a problem, consult your supported browser matrix requirements, employ both old and new headers to ensure all bases are covered, until possible to deprecate older security controls that are no longer valid. 20 | 21 | ### X-XSS-Protection 22 | 23 | Similar to the case with the `X-Frame-Options` HTTP header, the `X-XSS-Protection` header is considered deprecated completely and should mandate that you establish and roll out a Content Security Policy HTTP header instead. 24 | 25 | It's still useful to keep as a header if you are targeting older browsers, but otherwise, note that Chrome and Edge removed their XSS auditor, and Firefox isn't planning on implementing support for X-XSS-Protection. 26 | 27 | Following is the [browser compatibility matrix for the header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection) as listed on MDN: 28 | 29 | ![Figure 3-1: Partial screenshot of the MDN X-XSS-Protection header page (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection)](Figure3-1Next1.png) 30 | 31 | ### Summary 32 | 33 | Security controls will regularly need fine-tuning and keeping up to date as newer and modern technologies evolve around them. This isn't to say that the two security headers we studied and reviewed here are useless. On the contrary. We need to understand in which situations they are still relevant and establish a migration path to newer standards that will eventually replace them. 34 | 35 | ## Monitor your web application 36 | 37 | We learned how to increase security using web controls such as HTTP headers, but to further ensure that they are kept in check we need to monitor them. 38 | 39 | We learned how to increase security using web controls such as HTTP headers, but how do we ensure that we're always up to date with security controls? How do we ensure there isn't a regression next week where headers are removed from an HTTP response? The problem can get a lot harder even if you're working in a rich microservices environment, and needing to account for more than a few services. 40 | 41 | ### Monitoring and Shifting-left 42 | 43 | Shift-Left is a concept in which we refer to moving activities to be as early as possible in the software development lifecycle. 44 | 45 | We would ideally want to shift left as much of the monitoring activities as possible, so we can ensure that problems are detected earlier in the process rather than after the fact. 46 | 47 | We reviewed some tools in which we can easily create a CI integration during the build process. For example, we can leverage a full WebPageTest integration for both its performance and security insights by triggering an API call upon a successful website deployment to run an end-to-end build. 48 | 49 | Furthermore, we can use command-line tools such as Check My Headers and others to validate that server response are indeed conforming to a policy. This helps us shift left in application security testing and find issues earlier in the software development lifecycle. 50 | 51 | ## Other browser security headers and controls 52 | 53 | The web is an evolving standard and as such, new security controls would be introduced. We should keep an eye on them! 54 | Embrace and prepare for privacy, feature controls, and future headers such as `Referrer-Policy`, `Feature-Policy`, `Origin-Policy`, `Integrity`, `Accept-CH`, and `Clear-Site-Data`. 55 | 56 | As the web evolves, it creates new standards for us to adopt. This also applies to new HTTP headers and we will quickly review a bunch of them here as your future steps in establishing a wider range of headers. 57 | 58 | ## Referrer-Policy 59 | 60 | Embrace and prepare for privacy-related policies using `Referrer-Policy`, which instructs the browser when and how much information to provide when setting a `Referer` header as users navigate from an existing web page. 61 | 62 | Some example values for Referrer Policy are: 63 | 64 | ``` 65 | Referrer-Policy: no-referrer 66 | Referrer-Policy: origin-when-cross-origin 67 | Referrer-Policy: same-origin 68 | ``` 69 | 70 | The default value set by the browser is `no-referrer-when-downgrade`, however, a more recommended setting will be one of the strict-origin options, such as `strict-origin-when-cross-origin`. That setting ensures that complete referrer information is sent when requests are kept to the same origin and so are bound to the same web application context. Then only sending the origin (not the full path) to any requests that are kept within the same secure HTTPS level, and nothing otherwise. 71 | 72 | The browser support matrix as to the date of writing this is as follows: 73 | 74 | ![Figure 3-2: Screenshot of the browser version support for the Referrer-Policy HTTP header as provided in the MDN website for it: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy](Figure3-2Next2.png) 75 | 76 | 2. Use the independent [feature-policy](https://snyk.io/advisor/npm-package/feature-policy) module on npm. 77 | 78 | ### Summary 79 | 80 | As the web evolves, security controls are evolved along with it. For example, a security header that increases user privacy is [Clear-Site-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data) which aims at minimizing the scope of data at rest for a website. 81 | 82 | Gradually implement more HTTP security headers to increase the controls you have for your web application, and create mitigation points for vulnerabilities. 83 | 84 | ## Educational resources 85 | 86 | Where-as this learning experience isn't geared at being a comprehensive list of all available security headers, your next step is refer to more web resources such as [Mozilla's Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) and the [W3C specs](https://www.w3.org/standards/) to keep up to date with standards and best practices. 87 | 88 | In particular, I want to recommend the following topics to enrich your knowledge on the topic of security headers and gaining an edge in understanding web security: 89 | 90 | - [OWASP Secure Headers Project](https://www.owasp.org/index.php/OWASP_Secure_Headers_Project) 91 | - Cross-Origin topics, and particularly [Cross-Origin-Resource-Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). 92 | - [Sub-resource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) policies. 93 | - [Cross-site Request Forgery](https://infosec.mozilla.org/guidelines/web_security#csrf-prevention) and related forms of tokenization. 94 | - Understanding how [Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) work and spec updates such as `SameSite` attribute. 95 | 96 | ## Security headers tooling 97 | 98 | The following list of curated resources will help you in your journey of implementing, debugging and monitoring security headers: 99 | 100 | - The [report-uri](https://report-uri.com) service 101 | - [Check My Headers](https://github.com/UlisesGascon/check-my-headers) Node.js CLI 102 | -------------------------------------------------------------------------------- /manuscript/Chapter-03-Testing for Security Headers.md: -------------------------------------------------------------------------------- 1 | # Testing for Security Headers 2 | 3 | ## The State of HTTP Security 4 | 5 | What is the state of HTTP security today for the web? Are most people enabling HTTPS? Luckily, there's an open project that tracks this, and more, in order to gain and share these insights. 6 | 7 | The web, primarily runs on HTTP, but to ensure the security, integrity, and privacy of end-to-end connections, clients communicate over a secure HTTP known as HTTPS. 8 | 9 | The importance of a secure communications channel shouldn't be undervalued. Instead, it should be a standard for any size of web applications, whether static or dynamic and indeed HTTPS is more prevalent than ever. 10 | 11 | An important push for HTTPS has been made by browsers themselves, such as Chrome's continuous attempts to discourage the use of HTTP by portraying any such websites as potentially dangerous. 12 | 13 | A prime example of that is Chrome's recent [hardened policy about mixed content](https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html) which actively blocks HTTP requests, and it follows prior actions taken to increase the importance of security aspects of the web, such as: 14 | 15 | - Clearer indications of a website's security based on [green lock icon in the address bar](https://blog.mozilla.org/security/2017/01/20/communicating-the-dangers-of-non-secure-http/) 16 | - A dedicated [Security panel](https://developers.google.com/web/updates/2015/12/security-panel) on Chrome's DevTools 17 | 18 | ![Figure 2-1: Chrome DevTools new Security panel](Figure2-1StateOfHTTP1.png) 19 | 20 | ### The HTTP Archive 21 | 22 | The [HTTP Archive](https://httparchive.org/) is an important initiative by web activists that is tracking various aspects and traits of how the web evolves over time. The projects in the HTTP archive are [open source](https://github.com/HTTPArchive/httparchive.org) and managed by a community of developers. 23 | 24 | Some of the well known reports that have been made public and online from the HTTP Archive are: 25 | 26 | - [State of the Web](https://httparchive.org/reports/state-of-the-web) - tracks the adoption of web technologies and growing web standards across websites. It reports on data points such as `Total Requests`, `Pages with Vulnerable JavaScript libraries`, and the prevalence of `HTTP/2 Requests` in websites, in the aim of identifying trends. 27 | - [State of JavaScript](https://httparchive.org/reports/state-of-javascript) - tracks the overall impact of JavaScript in a website, with identifying data points such as the size of JavaScript libraries in a website, the amount of JavaScript requests and the boot-up time which indicates the amount of CPU time each script consumes on a webpage. 28 | - [Accessibility Report](https://httparchive.org/reports/accessibility) - tracks an overall accessibility score, as noted by Chrome's Lighthouse tool, and other accessibility traits and standards such as the use of `Image Alt` attributes. 29 | 30 | I> Chrome Lighthouse 31 | I> 32 | I> Lighthouse is an open-source browser automation tool which helps in auditing a web page for performance, security, accessibility and other metrics. It also provides an overall score and recommendations for improving a web page. 33 | 34 | The [data for all HTTP Archive reports](https://httparchive.org/faq#how-do-i-use-bigquery-to-write-custom-queries-over-the-data)) is made available via Google’s BigQuery for anyone to examine. It is compiled by analyzing Alexa’s top 1 million websites, in bi-weekly scans, using the open source project and the online web performance tool [WebPageTest](https://webpagetest.org). 35 | 36 | #### HTTPS Requests 37 | 38 | Using the HTTP Archive as a tool, we can see the growth in trend of _secure by default_ with regards to HTTPS adoption by websites. 39 | 40 | I> Secure by default 41 | I> 42 | I> A secure by default approach refers to using or initializing a component with safe and secure default values, unless explicitly stated otherwise. 43 | 44 | The earliest data point is January 2016, which states a 24% of desktop websites using HTTPS, and whooping 87.7% by August 2020 across the same category. 45 | 46 | ![Figure 2-3: HTTP Archive's State of the Web - HTTPS Requests](Figure2-1StateOfHTTP2.png) 47 | 48 | #### Secure Hosting 49 | 50 | With the growth of HTTPS, static website hosting platforms have adjusted and adopted similar standards, and help push towards a more secure web. 51 | 52 | All of the following platforms for deploying and hosting your websites will serve your content over HTTPS: 53 | 54 | - Vercel 55 | - Netlify 56 | - Google's Firebase 57 | - Heroku 58 | 59 | This helps strengthen the ubiquity of HTTPS and its accessibility for small and large websites alike. 60 | 61 | [Let's Encrypt](https://letsencrypt.org) had certainly contributed a lot to a secure web by making certificates affordable (completely free). 62 | 63 | ## WebPageTest 64 | 65 | [WebPageTest](https://webpagetest.org) is one of the most popular tools around the Web Performance community to provide page speed insights, bottlenecks breakdown reports, and further information when measuring a website's performance. 66 | 67 | It is an [open source project](https://github.com/WPO-Foundation/webpagetest) that is maintained by long-time Google's software engineer [Patrick Meenan](https://github.com/pmeenan). Many leverage the project to run their performance tests in a hosted environment, where they can provide their internal resources to run end-to-end or periodical smoke test scans, to keep an eye on the quality of their web assets. 68 | 69 | I> Smoke test 70 | I> 71 | I> Smoke testing is a pattern of running a small sub-set of tests to ensure a minimal yet vital and critical flow or business capability. 72 | 73 | A relatively recent addition that was introduced to WebPageTest (May 2020) now provides users with security insights as to the status of HTTP security headers and detection of vulnerable JavaScript libraries that are rendered in scanned web pages. 74 | 75 | ### Running a scan 76 | 77 | Head over to https://webpagetest.org and enter the URL for a web page of your preference. For our demo purposes, we'll use the Fox News website `https://www.foxnews.com/` as a website to scan and see what security information can we find, to further improve the website's security posture. 78 | 79 | You may choose to configure other settings for performance, such as tweaking the location origin for running the test, specifying a browser type or maybe even a mobile device, and many other fine tunings. 80 | 81 | However, we won't be needing any of the special configurations to get a security score so go ahead and hit the **START TEST** button on the right once you've entered a URL: 82 | 83 | ![Figure 2-2: Scanning a website with WebPageTest](Figure2-2WebPageTest1.png) 84 | 85 | ### Test results 86 | 87 | Testing will take a few seconds, perhaps even up to a couple of minutes as all the test requests are queued up in the publicly available nodes for WebPageTest. 88 | 89 | Once testing is complete, WebPageTest presents the main test results which include: 90 | 91 | - Top-page scores 92 | - Test results summary for browser performance metrics such as First Byte, First Contentful Paint, Total Blocking Time, Document Complete, and Fully Loaded. These performance metrics are, however, out of the scope for us. 93 | - Waterfall for all the requests. Should be familiar and similar to the browser's DevTools. 94 | 95 | Here is how a test result looks like for `https://www.foxnews.com`: 96 | 97 | ![Figure 2-2: WebPageTest test result showing top level scores](Figure2-2WebPageTest2.png) 98 | 99 | Click on the `E` score rectangle to find out more. 100 | 101 | This takes us to the Snyk website scanner results for JavaScript vulnerabilities and security headers from the WebPageTest scan. 102 | 103 | We can clearly see the same score of `E` on the Snyk results, but here we also get a split-screen view of the scan. It is comprised of JavaScript libraries with vulnerabilities that were detected, as well as missing HTTP security headers in the web page's response. 104 | 105 | ![Figure 2-2: WebPageTest test shows security results for Fox News website](Figure2-2WebPageTest3.png) 106 | 107 | #### JavaScript libraries with vulnerabilities 108 | 109 | Let's take a closer look at each of these security insights that we received. 110 | 111 | We can spot both [lodash](https://snyk.io/vuln/npm:lodash) and [jquery](https://snyk.io/vuln/npm:jquery) with 5 vulnerability reports among them. 112 | 113 | Maybe that web page is not exploitable through Prototype Pollution vulnerabilities and Cross-site Scripting (XSS), or maybe it is. Why take the chance? 114 | 115 | Remediate the security vulnerability and the low score by upgrading to the latest version of these libraries which includes a fix for the security vulnerability. 116 | 117 | #### Security headers 118 | 119 | To the right of the test results, we see the score status related to the HTTP security headers detected as part of the HTTP response of the web page. 120 | 121 | WebPageTest was able to successfully detect the good practice of responding with the HTTP Strict Transport Security header. That's a great start. However, it looks like there are a bunch of other HTTP headers that we've learned about before which are missing. Some of these are showing up at the top of the list such as `X-Content-Type-Options`, and `X-Frame-Options`. 122 | 123 | ### Exercise 124 | 125 | Now it's time to test yourself and see what scores you get on your company website, your personal blog, or your favorite website. 126 | 127 | Scan a website and get a security score. 128 | Do you know how to fix it? 129 | 130 | You'll find more information about this topic in the following blog article about [website security score](https://snyk.io/blog/website-security-score-explained). Dig through and make sure you know have the skills to assess security headers for a website, and the notion of vulnerable JavaScript libraries. 131 | 132 | ### Summary 133 | 134 | WebPageTest is an online web tool that is well known for performance testing. Small unknown fact is that relatively recently (May 2020) it received an update to also report on security status of websites. It is not to be considered as a security penetration testing tool, but rather revealing the status of HTTP security headers employed by a website and detecting vulnerable JavaScript libraries. 135 | 136 | ## Lighthouse 137 | 138 | Using Lighthouse we can learn how to improve our website's metrics based on insights and recommendations provided after a scan is performed. 139 | 140 | It's right there in your Chrome's DevTools console, and chances are that you aren't utilizing it highly enough to get everything you can out of it, including the security aspects. 141 | 142 | ### Getting started 143 | 144 | Continuing with our previous example, let’s browse over to Fox News’ website. 145 | 146 | Once the website has loaded, launch DevTools using the `F12` keyboard key or `CMD-OPTION-I` if you're on a Mac. The location of the DevTools console might appear elsewhere in your setup, or as its own window. 147 | 148 | Once opened, click on the `Lighthouse` tab and you should see the available categories to include in our tests. 149 | 150 | ![Figure 2-3: Chrome Lighthouse in action](Figure2-3Lighthouse1.png) 151 | 152 | While it may not seem very obvious to begin with, but the security part is included as part of the `Best practices` category. This will reveal any vulnerable JavaScript libraries and their versions that are loaded on the current web page. 153 | 154 | Click the `Generate report` and let it run and collect the data about the page. Finally, we'll be presented with top scores for each category. 155 | 156 | ![Figure 2-3: Chrome Lighthouse scan results](Figure2-3Lighthouse2.png) 157 | 158 | Very clearly, the website is doing poorly on performance, but notice the best practices score isn't really high either. Let's take a further look down and check what is going on there. 159 | 160 | We can click on the `Best Practices` score or scroll down on our own and see the results, which open with the `Trust and Safety` for the website headline: 161 | 162 | - Links to cross-origin destinations were detected on the website, which is considered to be unsafe. 163 | 164 | - This website includes front-end JavaScript libraries with known security vulnerabilities. 8 of them in total, and as we expand the view we can see the libraries, their versions, and the vulnerability count for each. 165 | 166 | ![Figure 2-3: Chrome Lighthouse security scan results](Figure2-3Lighthouse3.png) 167 | 168 | ### Summary 169 | 170 | A repeated theme here from both WebPageTest in the previous chapter, as well as covering Lighthouse here as a security testing tool, is JavaScript libraries with known vulnerabilities. 171 | 172 | Lighthouse is Google's open source browser automation and testing tool to provide you with insights about web best practices for performance, accessibility, security, and more. It's right there in your Chrome's DevTools console, and chances are that you aren't utilizing it highly enough to get everything you can out of it, including the security aspects. 173 | 174 | We primarily focused on the importance of HTTP security headers, but other web security concerns and best practices shouldn't be overlooked. 175 | 176 | ## Check My Headers command line application 177 | 178 | In this lesson, we'll learn how to use a command-line application to retrieve HTTP headers set for a web page. 179 | 180 | [check-my-headers](https://github.com/UlisesGascon/check-my-headers) is a fast and simple command-line application in Node.js to ping web servers and inspect the HTTP security headers to provide a status log. 181 | 182 | Unlike online and built-in tools, `check-my-headers` would need to be installed in your development environment, or perhaps better yet, in your continuous integration pipeline. 183 | 184 | I> Continuous Integration 185 | I> 186 | I> A Continuous Integration pipeline harness automation to verify a software is building successfully, as well as functioning per an expected threshold and set of tests. 187 | 188 | It is open source, and based on Node.js, and so if you have a JavaScript tooling environment setup then it can be easily installed. 189 | 190 | In a modern Node.js environment we can make use of the `npx` tool to execute a one-off executable npm package. 191 | 192 | To start a scan, we can run the following command: 193 | 194 | ``` 195 | npx check-my-headers https://example.com 196 | ``` 197 | 198 | This will yield a result as the following screenshot proposed by Ulises Gascon, the author of this tool: 199 | 200 | ![Figure 2-4: Test results of check-my-headers Node.js CLI](Figure2-4CheckMyHeaders1.png) 201 | 202 | `check-my-headers` can also be used programmatically. As it is an npm package, it can be used as a library, in the following way: 203 | 204 | ```js 205 | const checkMyHeaders = require("check-my-headers"); 206 | 207 | checkMyHeaders("http://example.com").then(({ messages, headers, status }) => { 208 | console.log(`Status code: ${status}`); 209 | console.log(`Messages:`); 210 | console.log(messages); 211 | console.log("Current headers:"); 212 | console.log(headers); 213 | }); 214 | ``` 215 | 216 | The above will test the web page `http://example.com` for HTTP headers and return a promise, upon which it prints the result data of the scan to the console. 217 | 218 | ## Summary 219 | 220 | We looked at several tools to help us find security issues in web applications: 221 | 222 | - WebPageTest - An online web performance and security scanning tool for websites. 223 | - Lighthouse - Browser-based web assessment tool for performance, accessibility, security, and more. 224 | - Check My Headers CLI app - a handy command-line Node.js application to test a website's headers. 225 | 226 | ### Test yourself 227 | 228 | Let's see how well you know the tools we reviewed. 229 | 230 | X> 231 | X> 232 | X> 233 | X> 234 | 235 | X> ## Quiz time! 236 | X> 237 | X> ### WebPageTest 238 | X> WebPageTest helps with: 239 | X> 240 | X>a) Testing for performance issues in websites 241 | X>b) Testing for security issues in websites 242 | X>c) Testing for performance and security issues in websites and giving me insights into how to fix them 243 | X> 244 | X>The correct answer is C. 245 | 246 | X> ### Lighthouse 247 | X> Lighthouse is available via Chrome DevTools and helps with: 248 | X> 249 | X>a) Finding performance issues 250 | X>b) Finding security issues 251 | X>c) Finding SEO and Web Accessibility issues 252 | X>d) Finding issues with Progressive Web Apps 253 | X> 254 | X>The correct answers are A,B,C, and D. 255 | 256 | X> ### Keeping up with security 257 | X> What are some ways you can make sure you have no regressions in your security headers setup? 258 | X> 259 | X>a) Run tools like `check-my-headers` in my Continuous Integration systems to fail the build if a regression happens 260 | X>b) In an End-to-End Continuous Integration setup I can use the WebPageTest API to schedule tests of my website and ensure the security score is the same, or better 261 | X>c) Run a security penetration test after the web application is published 262 | X>d) This is a manual and rigorous process that takes time, very expensive and is hard to keep up repeating effectively. 263 | X> 264 | X>The correct answers are A and B. 265 | 266 | What's next? 267 | 268 | If you'd like to keep security in check, you'd want to automate it to keep up with the scale of development. All of the above tools have APIs or integration points that you can connect to continuous integration systems. 269 | -------------------------------------------------------------------------------- /manuscript/Chapter-02-HTTP Security Headers.md: -------------------------------------------------------------------------------- 1 | # HTTP Security Headers 2 | 3 | ## HTTP Strict Transport Security 4 | 5 | HTTP Strict Transport Security, also known as HSTS, is a protocol standard to enforce secure connections to the server via HTTP over SSL/TLS. HSTS is configured and transmitted from the server to any HTTP web client using the HTTP header _Strict-Transport-Security_ which specifies a time interval during which the browser should only communicate over an HTTP secured connection (HTTPS). 6 | 7 | > Tip 8 | > 9 | > When a _Strict-Transport-Security_ header is sent over an insecure HTTP connection the web browser ignores it because the connection is insecure, to begin with. 10 | 11 | In future requests, after the header has been set, the browser consults a _preload_ service, such as [that of Google's](https://hstspreload.org/), to determine whether the website has opted in for HSTS. 12 | 13 | ### The Risk 14 | 15 | The risk that may arise when not communicating over a secure HTTPS connection is that a malicious user can perform a Man-In-The-Middle (MITM) attack and down-grade future requests to the webserver to use an HTTP. Once an HTTP connection is established, a malicious attacker can see and read all the data that flows through. 16 | 17 | > Interesting fact: 18 | > The [original HSTS draft](https://tools.ietf.org/html/rfc6797) was published in 2011 by Jeff Hodges from PayPal, 19 | > Collin Jackson from Carnegie Mellon University, and Adam Barth from Google. 20 | 21 | A website that uses HTTPS may still create insecure HTTP requests which end users wouldn't suspect but expose end-users to MITM attack security concerns. 22 | 23 | In the following flow diagram, _Figure 1-1_, we can see an example scenario where the server returns an HTML file for the login page to the browser, which includes some resources that are accessible over HTTP (`http://cdn.server.com/images/submit.png`), like the submit button's image. 24 | 25 | If an attacker can perform a Man-In-The-Middle attack and "sit on the wire" to listen and sniff any un-encrypted traffic that flows through, then they can access and read those HTTP requests which may include sensitive data. Even worse scenarios may include HTTP resources set for POST or PUT endpoints where actual data is being sent and can be sniffed. 26 | 27 | ![Figure 1-1 - Visualizing HTTPS MITM Attack](Figure1-1-VisualizingHTTPSMITMAttack.png) 28 | 29 | ### The Solution 30 | 31 | When web servers want to protect their web clients through a secured HTTPS connection, they need to send the _Strict-Transport-Security_ header with a given value which represents the duration of time in seconds for which the web client should send future requests over a secured HTTPS connection. 32 | 33 | e.g. to instruct the browser to upgrade all requests sent to the server to HTTPS for the next hour: 34 | 35 | ``` 36 | Strict-Transport-Security: max-age=3600 37 | ``` 38 | 39 | ### Helmet Implementation 40 | 41 | To use Helmet's HSTS library we need to download the npm package and we will also add it as a package dependency to the Node.js project we're working on: 42 | 43 | ```bash 44 | npm install helmet --save 45 | ``` 46 | 47 | Let's set up the `hsts` middleware to indicate to a web client, such as a browser, that it should only send HTTPS requests to our server's hostname for the next month: 48 | 49 | ```js 50 | const helmet = require("helmet"); 51 | 52 | // Set the expiration time of HTTPS requests to the 53 | // server to 1 month, specified in milliseconds 54 | const reqDuration = 2629746000; 55 | 56 | app.use( 57 | helmet.hsts({ 58 | maxAge: reqDuration, 59 | }) 60 | ); 61 | ``` 62 | 63 | In the above snippet, we instruct the Express `app` to use the `hsts` middleware and respond to all requests with the `Strict-Transport-Security` header set. 64 | 65 | Note that if for any reason the browser receives multiple HSTS header directives it will only respect and enforce the policy based on the first one sent. 66 | 67 | It is common for web servers to have sub-domains to fetch assets from or make REST API calls to, in which case we would also like to protect them and enforce HTTPS requests. To do that, we can include the following optional parameter to the `hsts` options object: 68 | 69 | ```js 70 | includeSubDomains: true; 71 | ``` 72 | 73 | > Tip 74 | > 75 | > If it is necessary to instruct the browser to disable the _Strict-Transport-Security_ a server can respond with this header's `max-age` set to `0` which will result in the browser expiring the policy immediately and enable access over an insecure HTTP connection. 76 | 77 | ### Exercise 78 | 79 | The following exercise shows a practical example of using HTTP Strict Transport Security (HSTS), 80 | as a browser security control to allow only HTTPS-enabled resources to be fetched from 81 | the primary domain for a website. 82 | 83 | #### Requirements 84 | 85 | We will be using [Heroku](https://www.heroku.com/) as our hosting platform for an Express Node.js application, as we will need both an HTTPS-enabled hosting, as well as an HTTP hosting to switch on and off the HTTP Strict Transport Security header. 86 | 87 | #### Source code 88 | 89 | Obtain the source code from the official GitHub repository at: https://github.com/lirantal/nodejssecurity-headers-hsts. 90 | 91 | Once you cloned the repository, the overall projects file structure that you should be aware of is: 92 | 93 | 1. An express server in `server.js` 94 | 2. A handlebars template in `views/home.handlebars` which serves as an example website 95 | 3. A `public` directory which has an image that we will use 96 | 97 | #### Deployment 98 | 99 | You'll need a Heroku account to deploy the Express web app there. 100 | 101 | 1. Sign-up for a free Heroku account, and have the `heroku` CLI installed. 102 | 2. `npm install` all the dependencies in the project. 103 | 3. Create a Heroku Node.js project 104 | 4. Login from the CLI using: `heroku login` 105 | 5. Using the `heroku` CLI create a new project, such as: `heroku git:remote -a hsts-express-example` to instantiate a git remote for the project, assuming `hsts-express-example` is the name of the heroku project name you used in step (3). 106 | 6. Deploy the app using `git push heroku master` 107 | 108 | At this point, it should be available as both HTTPS and HTTP endpoints, such as: 109 | 110 | - https://hsts-express-example.herokuapp.com/ 111 | - http://hsts-express-example.herokuapp.com/ 112 | 113 | #### Exercise 1 114 | 115 | Once the Express app is deployed, try to access it: `https://hsts-express-example.herokuapp.com/` 116 | 117 | X> ## Quiz time! 118 | X> 119 | X> What is special about the request to load the [static unplash image](http://hsts-express-example.herokuapp.com/harley-davidson-zGzXsJUBQfs-unsplash.jpg) ? 120 | X>a) It is originally an HTTP request 121 | X>b) This request is upgraded to an HTTPS request 122 | X>c) Nothing special about this HTTP request 123 | X> 124 | X>The correct answer is both A and B. 125 | X> 126 | X> Are you seeing anything going wrong with the network requests? What is not working with the favicon? 127 | X> 128 | X>a) The favicon is not loading because it's a bigger image than it should be. 129 | X>b) The favicon is not loading due to the HSTS security header. 130 | X>c) The favicon is not loading because the web server is misconfigured. 131 | X> 132 | X>The correct answer is B. The favicon is not loading because it is only served from an HTTP domain, but the HSTS security header is upgrading all requests to be HTTPS and so it fails to load. 133 | 134 | Did you look at the network tab in the browser's DevTools? What did you find? 135 | 136 | You should notice a few things happening: 137 | 138 | - The main request to the page `https://hsts-express-example.herokuapp.com/` replies with a `Strict-Transport-Security` security header. 139 | - The request to load the image `http://hsts-express-example.herokuapp.com/harley-davidson-zGzXsJUBQfs-unsplash.jpg` gets an internal browser redirect to its HTTPS version because the HSTS version does just that - it upgrades all requests to their HTTPS counterpart to load them securely. 140 | - The favicon from `http://http.rip/favicon.ico` is blocked from being loaded. 141 | 142 | X> ## Quiz time! 143 | X> 144 | X> 145 | X> Update the expiration time of the HSTS setting to 0 (zero): 146 | X>`js X> httpApp.use( X> helmet.hsts({ X> maxAge: 0, X> }) X>); X>` 147 | X> 148 | X>What changed? 149 | X> 150 | X>a) Strict-Transport-Security is set but with an expiration time of 0 which disables it. 151 | X>b) The unsplash image is loaded from HTTP directly, without any redirect 152 | X>c) The favicon is fetched and displayed for the website 153 | X> 154 | X>The correct answers are A, B, and C. 155 | 156 | ### Debugging HSTS settings in Chrome 157 | 158 | As you experiment with the HTTP Strict Transport Security header, you may be setting it on localhost served pages, which could end up as a footgun due to HTTP-only pages being forcefully redirected to HTTPS. 159 | 160 | #### Reviewing Chrome's HSTS settings 161 | 162 | If such an issue occurs and you wish to review your Chrome setup of HSTS settings and manually include or exclude domains from the HSTS list, navigate to `chrome://net-internals/#hsts` in Chrome's address bar and update as necessary. 163 | 164 | It should look like the image depicted in Figure 1-2 below: 165 | 166 | ![Figure 1-2 - Chrome's internal HSTS configuration](Figure1-2-ChromeinternalHSTSconfiguration.png) 167 | 168 | #### Clear cache 169 | 170 | Sometimes, no localhost entry will exist on the HSTS internal configuration for Chrome, yet a forceful redirect to HTTPS will still take place. 171 | 172 | To ensure you clear the cache, do as follows: 173 | 174 | 1. Navigate to the localhost domain at `http://localhost` 175 | 2. Open DevTools by pressing `CTRL+SHIFT+I` or `F12` 176 | 3. Locate the address bar's reload page icon and right-click it. In the menu that opens up select `Empty Cache and Hard Reload` 177 | 178 | Reloading the localhost website over HTTP, such as `http://localhost:3000` should now work as expected without an HTTPS redirect. 179 | 180 | ## X Frame Options 181 | 182 | The [X-Frame-Options](http://tools.ietf.org/html/7034) HTTP header was introduced to mitigate an attack called Clickjacking. It allows an attacker to disguise page elements such as buttons, and text inputs by hiding their view behind real web pages which render on the screen using an iframe HTML element or similar objects. 183 | 184 | > Deprecation notice 185 | > The X-Frame-Options header was never standardized as part of an official specification but many of the popular browsers today still support it. 186 | > Its successor is the Content-Security-Policy (CSP) header which will be covered in the next section and one should focus on implementing CSP for newly built web applications. 187 | 188 | ### The Risk 189 | 190 | The [Clickjacking](https://owasp.org/www-community/attacks/Clickjacking) attack, also known as UI redressing, is about misleading the user to perform a seemingly naive and harmless operation while in reality, the user is clicking buttons that belong to other elements, or typing text into an input field which is under the attacker's control. 191 | 192 | Common examples of employing a Clickjacking attack: 193 | 194 | 1. If a bank or email account website doesn't employ an `X-Frame-Options` HTTP header, then a malicious attacker can render them in an iframe, and place the attacker's input fields on the exact location of the bank or email website's input for username and password and record your credentials information. 195 | 2. A web application for video or voice chat that is insecure can be exploited by this attack to let the user mistakenly assume they are just clicking around on the screen or playing a game, while in reality, the series of clicks is actually turning on your webcam. 196 | 197 | ### The Solution 198 | 199 | To mitigate the problem, a web server can respond to a browser's request with an `X-Frame-Options` HTTP header which is set to one of the following possible values: 200 | 201 | 1. `DENY` - Specifies that the website can not be rendered in an iframe, frame, or object HTML elements. 202 | 2. `SAMEORIGIN` - Specifies that the website can only be rendered if it is embedded on an iframe, frame, or object HTML elements from the same domain the request originated from. 203 | 3. `ALLOW-FROM ` - Specifies that the website can be framed and rendered from the provided URI. It is important to note that you can't specify multiple URI values, but are limited to just one. 204 | 205 | A few examples to show how this header is set are: 206 | 207 | ``` 208 | X-Frame-Options: ALLOW-FROM http://www.mydomain.com 209 | ``` 210 | 211 | and 212 | 213 | ``` 214 | X-Frame-Options: DENY 215 | ``` 216 | 217 | T> Beware of Proxies 218 | T> 219 | T> Web proxies are often used as a means of caching and they natively perform a lot of header manipulation. 220 | T> 221 | T> Beware of proxies that might strip off this or other security-related headers from the response. 222 | 223 | ### Helmet Implementation 224 | 225 | With Helmet, implementing this header is as simple as requiring the `helmet` package and using Express's `app` object to instruct Express to use the `xframe` middleware provided by Helmet. 226 | 227 | To set the `X-Frame-Options` to completely deny all forms of embedding: 228 | 229 | ```js 230 | const helmet = require("helmet"); 231 | 232 | app.use( 233 | helmet.frameguard({ 234 | action: "deny", 235 | }) 236 | ); 237 | ``` 238 | 239 | Similarly, we can allow frames to occur only from the same origin by providing the following options object: 240 | 241 | ```js 242 | { 243 | action: "sameorigin"; 244 | } 245 | ``` 246 | 247 | Or to allow frames to occur from a specified host: 248 | 249 | ```js 250 | { 251 | action: 'allow-from', 252 | domain: 'https://mydomain.com' 253 | } 254 | ``` 255 | 256 | ### Exercise 257 | 258 | The following exercise shows a practical clickjacking attack by a malicious party. In this example, the attacker deploys a website they control with a hidden iframe. The website is rendered in an iframe is an innocent, third-party website. The attacker's aim is to hijack any clicks made by unsuspecting users on that website. 259 | 260 | #### Requirements 261 | 262 | Node.js and npm are expected to be available in your development environment as we will run this exercise locally. 263 | 264 | Note: In this exercise, there's no strict need for serving the web pages content over HTTPS. 265 | 266 | #### Source code 267 | 268 | Obtain the source code from two official GitHub repositories: 269 | 270 | - https://github.com/lirantal/nodejssecurity-headers-xframe-malicious - serves the contents of a malicious website that embeds a remote iframe in an attempt to trick the user to click on. 271 | - https://github.com/lirantal/nodejssecurity-headers-xframe-innocent - serves the contents of an innocent website. In our example, this serves as a Twitter profile card. 272 | 273 | Once you cloned both repositories locally we are ready to run both servers. 274 | 275 | #### Deployment 276 | 277 | To run this exercise we will begin by installing all the dependencies for each npm project and then run the Express servers: 278 | 279 | In each directory where the projects are cloned: 280 | 281 | 1. `npm install` all the dependencies 282 | 2. Run `npm start` in two terminal windows so we can have the Express servers run in parallel 283 | 284 | The servers will require that you have ports 3000 and 3001 available to bind to by default. Otherwise, you may provide a `PORT` environment variable to each web server project to configure a different local port. 285 | 286 | Note: you should be running both servers simulatanously. 287 | 288 | #### Exercise 1 289 | 290 | Load up the malicious website by navigating to `http://localhost:3000`. 291 | 292 | You will be presented with a website asking you to sign-up for a React developer newsletter. Would you? 293 | 294 | ![Exercise1](Figure1-3Excercise1.png) 295 | 296 | D> ## Quiz time! 297 | D> 298 | D> 299 | D> The invite to join this React newsletter is quite tempting. Did you click it? What happened? 300 | 301 | It looks like clicking the `Sign up!` button on this website doesn't do what you hoped it would. 302 | 303 | ![Exercise1 - Interacting with a malicious website](Figure1-4Exercise1.png) 304 | 305 | #### Exercise 2 306 | 307 | In the previous excercise we observed a peculiar behavior, where clicking an website's invitation to a newsletter didn't result in the way we expected. 308 | 309 | You're not sure what was going on, right? 310 | What if you could see the actual element you clicked on? 311 | 312 | Add `reveal=1` query parameter to the website, such as: `http://localhost:3000?reveal=1` and the iframe that has been loaded in the background will be revealed in 50% opacity so you can see how it renders on the screen and perfectly aligns with the "Sign up!" button. 313 | 314 | ![Exercise2 - Interacting with a malicious website](Figure1-5Exercise2.png) 315 | 316 | #### Exercise 3 317 | 318 | In the cloned malicious website directory, open `views/home.handlebars` and update the iframe URL to some other websites, such as Twitter itself (i.e: https://twitter.com). The change should look like this: 319 | 320 | ```html 321 | 322 | ``` 323 | 324 | Re-run the malicious website Express server with the change you made, and visit the page again at `http://localhost:3000`. 325 | 326 | D> ## Quiz time! 327 | D> 328 | D> What happened when you changed the iframe URL to something else? 329 | D> Can you try and find a website that should be secure but allows rendering in an iframe? 330 | 331 | #### Exercise 4 332 | 333 | Ok, let's fix things. 334 | 335 | In the cloned malicious website directory, open again the file `views/home.handlebars` and update the iframe URL to `http://localhost:3001/html/twitter.html` and make sure the other innocent web server, which we cloned earlier, is running. The change should look like this: 336 | 337 | ```html 338 | 339 | ``` 340 | 341 | Save the file changes, re-run the malicious website Express server with the change you made, and visit the page again at `http://localhost:3000`. 342 | Observe the current behavior. The iframe is now rendering the content of the innoccent website we have running at `http://localhost:3001` 343 | 344 | To protect the innocent website, let's make sure that we update it to disallow rendering itself as an iframe with the help of Helmet's `frameguard` middleware: 345 | 346 | ```js 347 | const helmet = require("helmet"); 348 | app.use(helmet.frameguard({ action: "deny" })); 349 | ``` 350 | 351 | Refresh the malicious website and note the changes. 352 | 353 | ## Content Security Policy 354 | 355 | As reviewed before with the X-Frame-Options header, there are many attacks related to content injection in the user’s browser. These include Clickjacking attacks or other forms of attacks such as Cross-Site-Scripting (XSS). 356 | 357 | I> What is an XSS? 358 | I> 359 | I> A Cross-site scripting, or XSS for short, is a type of security attack in which a user can inject JavaScript, or other types of scripts (for example injecting CSS, or HTML) to trigger the execution of them by the context interpreter, such as the browser. 360 | 361 | Another improvement to the previous set of headers we reviewed so far is a header that can tell the browser which content to trust. This allows the browser to prevent attempts of content injection that are not trusted in the policy defined by the application owner. 362 | 363 | With a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy) (CSP) it is possible to prevent a wide range of attacks, including Cross-site scripting and other content injections. The implementation of a CSP renders the use of the X-Frame-Options header obsolete. 364 | 365 | ### The Risk 366 | 367 | Using a Content Security Policy header will prevent and mitigate XSS and other injection attacks. Examples of some of the issues it can prevent by setting a CSP policy: 368 | 369 | - Inline JavaScript code specified with `