HTTP请求走私(HTTP Request Smuggling)是一种利用前端代理服务器和后端服务器对HTTP请求解析差异来实施攻击的技术,而Transfer-Encoding头部的处理不一致是引发这类漏洞的核心原因之一。简单来说,当攻击者构造一个包含Transfer-Encoding和Content-Length两个头部的畸形请求时,前端代理可能按Content-Length解析,后端服务器却按Transfer-Encoding解析,导致请求被"走私"到下一个请求中,从而绕过安全策略、窃取敏感数据甚至执行未授权操作。解决这个问题的关键在于:统一前后端解析逻辑、禁用或规范化Transfer-Encoding头部、部署具备请求走私检测能力的WAF,以及从代码层面严格校验请求边界。
一、HTTP请求走私的基本原理与Transfer-Encoding的角色
HTTP请求走私的本质是"解析歧义"。在HTTP/1.1协议中,一个请求的结束可以通过两种方式标识:一是Content-Length头部明确告诉服务器请求体有多长;二是Transfer-Encoding: chunked表示请求体以分块编码传输,最后一块大小为0表示结束。当这两个头部同时出现在一个请求中时,不同的服务器实现会选择不同的解析方式。
前端代理(如Nginx、负载均衡器)通常会优先信任Content-Length,而后端应用服务器(如Apache、Tomcat)可能优先处理Transfer-Encoding。攻击者正是利用这种差异,构造如下请求:
POST / HTTP/1.1 Host: target.com Content-Length: 13 Transfer-Encoding: chunked 0 GET /admin HTTP/1.1
在这个例子中,前端代理看到Content-Length为13,认为请求体只有"0\r\n\r\n"这几个字节(共6字节,但实际计算需要精确对齐),处理完后认为请求结束。而后端服务器看到Transfer-Encoding: chunked,会继续读取分块数据,把后面的"GET /admin HTTP/1.1"当作当前请求的一部分或者下一个请求的开始。这样,攻击者就成功地把一个恶意的GET请求"走私"进了系统。
二、Transfer-Encoding处理不一致的具体场景
在实际生产环境中,Transfer-Encoding处理不一致主要出现在以下几种组合场景:
第一种是CL.TE型(Content-Length + Transfer-Encoding同时存在)。前端按CL解析,后端按TE解析。这是最经典也最常见的走私方式,适用于大多数中间件和代理服务器组合。
第二种是TE.CL型(Transfer-Encoding + Content-Length同时存在,但顺序颠倒)。部分服务器会优先处理先出现的头部,导致解析顺序反转,同样产生歧义。
第三种是分块编码混淆。攻击者利用chunked编码中的大小写混写、多余空格、非法字符等方式绕过简单的过滤规则。例如:
Transfer-Encoding: Chunked Transfer-Encoding: chunked Transfer-Encoding: xchunked
某些不够严格的服务器会把"xchunked"这种非法值也当作合法的Transfer-Encoding来处理,从而打开攻击面。
三、请求走私的危害到底有多大
很多人觉得请求走私只是一个理论上的漏洞,实际上它的危害非常直接且严重。首先,攻击者可以绕过前端的访问控制和安全策略,直接访问后端的受保护资源,比如管理后台、API接口等。其次,通过走私请求可以实现会话固定攻击,将受害者的会话绑定到攻击者控制的账号上。再者,在某些配置下,请求走私还能导致缓存投毒,让所有后续用户都访问到被篡改的页面内容。
更危险的是,这种攻击不需要任何认证信息,也不会在传统的日志中留下明显痕迹,因为被走私的请求在前端看来根本不存在。安全团队往往在数据泄露发生后才发现问题,追溯难度极大。
四、从服务器配置层面的防护措施
针对Transfer-Encoding引发的请求走私,最直接的防护手段是从服务器和代理配置入手。以下是具体的操作建议:
对于Nginx作为前端代理的场景,需要确保Nginx版本在1.17.8以上,因为早期版本对Transfer-Encoding的处理存在已知问题。同时在配置中明确禁止或规范化相关头部:
http {
# 禁止客户端发送Transfer-Encoding头部
proxy_http_version 1.1;
proxy_set_header Transfer-Encoding "";
# 或者在server块中限制
if ($http_transfer_encoding) {
return 400;
}
}
对于Apache后端服务器,建议升级到最新稳定版本,并在httpd.conf中设置:
# 禁用Transfer-Encoding的模糊解析 HttpProtocolOptions Strict # 限制请求体大小,减少走私空间 LimitRequestBody 1048576
需要特别注意的是,单纯禁用Transfer-Encoding并不能完全解决问题,因为攻击者还可以通过其他方式(如Content-Length与实际内容不符)实现走私。所以配置层面的防护必须配合其他手段一起使用。
五、应用代码层面的防御策略
从应用开发的角度来看,防御请求走私需要在代码中实现严格的请求校验。核心原则是:永远不要信任前端传来的任何关于请求长度的信息,必须自己计算和验证。
具体做法包括:第一,在应用入口处统一读取请求体,不依赖任何中间件的预解析结果。第二,对Content-Length和Transfer-Encoding同时存在的请求直接拒绝。第三,对chunked编码的请求体进行完整性校验,确保读取到的数据与声明的分块完全一致。
以Java Spring Boot为例,可以通过Filter实现:
@Component
public class SmugglingPreventionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String contentLength = httpRequest.getHeader("Content-Length");
String transferEncoding = httpRequest.getHeader("Transfer-Encoding");
// 同时存在两个头部时直接拒绝
if (contentLength != null && transferEncoding != null) {
((HttpServletResponse) response).sendError(400, "Bad Request");
return;
}
// 对chunked编码进行额外校验
if ("chunked".equalsIgnoreCase(transferEncoding)) {
// 手动读取并验证分块完整性
validateChunkedBody(httpRequest.getInputStream());
}
chain.doFilter(request, response);
}
private void validateChunkedBody(InputStream is) throws IOException {
// 实现分块校验逻辑,确保没有多余数据
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
// 校验每一块的大小声明和实际数据是否匹配
}
}
}
六、WAF与专业安全设备的部署建议
在企业级防护中,部署具备HTTP请求走私检测能力的Web应用防火墙(WAF)是必不可少的。现代WAF产品通常内置了针对CL.TE、TE.CL等经典走私模式的检测规则,能够在流量到达后端之前拦截畸形请求。
选择WAF时需要关注几个关键点:一是是否支持对HTTP/1.1协议解析逻辑的深度检测,而不仅仅是简单的正则匹配;二是是否能够处理编码变体和混淆技术;三是是否提供实时告警和自动阻断功能。此外,定期更新WAF规则库也非常重要,因为新的走私变种不断出现。
七、检测与排查:如何发现自己是否被攻击
排查请求走私漏洞需要主动测试和被动监控相结合。主动测试可以使用专门的工具如Turbo Intruder、HTTP Request Smuggler等,模拟各种走私场景对自己的系统进行检测。被动监控则需要在代理层和应用层同时部署日志审计,重点关注以下异常:
一是Content-Length与实际请求体大小不一致的记录;二是Transfer-Encoding头部出现但请求体不符合chunked格式的情况;三是后端日志中出现了前端不应该转发过来的请求路径或方法。通过对比前后端日志的差异,往往能发现走私攻击的痕迹。
八、总结与最佳实践
HTTP请求走私中Transfer-Encoding处理不一致是一个长期存在且容易被忽视的安全问题。防护的核心思路可以归纳为三点:第一,消除歧义,确保前后端使用完全一致的HTTP解析逻辑;第二,纵深防御,从代理配置、应用代码、WAF设备三个层面同时设防;第三,持续检测,定期进行安全测试和日志审计。没有任何单一措施能百分之百防御请求走私,只有多层防护协同配合,才能将风险降到最低。对于安全从业者来说,理解HTTP协议的解析细节不是可选项,而是必修课。
