抖音 html 中的 nonce 属性是什么?

1,784 阅读4分钟

image.png

进入抖音 Web 的官网,打开 DevTools 可以看到 html 中的 linkscript 标签中有很多 nonce 属性,没了解过的小伙伴可能会疑惑这个是干嘛用的?

先说结论nonce 与浏览器的 CSP(Content Security Policy)策略有关,用于防止多种常见的网络攻击,例如 XSS(跨站脚本攻击)和数据注入攻击。

CSP 策略

核心内容

官网文档developer.mozilla.org/en-US/docs/…

CSP 是通过 HTTP 响应头(通常是 Content-Security-Policy)或 <meta> 标签设置的。它提供了一系列指令,用于定义资源加载的安全策略。例如:

  1. default-src: 设置默认的资源加载源。
  2. script-src: 限制 JavaScript 文件的加载源。
  3. style-src: 限制样式表(CSS)的加载源。
  4. img-src: 限制图像资源的加载源。
  5. font-src: 限制字体文件的加载源。
  6. connect-src: 限制 AJAX 请求和 WebSocket 连接的目标。
  7. frame-src: 限制 <iframe> 的嵌入内容源。

CSP 的影响

CSP 对以下方面有直接影响:

  1. 脚本执行:

    • 阻止来自非信任源的脚本执行。
    • 禁止内联 JavaScript 执行(除非使用 unsafe-inline,但这会降低安全性)。
    • 防止动态创建的 <script> 元素加载未经允许的内容。
  2. 资源加载:

    • 限制外部资源(如图片、样式、字体等)的加载源。
    • 阻止跨域资源的加载,除非被明确允许。
  3. 内联资源:

    • 禁止内联 CSS 或内联 JavaScript,除非通过哈希值(hash)或加密签名(nonce)明确允许。
  4. Frame 嵌套:

    • 防止未授权的嵌套内容,例如通过 frame-src 限制恶意网站的 iframe 嵌套。
  5. 数据泄露防护:

    • 防止未经允许的网络连接,从而减少敏感信息通过恶意请求泄露的风险。

配置示例

 Content-Security-Policy: 
   default-src 'self'; 
   script-src 'self' https://apis.example.com; 
   style-src 'self' 'unsafe-inline'; 
   img-src 'self' data:;

解释:

  • 仅允许同源加载默认资源。
  • 仅允许加载来自 selfhttps://apis.example.com 的脚本。
  • 允许内联样式和同源样式表。
  • 图像可以来自同源和 data: 协议。

Nonce 的作用

CSP(Content Security Policy) 中,nonce(number used once) 是一种用于验证内联脚本和样式安全性的随机值。这种机制允许内联资源被浏览器加载和执行,而不必通过放宽安全策略(例如使用 unsafe-inline),从而在安全性与功能之间取得平衡。

nonce 的作用

当 CSP 策略中使用 nonce 时:

  1. 页面加载时,服务器会为每个请求动态生成一个唯一的、不可预测的随机字符串(即 nonce 值)。
  2. 浏览器只会执行那些脚本或样式标签中包含匹配的 nonce 属性的内容。
  3. 不包含匹配 nonce 的资源将被阻止执行。

这种方法有效防止了攻击者通过 XSS(跨站脚本攻击)注入恶意脚本,因为攻击者无法预先知道随机生成的 nonce 值。

nonce 的工作机制

  1. HTTP 响应头配置 nonce CSP 策略中使用 nonce,如下所示:

     Content-Security-Policy: script-src 'self' 'nonce-abcdef123456'; style-src 'self' 'nonce-abcdef123456';
    

    在这段配置中,只有内联脚本和样式中包含 nonce="abcdef123456" 的内容会被执行或应用。

  2. HTML 中的内联资源加 nonce 属性 在 HTML 文档中,内联脚本或样式需包含与 CSP 中指定的 nonce 值一致的属性:

     <script nonce="abcdef123456">
         console.log('This script is allowed to execute.');
     </script>
     ​
     <style nonce="abcdef123456">
         body { background-color: lightblue; }
     </style>
    
  3. 随机性和不可预测性 服务器应在每次请求时动态生成一个全新的 nonce,并且该值应该具有足够的随机性和长度,以防止被攻击者猜测。

使用 nonce 的优点

  1. 提升安全性 防止内联脚本和样式的注入攻击,即便攻击者试图在 HTML 中插入恶意脚本,也无法绕过 nonce 验证。
  2. 兼容性 使用 nonce 可以避免依赖 unsafe-inline,从而符合更高的安全要求,同时保持一定的灵活性。
  3. 与动态生成的内容配合良好 nonce 机制允许开发者在特定场景下安全地使用动态生成的内联脚本。

常见问题

  1. 如何生成 nonce 通常由服务器端动态生成,可以使用随机字符串生成工具或函数,例如:

     // Node.js 例子
     const crypto = require('crypto');
     const nonce = crypto.randomBytes(16).toString('base64');
    
  2. 每次请求的 nonce 必须不同 如果每次使用相同的 nonce,会削弱安全性,攻击者可能复用已知的 nonce 值。

  3. 浏览器支持 现代浏览器均支持 nonce,但仍需确保您的 CSP 策略中不包含 unsafe-inline,否则 nonce 无效。

参考链接

  1. developer.mozilla.org/en-US/docs/…