从流量视角打开HTTP(中)

前言

前一篇文章《从流量视角打开HTTP(上)》中我们从流量分析角度出发,介绍了HTTP协议的概念、原理、发展历程、流量解码和简单的分析方法。今天为大家带来本系列的第二篇,深入聊聊HTTP请求方式和状态码的意义。

本期互动问题:

1.GET和POST方法都可以请求资源,它们的不同之处在哪儿?

2.有人进行密码爆破时,为什么会在HTTP日志中会看到大量的“302”响应码?如何判断有没有被爆破成功?

  一、HTTP请求方式  

上篇文章,在HTTP请求解码的部分,我们讲到HTTP的请求由四部分构成,其中第一部分为:请求行。请求行又由请求方法、URL和HTTP协议版本组成,如下图:

所谓请求方法,很好理解:HTTP是基于C/S架构(客户点/服务器),客户端想要对服务器端进行什么操作,就需要在HTTP请求中指明,如:对服务器某资源进行“增、删、查、改”等。我们捕获的任意HTTP会话数据包中,最常见的请求方法就是GET和POST,那到底有多少种请求方法呢?它们分别是什么作用呢?我们了解这些请求方法后,对流量分析技术有什么帮助吗?不用着急,下面我们慢慢道来:

先看一张图:

上篇文章中,我们知道HTTP从发展至今经历了版本迭代,定义HTTP的RFC文档也有多个,因此HTTP的请求方法也不是一天形成的!

如上图所示:

  • 最早,RFC1945中规定的方法只有三种:GET、HEAD、POST;
  • RFC2616在此基础上补充了:PUT、DELETE、TRACE、CONNECT、OPTIONS;提到了PATCH、LINK和UNLINK但没有具体实现(记载于RFC2068);
  • 后面陆续扩展方法至15种,包括:PATCH、LINK、UNLINK、MOVE、COPY、WRAPPED、Extension-mothed(另外增加方法的统称);
  • 对于第15种方法Extension-mothed,在基于HTTP的其他协议可以扩展HTTP请求方法,如WebDAV(一种基于 HTTP 1.1协议的通信协议),又扩展定义了MKCOL、PROPFIND、PROPPATCH、LOCK、UNLOCK等方法。

这些请求方法的实际作用,其实就是对服务器的各种操作。理解了请求方法,我们在进行流量分析时,才能知道当前分析的HTTP会话,客户到底在做什么?是否规范?是否安全?

下面我们对这些请求方法作详细介绍:

1.GET

在HTTP流量中最常见的便是GET请求方法:

GET是HTTP中最古老、最经典的方法,一直沿用至今。GET的含义就是从服务器获取资源,这个资源既可以是静态的文本、页面、图片、视频等媒体资源,也可以是由后端语言比如PHP、JAVA等动态生成的各种类型数据。

在规范中有阐述,GET还可以分为两个类型:conditional GET 和 partial GET——

Conditional GET:当GET请求与If-Modified-Since字段配合使用,就变成了conditional GET,仅当资源被修改的时候才会执行GET操作。(关于常用首部字段,将在下一篇文章中详细讲解);

partial GET:是GET和Range字段一起使用的情况下产生的,只会返回整体数据的一部分;

做类型区分,主要是为了节省资源。

可能大家有所了解,GET能做得事情, POST也能做,而且POST好像还更好?其实不是这么回事,在前端实现时,相对POST方法,GET有它自身的特点,如:

  • GET请求可以被浏览器收藏(浏览器收藏夹的支持),POST请求不行;
  • GET在浏览器回退时是无害的,而POST会再次提交请求;
  • GET请求会被浏览器主动缓存,而POST不会(可手动设置);

‌GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

可以看到,协议虽然是一种规定,但它始终是为用户服务的,不能简单地说POST更好,可以替换掉GET。

需要注意的是,如果是通过GET向服务器传递数据,数据通常会在URL中,仅仅通过URL编码,相对来说不是太安全。(GET其实支持通过请求主体来提交数据,但部分浏览器和服务器不支持这样做)

2.POST

在最早的RFC定义中,GET是客户端向服务器请求数据,而POST用于客户端向服务器传输数据。现在两种请求方法的功能大面积重合,有细小区别,一般在前端开发时,根据具体场景和约定来决定用POST还是用GET方法。

