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
- 891