具有内容安全策略的 reCAPTCHA

reCAPTCHA with Content Security Policy

我正在努力使 reCAPTCHA 与严格的内容安全策略一起工作。这是我的基本版本,可以正常工作:

HTML

<script src='//www.google.com/recaptcha/api.js' async defer></script>

HTTP Headers

Content-Security-Policy: default-src 'self'; script-src 'self' www.google.com www.gstatic.com; style-src 'self' https: 'unsafe-inline'; frame-src www.google.com;

但是,我想删除 style-src 部分中的 unsafe-inline。在documentation上写着:

We recommend using the nonce-based approach documented with CSP3. Make sure to include your nonce in the reCAPTCHA api.js script tag, and we'll handle the rest.

但我无法让它工作...这是我尝试过的:

HTML

<script src='//www.google.com/recaptcha/api.js' nonce="{NONCE}" async defer></script>

HTTP Headers

Content-Security-Policy: default-src 'self'; script-src 'self' https: 'nonce-{NONCE}'; style-src 'self' 'nonce-{NONCE}'; child-src www.google.com;

这是我在 Chrome 53:

上遇到的错误

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' https: 'nonce-{NONCE}'". Either the 'unsafe-inline' keyword, a hash ('sha256-MammJ3J+TGIHdHxYsGLjD6DzRU0ZmxXKZ2DvTePAF0o='), or a nonce ('nonce-...') is required to enable inline execution.

我错过了什么?

我不相信 reCAPTCHA 支持 CSP 而不允许内联样式。我在 reCAPTCHA Github 存储库中找到了 this open issue

This sample page with reCAPTCHA using CSP 有效,因为它没有定义 style-srcdefault-src。检查页面的 DOM 会发现插入的 div:

<div class="g-recaptcha" data-sitekey="6LdOLRgTAAAAAPYECt9KLIL_LLwOuuuHAUw7QUTm">
    <div style="width: 304px; height: 78px;">
        <div>
            <iframe src="https://www.google.com/recaptcha/api2/anchor?k=6LdOLRgTAAAAAPYECt9KLIL_LLwOuuuHAUw7QUTm&amp;co=aHR0cHM6Ly9jc3AtZXhwZXJpbWVudHMuYXBwc3BvdC5jb206NDQz&amp;hl=en&amp;v=r20160926121436&amp;size=normal&amp;cb=g72al0v10dxg" title="recaptcha widget" width="304" height="78" role="presentation" frameborder="0" scrolling="no" name="undefined"></iframe>
        </div>
        <textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid #c1c1c1; margin: 10px 25px; padding: 0px; resize: none;  display: none; "></textarea>
    </div>
</div>

textarea 的内联样式计算结果为 MammJ3J+TGIHdHxYsGLjD6DzRU0ZmxXKZ2DvTePAF0o=,具体取决于:

echo -n "width: 250px; height: 40px; border: 1px solid #c1c1c1; margin: 10px 25px; padding: 0px; resize: none;  display: none; " | openssl dgst -sha256 -binary | base64

这与您的错误消息中指示的散列匹配。但是,在 style-src 中包含散列不适用于 Chrome per this open bug 中的内联样式。 unsafe-hashed-attributes 似乎会支持它,据我所知,它还没有发布到 Chrome 版本。

就其价值而言,添加哈希使其在 Firefox 中运行。

在 web.config 文件中为 ASp.Net 个应用程序使用以下代码。

<child-src>
      <add source="www.google.com"/>

reCAPTCHA 服务已更新,因此不再需要 style-src 'unsafe-inline'。 HTML 以下和 HTTP headers 应该可以根据 this 已关闭的问题工作:

HTML:

<script src="https://www.google.com/recaptcha/api.js?render=site-key" nonce="{NONCE}"></script>

HTTP Header:

Content-Security-Policy: default-src 'self'; script-src 'nonce-{NONCE}'; img-src www.gstatic.com; frame-src www.google.com; object-src 'none'; base-uri 'none';