A.协议与Web基础1(HTTP请求走私)
最近发现自己的基础特别差恶补一下这边用问答的方式来学习核心问题11、HTTP请求走私CL.TE / TE.CL为什么会产生前端代理和后端服务器的解析差异在哪具体展开(以下均为个人理解查了资料以后自己手写的理解有问题欢迎指正需要搞懂的基本概念前端服务器后端服务器你 客户端浏览器服务员 前端代理比如 Nginx、CDN节点、负载均衡器。你只跟服务员说话。厨师 后端服务器真正处理业务的程序比如 Tomcat、Node.js。你的请求是先给“服务员”服务员再转交给“厨师”。HTTP/1.0和HTTP/1.1去区别HTTP/1.0是每次请求建通道后请求完又把通道拆掉再次请求又需要重新建通道很慢。HTTP/1.1长连接请求后保持一条TCP通道可以连续发多个请求。CL和TE的区别既然建立了长连接那怎么知道第一个请求何时结束第二请求何时开始呢就引入了CL和TE两种方法。方法AContent-Length简称 CL例如请求包中有Content-Length: 13后端就往后读13个字节读完这个请求就结束。方法BTransfer-Encoding: chunked简称 TE简单理解就是每次传输不知道总长度一块一块发每块前面标明这块多大。当我发一个大小为0的块时表示结束。一般格式如下5\r\n (表示下一块有5个字节) Hello\r\n (具体的5个字节) 0\r\n (大小为0表示全部发完了) \r\n (结束的换行符)RFC标准规定如果一个请求同时带了 CL 和 TE应该以 TE 为准忽略 CL。漏洞理解假设“服务员”前端代理和“厨师”后端服务器用的是不同公司写的软件比如前端是 Nginx后端是 Tomcat。如果故意发了一个畸形不规范的请求里面同时包含了 CL 和 TE前端和后端对于请求的大小可能就会产生分歧。详细拆解 CL.TE 和 TE.CL只是前后端的数据大小判断方式不同CL.TE 前端用 Content-Length后端用 Transfer-Encoding。TE.CL 前端用 Transfer-Encoding后端用 Content-Length。可以利用这两种方法构造“幽灵请求”场景一CL.TE前端认CL后端认TE攻击者发送如下原始数据给前端POST / HTTP/1.1 Host: example.com Content-Length: 13 Transfer-Encoding: chunked 0 SMUGGLED前端知道大小是13会全部传给后端但是后端看到0觉得请求已经结束。后面的SMUGGLED后端认为它是下一个新请求的开头 此时如果有正常用户发来了一个请求GET /admin HTTP/1.1...。 后端会把滞留的SMUGGLED和正常用户的请求拼起来变成SMUGGLEDGET /admin HTTP/1.1...从而执行攻击者想要的操作。场景二TE.CL前端认TE后端认CL攻击者构造如下请求POST / HTTP/1.1 Host: example.com Content-Length: 3 Transfer-Encoding: chunked 6\r\n GOTCHA 0\r\n \r\n前端遵守TE知道第一块是6第二块是0可能直接原样转发给后端。也可能会把 chunked 格式去掉重新计算真实长度并加上新的 CL 头后端却忽略TE只看CL只认Content-Length: 3。 后端只读了前3个字节即6\r\n就认为这个请求结束了。会产生这样的情况前端认 TE 读完了整个请求但后端只认 CL 读了一点点就停了剩下的全变成了“幽灵”。前后端解析差异产生的原因畸形 TE 头容错处理不同 黑客故意把Transfer-Encoding: chunked写成奇怪的样子比如Transfer-Encoding: chunked2 多了个2 Transfer-Encoding: CHUNKED 大写 Transfer-Encoding : chunked 冒号前加了空格 Transfer-Encoding: \tchunked 加了制表符有些前端软件比较智能会自动修复规范化这些错误认出它是 TE但有些后端软件也许比较死板一看格式不对直接忽略它退回到使用 CLfallback to CL。这就产生了差异。前端重写 Body 有时候前端代理在转发时会主动把 chunked 编码解开转换成普通的带有 CL 的请求发给后端。如果转换过程中没处理好也会导致两边认知不同。H2.CL 变体HTTP/2 降级HTTP/2 本身是没有 CL 和 TE 这种定界问题的它有自己的帧结构。但是很多架构是客户端到前端用 HTTP/2前端到后端降级成 HTTP/1.1。 前端在把 H2 翻译成 H1 的时候如果不小心带上了错误的 CL 头而后端又信了这个 CL就会产生新的走私漏洞叫 H2.CL。这个我目前还没学会这边先了解一下危害窃取他人请求体黑客把幽灵请求构造为“把数据发到我的服务器”当正常用户访问时用户的密码/Cookie会被拼接到幽灵请求里发给黑客。绕过前端 ACL访问控制前端代理可能拦截了/admin路径但黑客通过走私让后端直接收到/admin请求绕过了前端的防火墙。缓存投毒Cache Poisoning黑客走私一个恶意响应让前端的 CDN 缓存下来导致所有访问该网站的用户都看到黑客伪造的页面。防御前端拒绝歧义请求前端代理如果发现一个请求里既有 CL 又有 TE或者 TE 格式畸形直接返回 400 Bad Request拒绝转发。不要试图去“猜”或“修复”。全链路 HTTP/2 端到端HTTP/2 协议从根本上解决了这个问题使用二进制分帧不需要 CL 和 TE 来定界。如果前端到后端也用 HTTP/2就不会有这种转换导致的差异了。补充概念这边需要区别软件开发中的前后端分离比较维度网络架构如HTTP走私软件开发如前后端分离“前端”指的是什么反向代理服务器、网关、CDN、Nginx用户看到的界面网页、App、Vue/React代码“后端”指的是什么真正处理业务的源站服务器Tomcat等提供数据和逻辑的服务器程序Java/Python/数据库他们怎么交流通过底层的 TCP/HTTP 协议转发字节流通过约定的 API 接口HTTP JSON交换数据常见面试题HTTP走私、负载均衡、跨域配置、缓存穿透前后端分离优缺点、RESTful API、JWT鉴权、跨域(CORS)