标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-2464] 作者: 如一 发表于: [2019-09-03]
本文共 [428] 位读者顶过
前言
传统上,HTTP请求通常被视为一个独立的主体。在本文中,我将会探讨一种已经被遗忘的技术,该技术可以让远程攻击者在未经身份验证的情况下,轻松攻击目标网络基础设施。 本文中,我将向你展示如何巧妙地通过该技术来修改受害者发送的HTTP请求,以此将他们钓鱼到恶意网站,进行后续的攻击。另外,我还将演示如何对你自己的请求使用后端重组来利用前端的每一点信任,获得对内部API的最大权限访问,攻击web缓存,并攻击PayPal的登录页面。 HTTP请求走私(HTTP Request Smuggling )最早是在2005年由Watchfire发现的。 Tomcat请求漏洞(Request Smuggling):CVE编码:CVE-2014-0227。 漏洞描述:通过在chucked请求中包含一个非正常的chunk数据有可能导致Tomcat将该请求的部分数据当成一个新请求。危害程度:重要!不过,HTTP走私技术要求对处理HTTP消息的各种代理相当熟悉,否则无法发动这种攻击。 综上所述,由于其技术难度和附带攻击的威力太大,多年来它一直被忽略。本文除了带你了解该攻击技术外,我还会介绍它的攻击变体和利用载体。最后,我还将帮助你使用你通过自定义的开源工具和可靠的黑盒检测,评估和利用该技术,以及最小化附带的风险,让你轻松使用该攻击技术。
[出自:jiwo.org] 核心概念
从HTTP/1.1开始,就广泛支持通过一个底层TCP或SSL/TLS套接字发送多个HTTP请求。该协议非常简单,只需将HTTP请求背靠背放置,服务器就会解析标头,以确定每个请求的结束位置和下一个开始的位置。不过该协议却常常与HTTP管线化(HTTP pipelining)混淆,这是因为在默认情况下,HTTP 协议中每个传输层连接只能承载一个 HTTP 请求和响应,浏览器会在收到上一个请求的响应之后,再发送下一个请求。在使用持久连接的情况下,某个连接上消息的传递类似于请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3。 HTTP Pipelining(管线化)是将多个 HTTP 请求整批提交的技术,在传送过程中不需等待服务端的回应。使用 HTTP Pipelining 技术之后,某个连接上的消息变成了类似这样请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3。 HTTP管线化是一种不太常见的子类型,本文描述的攻击并不需要这种子类型。 就HTTP Pipelining本身而言,这是无害的。然而,现代网站是由一系列系统组成的,所有这些系统都通过HTTP进行通信。这种多层架构会接收来自多个不同用户的HTTP请求,并通过单个TCP / TLS连接进行路由。
这意味着,后端与前端会在很短的时间内就每个消息的结束位置达成一致。否则,攻击者可能会发送一个模棱两可的消息,被后端解释为两个不同的HTTP请求。 这使攻击者能够在下一个合法用户的请求开始时,预先向请求中添加任意内容。在本文中,被走私的内容将被称为“前缀”,并以橙色突出显示。 让我们假设前端优先考虑第一个内容长度头部,后端优先考虑第二个内容长度头部。从后端角度看,TCP的流程可能是以下这样的。 在底层,前端将蓝色和橙色的数据转发到后端,后端仅在发出响应之前读取蓝色内容。这使得后端套接字被橙色数据攻击。这样,当合法的绿色请求到达时,恶意内容将被附加到橙色内容中,从而导致意外的响应。 在这个例子中,注入的“G”将攻击绿色用户的请求,他们可能会得到类似于“Unknown method GPOST”的响应。 本文中的每次攻击都会按着这种基本格式进行,Watchfire在他的研究文章描述了一种称为“向后请求走私”的替代方法,但这依赖于前端和后端系统之间的管线,因此这种方法很少会被使用。 而在现实中,双内容长度技术很少被使用,因为许多系统会明确地地拒绝具有多个内容长度头的请求。相反,我们将使用分块编码攻击系统,不过前提是使用RFC 2616规范。分块编码是HTTP1.1协议中定义的Web用户向服务器提交数据的一种方法,当服务器收到chunked编码方式的数据时会分配一个缓冲区存放之,如果提交的数据大小未知,客户端会以一个协商好的分块大小向服务器提交数据。 分块编码是是HTTP1.1协议中定义的Web用户向服务器提交数据的一种方法,当服务器收到chunked编码方式的数据时会分配一个缓冲区存放之,如果提交的数据大小未知,客户端会以一个协商好的分块大小向服务器提交数据。 如果接收到的消息同时具有传输编码标头字段和内容长度标头字段,则必须忽略内容长度标头字段。 由于RFC 2616规范默许可以使用Transfer-Encoding: chunked and Content-Length处理请求,因此很少有服务器拒绝此类请求。这意味着,无论何时,只要我们能够找到一种方法将传输编码标头隐藏在服务器中,它就会返回使用内容长度,这样我们就可以使整个系统失去同步。 你可能不太熟悉分块编码,因为Burp Suite之类的工具会自动将分块请求或响应缓冲到常规消息中,以便于编辑。在分块消息中,主体由0个或多个块组成。每个块由块大小组成,后跟一个换行符(\r\n),后面跟块内容。消息以大小为0的块终止。下面是使用分块编码的简单的去同步攻击: 此时,我们还没有在隐藏传输编码标头,所以这个漏洞利用主要适用于前端根本不支持分块编码的系统,这也是在许多网站上看到的使用内容传输网络Akamai的行为。 如果是后端不支持分块编码,我们需要翻转偏移量。 这种技术本来就适用于相当多的系统,但只要将传输编码标头经过简单地处理,变得稍微难以识别,就可以悄无声息地隐藏在系统中。这可以使用服务器HTTP解析中的差异来实现。下面是一些只有一些服务器能够识别Transfer-Encoding: chunked。在本研究中,每一个标头都成功地利用了至少一个系统:
如果前端和后端服务器都有这些特点,那么它们中的每一个都是无害的,否则就是一个主要的威胁。要了解更多技术,请查看regilero正在进行的研究,我们将简要介绍一下使用其他技术的实际例子。
请求走私的方法
请求走私背后的理论很简单,但是不受控制变量的数量以及我们对前端背后发生的事情的完全不可见性可能会导致更复杂的攻击。 目前我已经开发了应对这些挑战的技术和工具,并将它们组合成以下简单的方法,我们可以利用这些方法查找请求走私漏洞并证明其影响:
检测请求走私漏洞的方法
检测请求走私漏洞的最直接的方法就是发出一个模糊的请求,然后发出一个正常的“受害者”请求,其目的就是观察后者是否得到意外响应。然而,这种方法极容易受到干扰。如果另一个用户的请求在我们的受害者请求之前就遇到了感染的套接字,他们将得到被攻击的响应,而我们将不会发现漏洞。这意味着在具有大量流量的实时站点上,如果不利用此过程中大量的真实用户,就很难证明存在请求走私。即使在没有其他流量的站点上,你也有可能因为应用程序级的异常终止连接而导致错误的拒绝。 为了解决这个问题,我开发了一种检测策略,该策略使用一系列消息,这些消息使易受攻击的后端系统挂起并使连接超时。这种技术几乎没有误报,可以抵抗应用程序级的异常,否则会导致漏报,最重要的是几乎没有影响其他用户的风险。 假设前端服务器使用内容长度标头,后端使用传输编码标头。我把这个方向称为CL.TE 。我们可以通过发送以下请求来检测潜在的请求走私: 由于内容长度较短,前端将只转发蓝色文本,而后端将在等待下一个块大小时超时,这将导致可观察到的时间延迟。 如果两个服务器同步(TE.TE或CL.CL),请求将被前端拒绝或由两个系统无害地处理。最后,如果desync以另一种方式发生(TE.CL),由于无效的块大小“Q”,前端将拒绝消息,而不会将其转发到后端,这可以防止后端套接字被感染。 我们可以使用以下请求安全地检测TE.CL desync: 由于 以“0”块结束,前端将只转发蓝色文本,而后端将超时等待X到达。 如果desync以另一种方式发生(CL.TE),那么这种方法将使用X感染后端套接字。不过这可能会损害合法用户,幸运的是,通过首先运行先前的检测方法,我们可以排除这种可能性。 这些请求可以适应目标解析中的任意差异,它们用于通过HTTP Request Smuggler自动识别请求走私漏洞,HTTP请求走私者开发了一个开源的Burp Suite扩展来帮助处理此类攻击,它们现在也在Burp Suite的核心扫描器中使用。尽管这是一个服务器级别的漏洞,但是单个域中的不同端点常常路由到不同的目标,因此应该将此技术应用于每个端点。
漏洞确认
此时,我们要做的就是证明后端套接字是否遭受了感染。为此,我们将发出一个旨在感染后端套接字的请求,然后发出一个请求,该请求有望成为感染的受害者,明显改变原有的响应。如果第一个请求导致错误,后端服务器可能会决定关闭连接,放弃受感染的缓冲区并中断攻击。要避免这种情况,可以将目标对准设计为接受POST请求的端点,并保留任何预期的GET/POST参数。 有些站点有多个不同的后端系统,前端通过查看每个请求的方法、URL和标头来决定将其路由到哪里。如果受害者请求被路由到与攻击请求不同的后端,则攻击将失败。因此,可以确定“攻击”的内容和“受害者”的最初请求应该是相似的。 如果目标请求看起来像: 然后尝试CL.TE套接字感染,看起来如下: 如果攻击成功,受害者请求(绿色)将得到404响应。 TE.CL攻击看起来和受害者的请求很相似,但是需要一个关闭块,这意味着我们需要自己指定所有的标头,并将受害者请求放入主体中。确保前缀中的内容长度略大于正文:
|