为什么一个Http Header中的空格会被骇客利用

摘要:
乍一看可能让很多人迷惑,一个HeaderField名称识别错了为什么会被骇客攻击呢?大不了就缺了一个Header嘛。那么当它们两个同时出现在HttpHeader里时会发生什么呢?实际上Http协议规范有明确定义,当这两种确定长度的Header都存在时,应该优先使用TE,然后忽略CL。使用HTTP/2作为系统间协议,此协议避免了httpheader的混淆。比如Content-Length使用28来表示;`Transfer-Encoding`使用57来表示。

导读:本文通过一个Netty的一个issue来学习什么是"http request smuggling"、它产生的原因与解决方法,从而对http协议有进一步了解。

前言

前阵子在Netty的issue里有人提了一个问题 http request smuggling, cause by obfuscating TE header,描述了一个Netty的http解码器一直以来都存在的问题:没有正确地分割http header field名称,可能导致被骇客利用。

引起问题的那段code很简单,它的作用是从一个字符串中分割出header field-name:

 
for (nameEnd = nameStart; nameEnd < length; nameEnd ++) {
            char ch =sb.charAt(nameEnd);
            if (ch == ':' ||Character.isWhitespace(ch)) {
                break;
            }
 }

这段有什么问题呢?它不应该把空格也当成header field-name的终止符,这会导致Transfer-Encoding[空格]: chunked被解析为Transfer-Encoding而不是Transfer-Encoding[空格]

乍一看可能让很多人迷惑,一个Header Field名称识别错了为什么会被骇客攻击呢?大不了就缺了一个Header嘛。但真实世界,却没这么简单。这事,还得从现代的web服务架构说起。

起因

链式处理

通常现代的Web服务器并非单体存在的,而是由一系列的程序组成(比如nginx -> tomcat),为了实现均衡负载、请求路由、缓存等等功能。这些系统都会解析HTTP协议来进行一系列处理,处理完后,会将对应的请求分发链路中的下一个(往往也是通过HTTP协议)。

假设现在一个用户的请求到达逻辑服务器B的过程为: 用户 -> A -> B 。通常会有许多个用户连接到A,而为了减少连接建立的消耗,A到B的连接数会少很多,A与B之间会保持稳定的长连接,这样能够使性能得到提升。所以可能属于不同客户端的多个请求会共用同一个连接。(以NGINX举例,Nginx从1.1.4开始支持到后端的长连接池,不过在之前是使用的HTTP/1协议与后端通信,即创建连接处理完之后销毁。)

为什么一个Http Header中的空格会被骇客利用第1张

大家的请求都合在一起了,如何区分请求与请求之间的边界呢?接下来我们再来看看Http协议中的Transfer-Encoding: chunkedContent-Length

Transfer-Encoding: chunked和Content-Length

Http协议通过Transfer-Encoding: chunked(以下简称TE)或Content-Length(以下简称CL)来确定entity的长度。

TE表示将数据以一系列分块的形式进行发送,在每一个分块的开头需要添加当前分块的长度,以十六进制的形式表示,后面紧跟着 ' ' ,之后是分块本身,后面也是' ' 。终止块是一个常规的分块,不同之处在于其长度为0。

而CL通过直接指定entity的字节长度来完成同样的使命。

那么当它们两个同时出现在Http Header里时会发生什么呢?实际上Http协议规范有明确定义,当这两种确定长度的Header都存在时,应该优先使用TE,然后忽略CL。

看到这,结合上述那段不规范的header field-name解析代码,或许你想到了一些东西?假如一个包含了TE和CL的Http请求被处理了两次会发生什么?接下来,我们来看看具体的情况。

发送攻击请求

此时我们依旧使用 用户 -> A -> B的例子。这里我们假设B是存在问题的Netty,而A是一个正常的只识别CL的程序。一个包含了Transfer-Encoding[空格]: chunkedContent-Length的Http请求来了

POST / HTTP/1.1

Host: vulnerable-website.com

Content-Length: 8

Transfer-Encoding[空格]: chunked

0

FOR

然后又来了一个正常的用户请求

GET /my-infoHTTP/1.1

Host: vulnerable-website.com

A

A识别到了CL为8,并将这两个请求合并到一个连接中一起传给B

B

B识别到了Transfer-Encoding[空格],按照规则忽略了CL,此时B会怎么分割这两个请求呢:

请求1

POST / HTTP/1.1

Host: vulnerable-website.com

Content-Length: 8

