Skip to content

Improve Security with Lambda at Edge

Summary

This will be a copy/paste of a fantastic article discussing how to customize security headers after they've left the origin. This is extremely helpful for restricting the attack surface on a website and provides a significant improvement in security.

I have a similar article already written on this topic that can be found here.

Preface

[email protected] is Amazon Web Services’s (AWS’s) service run on the Amazon CloudFront Global Edge Network. You can utilize this service to run code in a serverless fashion at a location that is close to the end user.

There are numerous measures you can take to improve security with [email protected] Today we are going to cover five ways via the use of security headers. [email protected] provides you with the ability to customize headers after responses have left the origin.

X-XSS-Protection

The X-XSS-Protection header helps prevent a number of cross-site scripting (XSS) attacks in a handful of browsers.

Mozilla notes:

X-XSS-Protection is a feature of Internet Explorer and Chrome that stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although these protections are largely unnecessary in modern browsers when sites implement a strong Content Security Policy that disables the use of inline JavaScript (‘unsafe-inline’), they can still provide protections for users of older web browsers that don’t yet support CSP.

Directions

  • Create a Lambda function with the following code:
exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["x-xss-protection"] = [{ value: "1; mode=block" }];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response.

X-Content-Type-Options

The X-Content-Type-Options header helps prevent MIME type related XSS attacks.

Mozilla notes:

X-Content-Type-Options is a header supported by Internet Explorer, Chrome and Firefox 50+ that tells it not to load scripts and stylesheets unless the server indicates the correct MIME type. Without this header, these browsers can incorrectly detect files as scripts and stylesheets, leading to XSS attacks. As such, all sites must set the X-Content-Type-Options header and the appropriate MIME types for files that they serve.

Directions

  • Create a Lambda function with the following code:
exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["x-content-type-options"] = [{ value: "nosniff" }];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response.

X-Frame-Options

The X-Frame-Options header helps prevent frame related XSS attacks.

Mozilla notes:

X-Frame-Options is an HTTP header that allows sites control over how your site may be framed within an iframe. Clickjacking is a practical attack that allows malicious sites to trick users into clicking links on your site even though they may appear to not be on your site at all. As such, the use of the X-Frame-Options header is mandatory for all new websites, and all existing websites are expected to add support for X-Frame-Options as soon as possible.

Directions

  • Create a Lambda function with the following code:
exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["x-frame-options"] = [{ value: "DENY" }];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response.

Content-Security-Policy

The Content-Security-Policy header helps prevent the vast majority of XSS attacks.

Mozilla notes:

Content Security Policy (CSP) is an HTTP header that allows site operators fine-grained control over where resources on their site can be loaded from. The use of this header is the best method to prevent cross-site scripting (XSS) vulnerabilities. Due to the difficulty in retrofitting CSP into existing websites, CSP is mandatory for all new websites and is strongly recommended for all existing high-risk sites.

One of the main benefits of the CSP comes from the disabling of inline Javascript. New websites can be built with this in mind, but fixing all of the inline Javascript on older websites may not be an option. As such, exercise caution when adding a CSP to existing websites.

Directions

Create a Lambda function with the following code:

exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["content-security-policy"] = [
    {
      value:
        "default-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; block-all-mixed-content",
    },
  ];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response

Gotchas

One challenge that single page applications (SPA) face if they implement server side rendering (SSR) is with inlining critical styles to the document head and inlining application state to the document body. To successfully resolve this challenge, you will need to calculate hashes for the script(s) and style(s) and put base64 encoded versions in the script-src and style-src sections of the content security policy. For example:

script-src 'self' 'sha256-1LWiqTBX9ooah9yxrjAPIapj/bpKu8E2gxHrAcrvXJQ='; style-src 'self' 'sha256-lEmNQfaoD6+gZL66vjr9syPi0uIaBbN/9

Strict-Transport-Security

The Strict-Transport-Security header prevents insecure access to your website.

Mozilla notes:

HTTP Strict Transport Security (HSTS) is an HTTP header that notifies user agents to only connect to a given site over HTTPS, even if the scheme chosen was HTTP. Browsers that have had HSTS set for a given site will transparently upgrade all requests to HTTPS. HSTS also tells the browser to treat TLS and certificate-related errors more strictly by disabling the ability for users to bypass the error page.

Directions

Create a Lambda function with the following code:

exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["strict-transport-security"] = [
    { value: "max-age=31536000; includeSubDomains" },
  ];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response

Extra Credit

If you are confident that all apex, subdomains, and nested subdomains of your domain will be served securely, you can submit your domain to be included on the HSTS preload list.

Putting It All Together

Rather than creating five separate [email protected] functions, you can combine them all into one function.

Directions

Create a Lambda function with the following code:

exports.handler = (event, context, callback) => {
  const { response } = event.Records[0].cf;

  response.headers["x-xss-protection"] = [{ value: "1; mode=block" }];
  response.headers["x-content-type-options"] = [{ value: "nosniff" }];
  response.headers["x-frame-options"] = [{ value: "DENY" }];
  response.headers["content-security-policy"] = [
    {
      value:
        "default-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; block-all-mixed-content",
    },
  ];
  response.headers["strict-transport-security"] = [
    { value: "max-age=31536000; includeSubDomains" },
  ];

  return callback(null, response);
};

Set the Lambda function to run as the CloudFront origin response or viewer response

Testing the Results

Mozilla has created a great tool for testing the presence and validity of the aforementioned security headers on your website. You must perform the following steps:

In Summary

Security should be one of the top concerns when operating any web application. Fortunately, [email protected] makes it easy to implement best security practices across the board on your websites. I challenge you to incorporate all of the aforementioned headers on all of your web applications and strive for an A on the Mozilla Observatory tool.

References

https://moduscreate.com/blog/simple-security-lambda-edge/