CSP:如何允许给定URI前缀的不安全eval(Firefox)

时间:2012-06-08 07:36:29

标签: javascript security firefox mathjax content-security-policy

我正在尝试使用MathJax作为我们的网络应用程序的一部分,该应用程序使用非常严格的Content Security Policy (CSP)。问题在于MathJax被编码为使用eval() [确切地说,以Function()的形式使用,而CSP默认不会将其视为安全。

我目前正在使用以下CSP标头:

X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation';

这导致MathJax 2.0代码失败,因为它使用Function()。我试图仅对位于路径Function()下方的同一原点内的MathJax允许unsafe-eval(即/:static/math/)。为此,我尝试添加

unsafe-eval '/:static/math/*'

使完整标题看起来像

X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation'; unsafe-eval '/:static/math/*'

但我仍然无法使用Firefox 13.0来运行代码。我收到一条错误消息给Firefox Web Console(位于Tools - Web Developer中):

[10:09:59.072] call to Function() blocked by CSP @ http://localhost:8080/:static/math/2.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML:29

但是,我没有收到“报告 - uri”的CSP报告。 (如您所见,我目前正在通过自定义localhost端口运行测试而不使用SSL,以防有所不同。static之前的冒号不是拼写错误,我保留所有以冒号开头的路径部分对于应用程序的内部使用,所有用户内容都可以自由定义其他URL。)

我对unsafe-eval属性的使用是否不正确或是否仅允许对'self'的子集进行unsafe-eval?目的是仅允许对同一来源的unsafe-eval路径前缀/:static/math,“self”的严格CSP JS代码执行,以及任何其他方法的JS代码。

1 个答案:

答案 0 :(得分:17)

存在多个问题:

  1. Content-Security-Policy(CSP)标头无法正常工作。 CSP仅具有单个主机+端口组合(原点)的粒度。如果您不允许所有脚本都拥有unsafe-eval,则没有脚本可以拥有它。唯一可行的解​​决方法是不使用需要unsafe-eval的脚本(幸运的是,自MathJax bug 256修复后,MathJax不再需要unsafe-eval。)

  2. allow语法是旧的Mozilla变体,不应使用。当前语法是说default-src后跟允许作为所有内容源的方案或主机名或来源,然后根据需要覆盖每个子类型的默认值(例如script-src)。除self之外,某些来源可能还支持其他来源关键字。例如,script-src支持unsafe-eval,这意味着任何允许执行的脚本都允许运行eval()或Function(),而unsafe-inline意味着任何一个标记允许支持某种内联脚本执行。允许unsafe-eval可能是可以接受的,但是unsafe-inline与script-src几乎没有关系(否则,你根本不应该打扰CSP)。

  3. script-src的正确语法如下:

    script-src 'self' cdnjs.cloudflare.com
    

    结合从https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js

  4. 加载MathJax
  5. MathJax还使用内联样式属性,因此需要关注(除非已经允许)或MathJax将在尝试渲染数学时引发Exception

    style-src 'self' 'unsafe-inline'
    

    不可能使用CSP来允许JS插入样式属性,并且不会在HTML源代码中插入样式属性以产生效果。

  6. 在CSP违规的情况下,似乎Firefox 13.0(至少)没有立即“回家”。大多数违规报告都会在活动结束后的某个时间提交。报告提交时,Chrome似乎更具侵略性,这将使测试更容易一些。根据我的经验,Firefox并不总是发送CSP报告 - 它可能使用某种启发式方法来发送不重复的消息。

  7. 最后,要使MathJax与Content-Security-Protection一起使用,您需要以下标题(假设您通过CDNJS使用MathJax):

    Content-Security-Policy: default-src 'self'; script-src 'self' cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline';
    

    较早的浏览器(例如Firefox 13)过去需要额外的参数,例如options,或者需要使用非标准的headere名称,例如X-Content-Security-PolicyX-WebKit-CSP。由于用户代理现在支持标准标题,因此不再需要这些黑客攻击。 ( MSIE除外,与MS Edge相反。