相对于GET,POST有一些显著的优点,如:

GET传递数据是放在URL里面,URL有长度限制,默认为2048个字节(部分浏览器只支持512字节),而POST是将数据放在请求主体中,理论上没有长度限制。因此一般提交数据,都会采用POST请求方法。(后文分析举例会用到该特性)。

3.HEAD

HEAD方法与GET请求方法是完全相同的,也是从服务器获取资源,服务器的处理机制也与GET一样。不同的是服务器在响应时,只传回状态行和消息报头,不会返回“响应正文”。

HEAD常用于测试功能,如测试下载功能,我只想知道服务器资源是否存在,而不需要真正把资源下载回来,这时使用HEAD就能避免资源浪费。如下图,使用HEAD请求一个zip压缩包,通过相应码200OK(后文会讲解),我们知道请求是成功的,但服务器并没有把zip文件传递给请求端。

4.PUT

PUT方法是对服务器资源进行“修改”。和POST有一点点类似,不过POST是对服务器“新增”资源,而且PUT方法必须指定资源在服务器上的具体存放位置。

一般来说,PUT对客户端是禁用的。TOMCAT有个很出名的任意文件写入漏洞(CVE-2017-12615:Tomcat配置文件/conf/web.xml 配置了可写(readonly=false),导致我们可以往服务器写文件)就涉及到了PUT,如下图:

5.DELETE

DELETE方法是删除服务器资源。本方法危险系数比较大,因此服务器一般会禁用或忽略该方法。也有例外,Amazon的S3云服务里面,就用DELETE方法来删除资源。

6.TRACE

TRACE方法本来是让服务器响应时显示请求-响应的路径,用于对HTTP请求链路的测试和诊断。设计出发点是好的,但存在漏洞(会泄漏网站的信息),所以会被服务器拒绝。

7.CONNECT

CONNECT方法使用得很少,也很特殊。它要求服务器为客户端和另外一台服务器建立一条通道,一般是SSL或TLS加密通道。此时被请求的服务器就充当了代理的角色。

8.OPTIONS

OPTIONS方法要求服务器列出可对该资源使用的方法列表(如服务器支持:GET、POST、HEAD等),会在响应头的Allow字段中返回。一般用于测试,正常生产环境中,会对客户端禁用,以防止非法探测行为。

9.PATCH

PATCH方法算是PUT方法的一种扩展,用于对服务器上的资源进行部分更新,一般禁止客户端使用。

10. 其他请求方法

其他方法一般很少使用或是HTTP扩展协议(如WebDAV)中使用,见下表:

序号请求方法描述
1MOVE请求服务器将指定的页面移至另一个网络地址
2COPY请求服务器将指定的页面拷贝至另一个网络地址
3LINK请求服务器建立链接关系
4UNLINK断开链接关系
5WRAPPED允许客户端发送经过封装的请求
6PROPFIND对资源进行检索
7PROPPATCH对资源设置属性
8MKCOL创建合集
9LOCK改写保护
10UNLOCK无写保护
………………

以上便是大家在作流量分析时可能会遇到的一些HTTP请求方法。HTTP协议灵活且易扩展,理论上来说,只要和服务器做好了约定,便可以随意扩展更多的HTTP方法!比如,官方在愚人节时曾出了个HTCPCP协议(超文本咖啡壶协议),还有专门的RFC文档(RFC2324),有一个BREW请求方法,它的作用是煮咖啡……因此,只要服务器支持,这些方法是可以灵活扩展的!

延伸学习:安全与幂等的概念

在RFC2616中,介绍每种请求方法时,都反复提到了两个概念:安全与幂等。

“安全”:是指请求方法会不会破坏服务器上原有的资源。从这个角度出发,GET和HEAD等方法就是安全的,而POST、PUT、DELETE则是不安全的(注意,这里的“安全”是从服务器角度出发的,区别前面我们说的“客户提交用户名密码的场景”中,通过POST提交更安全)。

“幂等”:指多次执行相同的请求方法,每次返回的结果都是相同的。(多次执行,返回不同结果,就称为非幂等)。例如GET、HEAD、DELETE、PUT则是幂等的,POST则不是幂等的。

理解“安全”与“幂等”可以加深我们对请求方法的理解。当然这两个概念更多和前端开发相关,对流量分析来说,了解多一些也非坏事。

  二、HTTP状态码  

