将带有 nonce 的 CSP 标头添加到 Lambda Edge

Posted

技术标签:

【中文标题】将带有 nonce 的 CSP 标头添加到 Lambda Edge【英文标题】:Adding CSP headers with a nonce to Lambda Edge 【发布时间】:2020-11-20 12:29:35 【问题描述】:

我是一名运营人员,正在建立一个需要实施安全标头的网站。

我创建了一个 Lambda@Edge 函数,其中包含我需要的标题,它工作正常,但我想为 style-src 添加一个随机数,因为我们正在调用外部 URL(谷歌字体等)。我发现的大多数指南都只使用“自我”而不是其他 URL。在 SO 上还有一个关于此的其他问题,但响应不起作用,因为我使用的是 Origin Request 而不是 Origin Response。

我可以将它添加到 Lambda@Edge 函数吗?我有一些生成随机数的 nodejs 代码,但是当我尝试将它添加到 style-src 部分时,它会忽略它。我不懂 JS,所以这对我来说很难解决。

如果这不是正确/最佳方式,我愿意接受任何将 nonce 与 CSP 和 Lambda@Edge 一起使用的方法。

这是我的 Lambda@Edge 代码。

'use strict';
exports.handler = (event, context, callback) => 
    
    //Get contents of response
    const response = event.Records[0].cf.response;
    const headers = response.headers;
    

//Set new headers
 headers['strict-transport-security'] = [key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload'];
 headers['content-security-policy'] = [key: 'Content-Security-Policy', value: "default-src 'self'; frame-ancestors 'none'; connect-src https://dev.example.io https://api.exampleapi.io; img-src 'self' data: https://examplebucket.s3.region.amazonaws.com; script-src 'self'; font-src 'self' https://fonts.example.com; style-src 'self' https://fonts.example.com; object-src 'none'"];
 headers['x-content-type-options'] = [key: 'X-Content-Type-Options', value: 'nosniff'];
 headers['x-frame-options'] = [key: 'X-Frame-Options', value: 'DENY'];
 headers['x-xss-protection'] = [key: 'X-XSS-Protection', value: '1; mode=block'];
 headers['referrer-policy'] = [key: 'Referrer-Policy', value: 'same-origin'];
    
    //Return modified response
    callback(null, response);
;

这是我用来生成 nonce 的代码,可以在本地工作。

const crypto = require('crypto');
let nonce = crypto.randomBytes(16).toString('hex');

【问题讨论】:

【参考方案1】:

我注意到,当您使用 CloudFront 事件 Origin RequestOrigin Response 作为 lambda@edge 函数的触发器时,您只会在这种情况下生成随机数如果有缓存未命中。但据我了解,每个 HTTP 请求都需要一个随机数。这表明您需要使用其他事件之一(查看器请求或查看器响应),但另一方面,这会为每个 HTTP 请求触发您的函数(无论您请求的对象是否在缓存中),什么可能对您网站的访问量产生高额成本。

AWS 在此处详细描述了所有 CloudFront 事件: CloudFront Events That Can Trigger a Lambda Function

您在这里没有提到的一件事是,不仅需要为 CSP 标头生成 nonce,而且还需要将 nonce 添加到您的 html 页面(例如,将所有 <script> 标记替换为 @ 987654325@。可以在 lambda@edge 函数中执行此操作,方法是从 S3 存储桶中读取所需的对象并替换所有脚本标签,如上所述。但是您需要了解 AWS lambda@edge 限制(例如由 Lambda 函数生成的响应)。在此处检查限制:Restrictions on using Lambda functions with CloudFront

我已经找到了在使用 nonces 创建 CSP 时不使用 lambda@edge 函数的解决方案。因此,您不要使用 lambda@edge,而是使用例如将 API 网关与 Lambda 一起使用。请参阅此处(尝试 3:Route53、CloudFront、S3、API 网关、Lambda):My experience getting an A+ from Mozilla’s Observatory tool on AWS

【讨论】:

以上是关于将带有 nonce 的 CSP 标头添加到 Lambda Edge的主要内容,如果未能解决你的问题,请参考以下文章

CSP PHP 问题 LottiePlayer

为啥 CSP 安全标头会阻止 Iphone 上的谷歌地图?

如何允许内联 JS 脚本使用 Nonce 进行 CSP

CSP nonce 实现是啥样的?

CSP 在 NextJs 中阻止 Google Tag Manager 仍然使用 nonce

如何根据请求创建 OWIN 中间件