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 web application in
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
- 918