客户端使用各种请求方法发出了请求,服务器收到请求后,会解析请求(HTTP请求里面的内容不就是客户端想和服务器协商的吗?)。服务器根据请求方法、资源路径、请求头部信息等,决定如何响应客户端,在HTTP响应的最前面就显示出结果,这就是“状态码”。

状态码很多,有很多网站把所有状态码做成了表格供大家查阅。本文中,我们先对状态码做统筹介绍,再把各类型常见的状态码作举例。

RFC1945及RFC2616把状态码分为了5类,从100~599(RFC 2518、RFC 2817、RFC 2295、RFC 2774 、 RFC 4918陆续进行了扩充)。这五类状态码的具体含义如下表:

状态码类别状态码描述
1XX指示信息状态码(Informational)接收的请求正在处理
2XX成功状态码(Success)请求正常处理完毕
3XX重定向状态码(Redirection)需要进行附加操作以完成请求
4XX客户端错误状态码(Client Error)客户端的请求有误或请求无法实现
5XX服务器错误状态码(Server Error)服务器处理请求出错

接下来我们一起看看在流量中常见的状态码。

1.   状态码1XX

实际遇到得比较少,下面进行简单举例:

(1)状态码:100 Continue

表示请求者应当继续提出请求。如下图:

服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。后续继续提交数据,如下图:

服务器收到完整数据后,响应“200 OK”。

(2)状态码101 Switching

切换协议,需要配合首部字段Upgrade,在HTTP协议基础上改成其他协议继续通信,比如WebSocket。如果服务器同意变更,就会发送状态码101,之后数据传输就会使用变更后的协议了。如下图:

除了上面2种常见的1开头状态码,另外还有102 Processing。它是WebDAV扩展的,当WebDAV请求可能包含许多涉及文件操作的子请求,需要很长时间才能完成请求。该代码表示服务器已经收到并正在处理请求,但无响应可用。

2.   状态码2XX

2开头的状态码表示请求成功,RFC1945定义了200 OK、201 Created、202 Accept和204 No Content这4种;RFC2616进行了扩展:203 Non-Authoritative Information、205 Reset Content、206 Partial Content等等,下面就常见的进行举例:

(1)状态码200 OK

这是最常见的状态码,表示服务器成功收到了客户端发送的消息,并且成功处理了客户端的请求,返回了客户端想要的数据。

(2)状态码204 No Content

与200的含义基本上一模一样的,区别是,204不会返回body。

(3)状态码206 Partial Content

状态码206表示部分传输,是HTTP分块传输或者断点续传的基础,当客户端发送“范围请求”、要求获取整体资源的部分数据时会出现。通常会伴随着首部字段“Content-Range”头字段,表示响应报文里数据的具体范围。

其余2XX状态码不太常见,这里用表格列出,供大家参考:

状态码描述
201 Created请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其URI已经随Location头信息返回。
202 Accepted服务器已接受请求,但尚未处理。最终该请求可能会也可能不会被执行,并且可能在处理发生时被禁止。
203 Non-Authoritative Information服务器是一个转换代理服务器,以200 OK状态码为起源,但回应了原始响应的修改版本。
205 Reset Content服务器成功处理了请求,但没有返回任何内容。与204响应不同,此响应要求请求者重置文档视图。
207 Multi-Status代表之后的消息体将是一个XML消息,并且可能依照之前子请求数量的不同,包含一系列独立的响应代码。
208 Already ReportedDAV绑定的成员已经在(多状态)响应之前的部分被列举,且未被再次包含。
226 IM Used服务器已经满足了对资源的请求,对实体请求的一个或多个实体操作的结果表示。

3.   状态码3XX

3开头的状态码的含义是重定向。例如以前的资源找不到了,得向新的地址重新发送请求。3xx的状态码一共也有八个,其中废弃了一个306,所以只剩下7个了。其中重要的如301 Moved Permanently、302 Found(Moved Temporarily)、304 Not Modified等;不太重要的,如300 Multiple Choices、303 See Other、305 Use Proxy 、307 Temporary Redirect等:

(1)状态码301 Moved Permanently

