由Roarctf Easy Calc引起对http走私和分块传输绕过waf的思考

2019-11-18 6,134

之前在做roarctf第一个web时候读到过关于php解析漏洞的文章。

https://www.freebuf.com/articles/web/213359.html

但是用的是在num参数前面构造一个%20来绕过waf。

但是后来看群里有个师傅提起了http走私协议。于是就去学习了一下。

HTTP走私原理:

HTTP请求走私漏洞的原因是由于HTTP规范提供了两种不同方式来指定请求的结束位置,它们是Content-Length标头和Transfer-Encoding标头,Content-Length标头简单明了,它以字节为单位指定消息内容体的长度。

Transfer-Encoding标头用于指定消息体使用分块编码(ChunkedEncode),也就是说消息报文由一个或多个数据块组成,每个数据块大小以字节为单位(十六进制表示) 衡量,后跟换行符,然后是块内容,最重要的是:整个消息体以大小为0的块结束,也就是说解析遇到0数据块就结束。

相当于我发送请求,包含Content-Length,前端服务器解析后没有问题发送给后端服务器,但是我在请求时后面还包含了Transfer-Encoding,这样后端服务器进行解析便可执行我写在下面的一些命令,这样便可以绕过前端的waf。




走私的四种方法:


CL不为0时

这种情况一般发生在get请求下,当前端允许content-length,后端不允许时,此时后端服务器就不会解析content-length,这样就可能绕过waf。

CL-CL

这种利用的前提条件是服务器不会返回400错误。但是前端服务器按照第一个Content-Length的值对请求进行处理,而后端源站服务器按照第二个Content-Length的值进行处理,这样便有可能引发请求走私。比如出现下面这种情况时:

Content-Length:68
Content-Length:5  


num=1GET /calc.php?num=1 HTTP/1.1


前端先解析第一个cl为68,就会把下面的“num=1GET/calc.php?num=1 HTTP/1.1”都当做请求的内容。但是后端会解析第二个cl,也就是说后端只解析“num=1” 后面的请求体就作为下次请求的请求头(前提是Connection:keep-alive)。这样就会引发走私。

CL-TE

就是当收到存在两个请求头的请求包时,前端代理服务器只处理Content-Length这一请求头,而后端服务器会忽略掉Content-Length,处理Transfer-Encoding这一请求头。

Content-Length:123
Transfer-Encoding: chunked


这里的chunked对请求内容进行分块编码,并且直到有rn的时候才结束。

TE-CL

所谓TE-CL,就是当收到存在两个请求头的请求包时,前端代理服务器处理Transfer-Encoding这一请求头,而后端服务器处理Content-Length请求头。

在calc的题目中:

<?php
error_reporting(0);
if(!isset($_GET['num'])){ 
   show_source(__FILE__);
   }else{ 
          $str =$_GET['num'];        
          $blacklist= [' ', 't', 'r', 'n',''', '"', '`', '[', ']','$','\','^'];        
          foreach($blacklist as $blackitem) {       
                   if(preg_match('/' . $blackitem . '/m', $str)) {         
                                 die("what are you want to do?");               
                           } 
                 }        
                 eval('echo'.$str.';');
}
?>


这里后端对特殊符号做了一些过滤,而且除了这个过滤,还有waf拦截字符串的输入。然后就想利用http走私来绕过。

因为这里是get请求,而content-length是在post才会有用,所以这里跟cl其实关系不大,但是利用起来也不会报错。

这里我最开始就是想用cl和chunked结合起来去绕过。


这里的cl设置多少都无所谓,只要设置了chunked,并且最后由rn那么就能成功执行,如果没有rn那么就会一直waiting。

于是我想着能不能重新构造一个请求头来试试:


这里第一个请求头那一定得是keep-alive,然后设置content-length为5。目的是让tcp能够持续响应,而且这里服务器会因为cl为5只识别num=1,后面的一大串就被安排到了下一轮的请求里。(最后的chunked后面还是得跟两次rn来控制块)


说到这里,感觉这道题其实没怎么利用到http走私,主要还是用分块传输chunked方法来绕过waf。但是毕竟也是通过这个点学习了http走私的知识,所以就记录下来。

如果各位有看到不对的地方,还请斧正!

 

本文作者:星盟安全团队

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/118622.html

Tags:
评论  (0)
快来写下你的想法吧!

星盟安全团队

文章数:31 积分: 75

星盟安全团队---"VENI VIDI VICI"(我来,我见,我征服),我们的征途是星辰大海。从事各类安全研究,专注于知识分享。

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号