Transfer-Encoding[空格]: chunked

0

请求2

FORGET /my-info HTTP/1.1

Host: vulnerable-website.com

这就糟糕了:服务端报了一个错,正常用户获得了一个400的响应。

为什么一个Http Header中的空格会被骇客利用第2张

(任何上下游识别请求的分界不一致的情况都会出现这样的问题)

如何避免这样的漏洞

  1. 避免重用连接,这样的方式会造成性能的下降。
  2. 使用HTTP/2作为系统间协议,此协议避免了http header的混淆。
  3. 使用同一种服务器作为上下游服务器。
  4. 大家都按规范来,不出BUG。

其中我们展开了解一下为什么HTTP/2可以避免这种情况

HTTP/2不会有含糊不清的Header

HTTP/2是一个二进制协议,致力于避免不必要的网络流量以及提高TCP连接的利用率等等。

它对于常用的Header使用了一个静态字典来压缩。比如Content-Length使用28来表示;`

Transfer-Encoding`使用57来表示。这样一来,各种实现就不会有歧义了。更多的定义详见HTTP/2关于Header静态表的定义

文献

  1. Hypertext Transfer Protocol (HTTP/1.1)关于Http Header Field的解析定义
  2. Transfer-Encoding - HTTP | MDN
  3. Content-Length - HTTP | MDN
  4. What is HTTP request smuggling? Tutorial & Examples
  5. HTTP/1.x 的连接管理 - HTTP | MDN
  6. HTTP/2关于Header静态表的定义
  7. HTTP Keepalive Connections and Web Performance

免责声明:文章转载自《为什么一个Http Header中的空格会被骇客利用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PE444操作系统开发:启用内存分页机制下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Fiddler的详细介绍

Fiddler的详细介绍 一、Fiddler与其他抓包工具的区别 1、Firebug虽然可以抓包,但是对于分析http请求的详细信息,不够强大。模拟http请求的功能也不够,且firebug常常是需要“无刷新修改”,如果刷新了页面,所有的修改都不会保存; 2、Wireshark是通用的抓包工具,能获取HTTP,也能获取HTT...

抓包工具 Fiddler 使用介绍

简介 Fiddler是一个抓包工具,可以将网络传输发送与接收的数据包进行截获、重发、编辑等操作。也可以用来检测流量。原理是以web代理服务器的形式进行工作的,使用的代理地址是:127.0.0.1,端口默认为8888,我们也可以通过设置进行修改。 Fiddler是通过改写HTTP代理,让数据从它那通过,来监控并且截取到数据。在打开它的那一瞬间,它就已经设置好...

LRU缓存及其实现

缓存是我们日常开发中来提高性能最直接的方式,经常会听到有人说:性能不行?是因为你没加缓存!常见的缓存有外部缓存服务以及程序内部缓存,外部缓存服务包括:Redis、Memcached等,内部缓存就是我们可以在程序内使用类似HashMap这种方式来建立缓存,另外比如Web中常见的cdn静态资源缓存等也属于缓存,以及我们计算机中的CPU缓存,文件系统缓存等都不约...

服务器内部模拟Http请求

前言:   在做小程序的开发时需要获取用户的openId用来做唯一标识,来获取对应用户的相关数据   官方的文档说明上有四个必须传的参数   其中appId和appSecret可在自己的微信公众号平台上获取,同时这些也是属于私密信息,应该妥善保管的,因为微信手机客户端是很容易反编译获取到这些信息的,所以在前端的ajax请求将这些参数传到后台是不可取的,最...

HTTP协议--MyWebServer

HTTP协议 HTTP协议是一种Web通信协议,通过特定的规则来实现服务器跟客户端的通信。HTTP协议有这样几个特点: (1)面向无连接的,一次只能处理一个请求,HTTP1.0服务器解析完客户端请求并作出应答后,会关闭连接;对于HTTP1.1应答后会等待一个非常短的时间,如果这段时间没有新请求,就会关闭连接。 (2)HTTP协议是无状态的,即对处理过的事务...

浏览器访问网页的详细内部过程(转)

我们来看当我们在浏览器输入http://www.mytest.com:81/mytest/index.html,幕后所发生的一切。 首先http是一个应用层的协议,在这个层的协议,只是一种通讯规范,也就是因为双方要进行通讯,大家要事先约定一个规范。 1.连接 当我们输入这样一个请求时,首先要建立一个socket连接,因为socket是通过ip和端口建立的,...