301指永久重定向,访问的资源已经不存在了,需要通过Location头字段指明后续要跳转到的URI。比如,京东以前的网址为:www.360buy.com,后来域名改为了www.jd.com。但如果我们访问www.360buy.com仍然可以打开京东的官网,就是做了永久性重定向到www.jd.com的缘故。在流量分析中能看到的状态码301举例如下图:

(2)状态码302 Found(Moved Temporarily)

状态码302和301都会跳转到新的Location地址,但302是临时的。比如网站资源位置发生了永久性的变动,或者从http升级到了https协议,但不能直接删除原来的地址,因为老客户还要用,为了可以直接使用新的https,需要把请求到旧的地址的请求重定向到新的地址。另外还有一种场景,就是在使用用户名和密码进行登陆时,如果输入错误,会跳转到一个指定的页面,这时,通常也是使用302进行跳转。

(3)状态码304 Not Modified

状态码304,主要用于缓存控制,配合字段If-Modified-Since等条件。如果没有超过时效,就调用缓存资源,如果过了时效,就跳过缓存访问服务器资源。

其余3XX状态码不太常见,这里用表格列出,供大家参考:

状态码描述
300 Multiple Choices被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。
303 See Other对应当前请求的响应可以在另一个URI上被找到,当响应于POST(或PUT / DELETE)接收到响应时,客户端应该假定服务器已经收到数据,并且应该使用单独的GET消息发出重定向。
305 Use Proxy被请求的资源必须通过指定的代理才能被访问。Location域中将给出指定的代理所在的URI信息,接收者需要重复发送一个单独的请求,通过这个代理才能访问相应资源。
307 Temporary Redirect请求应该与另一个URI重复,但后续的请求应仍使用原始的URI。与302相反,当重新发出原始请求时,不允许更改请求方法。
308 Permanent Redirect请求和所有将来的请求应该使用另一个URI重复。 307和308重复302和301的行为,但不允许HTTP方法更改。

4.   状态码4XX

4开头的状态码意味着客户端请求错误,整个4xx下的状态码有18个之多,我们仍然用常见的进行举例。

(1)状态码400 Bad Request

状态码400代表服务器无法理解这次请求。但是具体是什么错误,并没有详细准确的说明,只是告诉你错了,但是却不告诉你哪里错了……所以,在实践应用开发中,尽可能不要出现400这个状态码,除非是有意为之(如干扰攻击者判断,让安装设备故意回复400)

(2)状态码403 Forbidden

403实际是服务器拒绝了对该资源的访问,至于原因,一般不会详细说明。

(3)状态码404 Not Found

这个状态码可能是大家除了200 OK外遇到最多的。它的本意是资源不存在,无法在服务器上找到,所以无法返回给客户端。在实践中,经常是客户端请求有问题,就统一回复404……比如下图中去访问robots.txt文件,并非服务器没有这个文件,而是拒绝访问。

其余4XX状态码不太常见,这里用表格列出,供大家参考:

