HTTP协议
HTTP版本介绍
HTTP 0.9
第一代http协议,已过时,没有协议头,仅支持GET方式,且不支持请求头,所以仅支持纯文本的传输。
HTTP 0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接。由此可见,HTTP协议的无状态特点在其第一个版本0.9中已经成型。一次HTTP 0.9的传输首先要建立一个由客户端到Web服务器的TCP连接,由客户端发起一个请求,然后由Web服务器返回页面内容,然后连接会关闭。如果请求的页面不存在,也不会返回任何错误码。
HTTP 1.0
HTTP协议的第二个版本,第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用。相对于HTTP 0.9 增加了如下主要特性:
- 请求与响应支持头域
- 响应对象以一个响应状态行开始
- 响应对象不只限于超文本
- 开始支持客户端通过POST方法向Web服务器提交数据,支持GET、HEAD、POST方法
- (短连接)每一个请求建立一个TCP连接,请求完成后立马断开连接。这将会导致2个问题:连接无法复用,head of line blocking。连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类请求影响较大。head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞。
HTTP 1.1
HTTP协议的第三个版本是HTTP 1.1,是目前使用最广泛的协议版本 。HTTP 1.1是目前主流的HTTP协议版本,HTTP 1.1引入了许多关键性能优化:keepalive连接,chunked编码传输,字节范围请求,请求流水线等
HTTP 2.0
HTTP 2.0是下一代HTTP协议,目前应用还非常少。主要特点有:
多路复用(二进制分帧)HTTP 2.0最大的特点:不会改动HTTP 的语义,HTTP 方法、状态码、URI 及首部字段,等等这些核心概念上一如往常,却能致力于突破上一代标准的性能限制,改进传输性能,实现低延迟和高吞吐量。而之所以叫2.0,是在于新增的二进制分帧层。在二进制分帧层上, HTTP 2.0 会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码 ,其中HTTP1.x的首部信息会被封装到Headers帧,而我们的request body则封装到Data帧里面。
HTTP 1.1 特性(Keep-Alive&Pipeline&chunked)
正如上面所介绍的,HTTP1.1协议之前,所有的访问都是短连接,客户端每进行一次HTTP请求,就需要同服务器建立一个TCP链接。而现代的Web网站页面是由多种资源组成的,我们要获取一个网页的内容,不仅要请求HTML文档,还有JS、CSS、图片等各种各样的资源,这样如果按照之前的协议设计,就会导致HTTP服务器的负载开销增大。于是在HTTP1.1
中,增加了Keep-Alive
和Pipeline
这两个特性。
Keep-Alive,
在HTTP请求中,会带上一个
Connection: Keep-Alive 的请求头,这代表着,当我完成一次对服务器的HTTP请求,会告诉服务器,不要断开TCP连接,在后续对服务器发起新的HTTP请求时,继续复用该TCP连接,这样只需要进行一次TCP握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。(HTTP1.1协议默认开启该特性)
Pipeline,在Keep-Alive的基础上,请求方客户端不需要在发起一次请求后等待服务器响应,而是可以一直发送请求,
服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端(浏览器默认是不启用Pipeline
的,但是一般的服务器都提供了对Pipleline
的支持)。
chunked,分块传输编码,HTTP1.0协议中,是通过Content-Length 请求头字段来计算 Request body字段,在HTTP1.1中,新增了Transfer-Encoding 请求头,可以通过 Transfer-Encoding: chunked 来代替 Content-Length:number,发送数据,使用方式也很简单,如图,2;FkxpBSG\r\naa
2(16进制)代表还需要读两个字符,读取下一行的aa 2分号后面的是注释语句,无实际作用,数据最后为0,读取0个字符,代表结束,添加两个\r\n代表一次完整的请求结束(Burp插件-chunked)。
HTTP Request Smuggling
上面说了这么多,终于要来到了咱们的漏洞环节,再补充两个小知识点
1. 在发送畸形HTTP请求时,服务器不能识别,会返回400状态码,bad request
2. 而在RFC2616
的第4.4节中,规定:如果收到同时存在Content-Length和Transfer-Encoding这两个请求头的请求包时,在处理的时候必须忽略Content-Length
,这其实也就意味着请求包中同时包含这两个请求头并不算违规,服务器也不需要返回400
错误。当然了,总是会有不遵守的服务器出现:),这样就存在了差异性,导致出现问题。
而