概述
如上图所示,我们发送的金丝雀被反射在一个id属性中。通过发送双引号,我们可以看到值是如何到达接收器的。但当发送双引号时,屏幕变为空白。这时只需转义双引号,那么网站就不会中断,我们可以看到它到达接收器:
在HTML中反斜杠对双引号没有影响,因此这里似乎存在一个XSS漏洞。我们需要通过注入其它会导致JavaScript执行的字符进行确认。在对该注入点进行多次测试后,我们发现注入的值必须是一个有效的CSS选择器。所以我们想出了以下XSS向量:
burpdomxss input[value='"><iframe srcdoc=<script>alert(document.domain)&llt;/script>>"']
但只有在禁用CSP保护策略时,该向量才能生效。因此,我们开始寻找在PayPal上绕过CSP保护策略的方法。
在 PayPal 上绕过 CSP
首先,我们注意到CSP中存在一些薄弱环节。在script-src指令中,它允许某些域名如*.paypalobjects.com和*.paypal.com。在“unsafe-eval”指令中允使用eval、函数构造器和其他JavaScript执行接收器:
base-uri 'self' https://*.paypal.com; connect-src 'self' https://*.paypal.com
https://*.paypalobjects.com https://*.google-analytics.com
https://nexus.ensighten.com https://*.algolianet.com https://*.algolia.net
https://insights.algolia.io https://*.qualtrics.com; default-src 'self'
https://*.paypal.com https://*.paypalobjects.com; form-action 'self'
https://*.paypal.com; frame-src 'self' https://*.paypal.com
https://*.paypalobjects.com https://www.youtube-nocookie.com
https://*.qualtrics.com https://*.paypal-support.com; img-src 'self' https: data:; object-src 'none'; script-src 'nonce-RGYH2N1hP59U4+QwLcOaI5GgHbP19yxg1MEmKXc883wiDeAj' 'self' https://*.paypal.co
https://*.paypalobjects.com 'unsafe-inline' 'unsafe-eval'; style-src 'self' block-all-mixed-content;; report-uri https://www.paypal.com/csplog/api/log/csp
从策略来看,允许列表和“unsafe-eval”可能是绕过CSP的最佳目标。所以我们在如下所示的Burp Suite范围内添加了这些域名:
^(?:.*[.]paypal(?:objects)?.com)$
Burp允许在范围内选择特定的协议,由于策略具有“block-all-mixed-content”指令,因此我们只选择了HTTPS协议。
在研究了CSP保护策略之后,我们在Burp中打开了嵌入式浏览器,并开始手动浏览站点,以选择具有大量JavaScript资产的目标。一旦我们收集了大量的代理历史记录,就可以使用Burp的搜索功能来查找较旧的JavaScript库。使用Burp的限制功能来选定范围内的项目,以查找可以绕过CSP的资产。
我们从搜索AngularJS开始,因为使用它创建CSP绕过非常容易,但并没有找到相关对AngularJS的引用。所以我们继续使用Bootstrap,并在请求头和响应正文中进行搜索,出现了几个Bootstrap实例,我们发现了一个较旧的版本 (3.4.1)。
接下来,我们对Bootstrap工具进行了研究。GitHub上存在一些XSS漏洞,但这些漏洞只影响3.4.0 版本。尝试无果之后,我们开始考虑PayPal是否存在一些我们可以利用的不安全JavaScript。
这一次,我们不再是搜索特定的库,而是搜索托管库的部分路径,例如“/c979c6f780cc5b37d2dc068f15894/js/lib/”。在搜索结果中,我们注意到一个名为youtube.js的文件,并立即在其中发现了一个明显的DOM型XSS漏洞:
../' + $(this).attr("data-id") + '.jpg"...
该文件使用jQuery,因此我们需要做的就是包含jQuery和youtube.js,利用该漏洞绕过CSP保护策略。查看youtube.js文件,我们发现它使用CSS选择器来查找YouTube播放器元素:
...$(".youtube-player").each(function() {...
所以我们需要注入一个具有“youtube-player”类的元素,以及一个包含我们的jQuery XSS向量的data-id属性。一旦我们有了通用PayPal CSP绕过的基础,我们所要做的就是将它与原始注入相结合。首先,我们注入了一个带有srcdoc属性的iframe,但由于这是一个基于DOM的漏洞,脚本将无法执行。但是使用srcdoc他们将:
input[value='"><iframe srcdoc=
在这里我们需要通过转义双引号并为选择器的部分值指定单引号,来确保它是一个有效的选择器。然后我们可以注入指向jQuery和YouTube工具的脚本:
<script/src=https://www.paypalobjects.com/web/res/28f/c979c6f780cc5b37d2dc068f15894/js/lib/jquery-2.2.4.min.js></script><script/src=https://www.paypalobjects.com/web/res/28f/c979c6f780cc5b37d2dc068f15894/js/lib/youtube.js></script>
请注意,我们必须对向量进行HTML编码,因为我们不希望它用 > 字符关闭srcdoc属性。出于同样的原因,我们避免使用空格。然后我们使用YouTube工具注入脚本,jQuery会转换并执行该脚本。我们需要再次对向量进行HTML编码,给它正确的类名,并使用data-id属性来注入我们的向量。请注意,我们使用已编码的单引号来避免属性被破坏。我们必须对双引号进行双重HTML编码,因为srcdoc将解码HTML,并且data-id属性将在iframe中渲染时进行解码 。因此双重编码可以确保引号在注入YouTube工具时存在。最后,我们使用单行注释进行清理,以确保脚本在注入后忽略任何内容。用双引号和单引号完成CSS选择器:
<div/class=youtube-player data-id='&quot;><script>alert(document.domain)//'>>"']
以上就是对PayPal的CSP保护策略的完整绕过。但它是否一定需要呢?从以上过程中,我们可以发现,jQuery是CSP的克星。jQuery使用“unsafe-eval”指令转换脚本,并且乐于使用策略执行它们,而原始的XSS漏洞就是一个jQuery选择器。因此我们可以注入一个可以被jQuery转换的脚本,这样就不需要单独进行CSP绕过了。所以,我们可以将注入简化为以下内容:
input[value='"><script>alert(1)//>"']
END
本文始发于微信公众号(SecTr安全团队):PayPal中的DOM型XSS漏洞,以及CSP绕过
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论