状态码描述
401 Unauthorized表示当前请求需要用户验证。该响应必须包含一个适用于被请求资源的WWW-Authenticate信息头用以询问用户信息。
402 Payment Required该状态码最初的意图可能被用作某种形式的数字现金或在线支付方案的一部分,但几乎没有哪家服务商使用。
405 Method Not Allowed请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个Allow头信息用以表示出当前资源能够接受的请求方法的列表。
406 Not Acceptable请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体,该请求不可接受。
407 Proxy Authentication Required与401响应类似,只不过客户端必须在代理服务器上进行身份验证。
408 Request Timeout请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送,客户端可以随时再次提交这一请求而无需进行任何更改。
409 Conflict表示因为请求存在冲突无法处理该请求,例如多个同步更新之间的编辑冲突。
410 Gone表示所请求的资源不再可用。
411 Length Required服务器拒绝在没有定义Content-Length头的情况下接受请求。
412 Precondition Failed服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个。
413 Request Entity Too Large表示服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围。
414 Request-URI Too Long表示请求的URI长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。
415 Unsupported Media Type对于当前请求的方法和所请求的资源,请求中提交的互联网媒体类型并不是服务器中所支持的格式。
416 Requested Range Not Satisfiable客户端已经要求文件的一部分(Byte serving),但服务器不能提供该部分。
417 Expectation Failed在请求头Expect中指定的预期内容无法被服务器满足,或者这个服务器是一个代理服显的证据证明在当前路由的下一个节点上,Expect的内容无法被满足。
420 Enhance Your CaimTwitter Search与Trends API在客户端被限速的情况下返回。
421 Misdirected Request该请求针对的是无法产生响应的服务器(例如因为连接重用)。
422 Unprocessable Entity请求格式正确,但是由于含有语义错误,无法响应。
423 Locked当前资源被锁定。
424 Failed Dependency由于之前的某个请求发生的错误,导致当前请求失败,例如PROPPATCH。
425 Unordered Collection在WebDAV Advanced Collections Protocol中定义。
426 Upgrade Required客户端应当切换到TLS/1.0,并在HTTP/1.1 Upgrade header中给出。
428 Precondition Required原服务器要求该请求满足一定条件。
429 Too Many Requests用户在给定的时间内发送了太多的请求。旨在用于网络限速。
431 Request Header Fields Too Large服务器不愿处理请求,因为一个或多个头字段过大。
444 No ResponseNginx上HTTP服务器扩展。服务器不向客户端返回任何信息,并关闭连接(有助于阻止恶意软件)。
450 Blocked by Windows Parental  Controls这是一个由Windows家庭控制(Microsoft)HTTP阻止的450状态代码的示例,用于信息和测试。
451 Unavailable For Legal Reasons该访问因法律的要求而被拒绝,由IETF在2015核准后新增加。
494 Request Header Too Large在错误代码431提出之前Nginx上使用的扩展HTTP代码。

5.   状态码5XX

5开头的状态码,指服务器出现错误,意味着客户端的请求没有问题,但服务器在处理请求时内部发生了错误,无法返回应有的响应数据。

(1)状态码500 Internal Server Error

服务器错误,跟400类似,也是一个通用的服务器错误状态码。500的状态码可以有效的避免服务器泄漏可能的隐私信息(比如漏洞探测时,如果回复503等状态码时,就会泄露部分信息)。

(2)状态码503 Service Unavailable

503是一个临时的状态,表示服务器当前正忙,暂时无法响应服务。可以通过Retry-After字段告知在多久后再次尝试。

其余5XX状态码不太常见,这里用表格列出,供大家参考:

状态码描述
501 Not Implemented服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求。
502 Bad Gateway作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
504 Gateway Timeout为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。
505 HTTP Version Not Supported服务器不支持,或者拒绝支持在请求中使用的HTTP版本。
506 Variant Also Negotiates由《透明内容协商协议》(RFC 2295)扩展,代表服务器存在内部配置错误。
507 Insufficient Storage服务器无法存储完成请求所必须的内容。这个状况被认为是临时的。
508 Loop Detected服务器在处理请求时陷入死循环。
510 Not Extended获取资源所需要的策略并没有被满足。
511 Network Authentication Required客户端需要进行身份验证才能获得网络访问权限,旨在限制用户群访问特定网络。

  三、分析举例  

例1:在演练行动中,客户内网全部为HTTP明文流量(已卸载SSL层),想找到有没有被成功上传Webshell的会话,方便应急处理,封禁上传点。

分析

1.   上传Webshell,则HTTP的请求方法应该为POST(已禁用PUT方法);

2.   上传成功,则响应码应为“200 OK”;

还可以进一步添加条件,如:请求文件类型为脚本文件、上传文件大小大于500Kb等。

过滤后效果如下:

这样我们就找到了Webshell的上传点,经研判Webshell上传成功并已经有通信行为后,立即开展应急响应。

例2:发现对某系统的密码爆破行为,并研判密码爆破是否成功。

分析:某系统登录成功时会返回“200 OK”,若登录信息不正确时,会跳转到“用户名密码不正确”的页面,返回状态码“302”。

如下图,在“xxxx.login”页面,可以看到大量尝试登陆的会话,正是“密码爆破”行为。通过响应码过滤,发现全是“302”,无“200 OK”的状态码,说明并未爆破成功。

  结语  

为了方便我们对Web业务进行服务保障、安全保障,掌握HTTP协议,成为我们的一项基础技能。在HTTP协议中,请求方式和状态码又是两项非常重要的指标,通过本篇文章,我们从流量角度对它们进行了深入的介绍。希望本文对大家今后工作能有所帮助,下篇文章,我们继续讲解HTTP的首部字段,敬请期待!