利用HTTP管道化隐藏恶意请求的技术解析

本文详细探讨了如何利用HTTP管道化技术将恶意HTTP请求隐藏在合法请求中,通过实际代码示例和AWS CloudFront测试验证其有效性,并对比了Cloudflare的SNI防护机制。

利用HTTP管道化隐藏请求

在本篇文章中,我将讨论如何使用HTTP管道化来隐藏恶意HTTP请求。这并非域名伪装(domain fronting),但采用了类似技术以达到相同效果:对于无法执行TLS拦截的观察者,只能看到“良性”请求,从而掩盖了“恶意”请求。

背景知识

在Web早期,客户端请求的每个对象都通过独立的TCP连接完成。例如,如果一个页面包含两张图片和一个JavaScript库,则需要建立四个连接:第一个用于页面本身,另外三个用于额外元素。这种做法被认为增加了过多流量,尤其是在使用HTTPS时,因为每个元素都需要协商安全连接。为解决此问题,引入了管道化技术。

管道化允许多个请求通过单个TCP连接分组发送,从而消除了为每个页面元素单独建立和断开连接的需要,理应提升性能。这一概念在一段时间内运作良好,大多数现代浏览器和Web服务器都内置了支持。然而,到2018年,由于实现中存在太多问题,该功能在浏览器中被禁用。尽管如此,大多数服务器以及更重要的是大多数CDN仍支持此技术。

更多信息可参考维基百科页面:HTTP pipelining - Wikipedia

示例请求

以下是我将发送的管道文件内容:

1
2
3
4
5
GET /pipeline/page1.php HTTP/1.1
Host: vuln-demo.com

GET /pipeline/page2.php HTTP/1.1
Host: vuln-demo.com

如您所见,有两个请求:第一个针对page1.php,第二个针对page2.php。它们将通过同一连接依次发送,由服务器处理并按顺序返回响应。此概念后来被弃用的原因之一是,如果第一个请求耗时较长,所有后续请求都会被阻塞等待,最终可能减慢速度而非提速。

持久连接与管道化的区别

在研究之前,我误以为通过发送Connection: keep-alive头可激活管道化,但实际上这是错误的。“keep-alive”启用的是持久连接,与管道化不同。持久连接在请求之间保持TCP连接开放,但强制遵循等待先前请求返回的原始规则;管道化移除了该规则,允许客户端无需等待即可发送多个请求。必须有持久连接才能进行管道化,但拥有持久连接并不一定意味着能进行管道化。在HTTP 1.0中,持久性需通过“keep-alive”头激活;在HTTP 1.1中,持久性被默认假定,除非使用Connection: close头请求关闭连接。更多关于持久连接的信息,请参见:HTTP persistent connection

发送请求

使用以下命令发送请求:

1
$ (cat pipe ; sleep 5) | openssl s_client -connect vuln-demo.com:443 -servername vuln-demo.com

响应如下(部分内容省略):

1
2
3
4
5
HTTP/1.1 200 OK
...
This is page 1HTTP/1.1 200 OK
...
This is page 2DONE

可见有两个响应:页面1和页面2,表明管道化工作正常。

测试AWS CloudFront

我利用已有的AWS CloudFront设置进行测试。简要来说,“fronted.digi.ninja”是“良性”域名,指向主站点“digi.ninja”;“d1sdh26o090vk5.cloudfront.net”是“恶意”域名,指向“frontme.vuln-demo.com”。请求内容为:

1
2
3
4
5
GET / HTTP/1.1
Host: fronted.digi.ninja

GET / HTTP/1.1
Host: d1sdh26o090vk5.cloudfront.net

使用命令发送并筛选页面标题:

1
2
$ (cat pipe2 ; sleep 5) | openssl s_client -connect fronted.digi.ninja:443 -servername fronted.digi.ninja | \
  grep "<title>"

结果:

1
2
	<title>DigiNinja - DigiNinja</title>
	<title>Fronted Vuln Demo</title>

第一个结果来自我的站点,第二个来自vuln-demo站点,显示CloudFront支持管道化且请求按预期工作。观察者只能看到“良性”域名“fronted.digi.ninja”的DNS查询和TLS设置中的SNI字段,而无法察觉对“d1sdh26o090vk5.cloudfront.net”的请求。

测试Cloudflare的SNI防护

检查Cloudflare的SNI防护是否有效。请求内容:

1
2
3
4
5
GET / HTTP/1.1
Host: www.cloudflare.com

GET /index.php HTTP/1.1
Host: digininja.org.uk

发送命令:

1
2
(cat pipe3 ; sleep 5) | openssl s_client -connect cloudflare.com:443 -servername www.cloudflare.com | \
  grep "<title>"

结果:

1
2
    <title>Cloudflare - The Web Performance & Security Company
<head><title>403 Forbidden</title></head>

由于请求中使用的SNI为“www.cloudflare.com”,连接被绑定到该主机,因此对“digininja.org.uk”的请求被拒绝,返回403,表明防护有效。

结论

我们有了另一种隐藏HTTP流量的方法,该方法在AWS上有效,但在Cloudflare上无效。未来我将测试Azure CDN和Google CDN,目前您已有足够内容进行实验,快去尝试吧。

相关文章

近期归档

  • SteelCon Ninja Run 2022
  • Cracked Flask Lab
  • WSL2 DNS Oddness
  • Splitting XSS payloads
  • Alert Function Hijacking
  • The CORS Demos
  • Entering a new community
  • Out running with friends at SteelCon 2019
  • An odd quirk with XSS through JavaScript URI
  • Becoming More Accessible
  • Using HTTP Pipelining to hide requests
  • Domain Fronting with Cloudflare
  • Domain Fronting with CloudFront
  • A 101 on Domain Fronting
  • More …

支持本站

本站项目均无报酬,如果您想支持我的工作,可通过以下联盟链接提供账户积分或现金回馈(通常仅为几分钱,但积少成多)。

Buy me a smoothie


所有内容均由Robin Wood创建,除非另有说明。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计