Securing your static web application in

Prehistory & motivation

Prehistory & motivation

  • Colab was penetration tested (by SwiftSec)

Prehistory & motivation

  • Colab was penetration tested (by SwiftSec)
  • Numerous security vulnerabilities popped up (mainly in terms of HTTP response headers)

Prehistory & motivation

  • Colab was penetration tested (by SwiftSec)
  • Numerous security vulnerabilities popped up (mainly in terms of HTTP response headers)
  • We had to fix them! 👨🏻‍🚒

Prerequisites

Prerequisites

  • Your application is hosted on AWS S3.
  • The static domain (S3) has a CloudFront distribution in front of it.

AWS 101

AWS 101

  • S3 (Simple Static Storage)
    • Bucket
    • Holds your static files (your app)
    • Accessible via URL:
      • <bucket-name>.s3.amazonaws.com

AWS 101

  • S3 (Simple Static Storage)
    • Bucket
    • Holds your static files (your app)
    • Accessible via URL:
      • <bucket-name>.s3.amazonaws.com
  • CloudFront (CDN)
    • Stands in front of your S3 bucket domain
    • Caches responses

AWS 101

  • S3 (Simple Static Storage)
    • Bucket
    • Holds your static files (your app)
    • Accessible via URL:
      • <bucket-name>.s3.amazonaws.com
  • CloudFront (CDN)
    • Stands in front of your S3 bucket domain
    • Caches responses
  • Lambda
    • A serverless piece of code
    • Can be executed from other AWS services' events.
$ curl -X HEAD -I https://domain.com

HTTP/2 200
content-type: text/html
content-length: 2116
date: Wed, 22 Apr 2020 13:20:37 GMT
last-modified: Tue, 07 Apr 2020 13:47:55 GMT
etag: "f84939d115325fbd2da8208c4d83cfd4"
server: AmazonS3
x-cache: Miss from cloudfront
x-amz-cf-pop: SOF50-C
x-amz-cf-id: dtiJbNp4pn_GGAWOamdwULC0Q

CloudFront edges

CloudFront edges

CloudFront edges

CloudFront edges

Lambda@Edge

Adding security headers via L@E

Creating security headers L@E

  • Important: Lambda@Edge is currently supported in only one AWS region: us-east-1 (North Virginia)

Creating security headers L@E

Creating security headers L@E

Implementing the Lambda

def lambda_handler(event, context):
    # ...

Handler signature

Implementing the Lambda

def lambda_handler(event, context):
    # ...
{
  "Records": [
    {
      "cf": {
        "request": {
          "clientIp": "203.0.113.178",
          "headers": {},
          "method": "GET",
          "querystring": "",
          "uri": "/"
        },
        "response": {
          "headers": {},
          "status": "200",
          "statusDescription": "OK"
        }
      }
    }
  ]
}

Event structure

Implementing the Lambda

def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    headers = response['headers']
    
    return response

Fetching the response

Implementing the Lambda

def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    headers = response['headers']
    
    headers['x-frame-options'] = [
        {
            'key': 'X-Frame-Options',
            'value': 'DENY'
        }
    ]
    
    # ...
    
    return response

Adding a security header

Deploying the Lambda 🚢

Deploying the Lambda 🚢

Deploying the Lambda 🚢

$ curl -X HEAD -I https://domain.com

HTTP/2 200
content-type: text/html
content-length: 2116
date: Wed, 22 Apr 2020 13:20:37 GMT
last-modified: Tue, 07 Apr 2020 13:47:55 GMT
etag: "f84939d115325fbd2da8208c4d83cfd4"
server: AmazonS3
x-cache: Miss from cloudfront
x-amz-cf-pop: SOF50-C
x-amz-cf-id: dtiJbNp4pn_GGAWOamdwULC0Q
x-frame-options: DENY
$ curl -X HEAD -I https://domain.com

HTTP/2 200
content-type: text/html
content-length: 2116
date: Wed, 22 Apr 2020 13:20:37 GMT
last-modified: Tue, 07 Apr 2020 13:47:55 GMT
etag: "f84939d115325fbd2da8208c4d83cfd4"
server: AmazonS3
x-cache: Miss from cloudfront
x-amz-cf-pop: SOF50-C
x-amz-cf-id: dtiJbNp4pn_GGAWOamdwULC0Q
x-frame-options: DENY
$ curl -X HEAD -I https://domain.com

HTTP/2 200
content-type: text/html
content-length: 2116
date: Wed, 22 Apr 2020 13:20:37 GMT
last-modified: Tue, 07 Apr 2020 13:47:55 GMT
etag: "f84939d115325fbd2da8208c4d83cfd4"
server: AmazonS3
x-cache: Miss from cloudfront
x-amz-cf-pop: SOF50-C
x-amz-cf-id: dtiJbNp4pn_GGAWOamdwULC0Q
x-frame-options: DENY

Resources 📚

🕵🏻‍♂️ Analyze your app for security vulnerabilities: https://observatory.mozilla.org/

Securing your static application in AWS

By Ventsislav Tashev

Securing your static application in AWS

How to secure your static application in AWS S3 with Lambda@Edge

  • 754