如何检测内容安全策略(CSP)

37
我注意到GitHub和Facebook现在都在执行此策略,限制第三方脚本在其体验/网站中运行。 有没有一种方法可以使用JavaScript检测文档是否正在运行CSP? 我正在编写一个书签小工具,并希望在用户访问不支持嵌入脚本标记的站点时给出提示信息。

你可以尝试将新的<script>var test=true;</script>注入文档中,然后检查变量是否被设置。如果CSP被执行(并且您的脚本不被允许),则此代码块将根本不会被执行。 - kravietz
有趣,会尝试一下。 - onassar
它奏效了吗?只是好奇一下 :) - kravietz
2
哎呀 :( 在 Fb 中执行 JS 或那些有内容策略的网站中没有问题。只是在加载第三方、未列入白名单的脚本时会出现问题。我可以研究一下 script 的 onerror 事件,看看能否解决这个问题。 - onassar
我尝试了@onassar建议的onerror方法,至少在Chrome 40中似乎有效。 - Jon z
请参考以下链接的答案:https://dev59.com/KJvga4cB1Zd3GeqP46Xe#40053880 - milpool
7个回答

29

3
这是列表中我发现可以成功运作的唯一方法。 - FrostyDog

8

6

如果连接速度较慢,超时时间可能需要延长。我使用Onload来检测它,似乎可以工作。如果加载成功,则CSP显然未启用或配置不正确。

var CSP = 0;
frame = document.createElement('script');
frame.setAttribute('id', 'theiframe');
frame.setAttribute('src', location.protocol+'//example.com/');
frame.setAttribute('onload', 'CSP=1;');
document.body.appendChild(frame);
setTimeout(function(){if (0 == CSP){alert("CSP IS ENABLED");}}, 250);

gotcha. 设定一个很高的超时时间会很奇怪,因为那样我就必须防止我的应用程序/脚本在达到该超时时间之前运行。不过还是谢谢。 - onassar
抓住了。不过不想太依赖它。我们的书签小工具被广泛使用 :/ - onassar
啊哈。我的也是在全球使用的书签工具中运行。我同意。我的解决方案并不完美,但我尝试了很多东西,这是唯一有效的方法。我不知道你的书签工具是做什么的,但我们的相当复杂,所以这个方法很好用。如果你找到更好的方法,请告诉我!干杯 - user583507
你能提供链接吗?我们的许多用户来自网络带宽较低的发展中国家。 - onassar
糟糕,我的意思是链接您的 Chrome Web Store 扩展程序。 - onassar
显示剩余3条评论

5

以下是从https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5的内容翻译:

黑客可以通过注入恶意代码,从你的网站中窃取用户的信用卡号和密码。这种攻击方式被称为“形式填写攻击”,因为它利用了网站上的表单填写功能。

fetch(document.location.href)
.then(resp => {
  const csp = resp.headers.get('Content-Security-Policy');
  // does this exist? Is is any good?
});

但是如果connect-src='none',则此操作将失败并报告错误。


你也可以在代码中设置 CSP,而不仅仅是在头部设置吗? - Rok Burgar

4

检测CSP支持的简单方法是通过检查是否可以运行JavaScript的eval()方法而不会抛出错误,如下所示:

try {
    eval("return false;");
} catch (e) {
    return true;
}

然而,这仅在CSP实际启用(显然)且响应标头中设置了Content-Security-Policy并且script-src中没有'unsafe-eval'的情况下才有效。
我来到这里是为了找到一种在浏览器中检测CSP支持而无需实际启用CSP的方法。不过似乎这是不可能的。
顺便说一句,IE不支持CSP,仅支持IE 10+中的沙盒指令,根据CSP标准,这使其不成为符合标准的Web浏览器。

3

目前,在运行中的浏览器中没有办法实现这一点。

然而,根据规范,以下内容应该可以工作,并且在启用实验性网络平台功能的Chrome浏览器中可以正常工作:chrome://flags/

function detectCSPInUse() {
  return "securityPolicy" in document ? document.securityPolicy.isActive : false;
}

如果document.securityPolicy被实现,你可以从中得到 SecurityPolicy 接口。该接口有一些属性,可以提供更详细的信息以确定当前允许什么。


我通过控制台在Facebook上运行了那段代码。尽管他们正在运行一个代码(防止插入“script”标签),但我得到了一个“false”。 - onassar
这个功能似乎还没有完全准备好。例如,在所有当前版本的Chrome中,此功能都隐藏在“启用实验性Web平台功能”标志后面。您的用户必须转到chrome://flags/,打开它并重新启动浏览器。但是,如果API可用,您现在可以实现它--上面的代码旨在工作。 - AndrewF
这个功能似乎已经从Chrome中消失了,即使打开了chrome://flags/#enable-experimental-web-platform-features。 - Jeffrey Yasskin
3
看起来规范中已经不存在 SecurityPolicy 接口了。 - gsnedders

0

我正在检查我的书签代码中的onError事件,并在脚本未加载时提示用户安装我的扩展程序。

javascript:(function(){
var s=document.createElement('script');
s.setAttribute('type','text/javascript');
s.setAttribute('src','https://example.ru/bookmarklet?hostname=%27+encodeURIComponent(location.hostname));
s.setAttribute('onerror', 'if(confirm(`Downloading from the site is possible only through the "MyExtensionName" extension. Install extension?`)){window.open("https://chrome.google.com/webstore/detail/myextensionlink");}');
document.body.appendChild(s);})();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接