首先申明,因为缺时间自己写(看之前的博文),现在发的都是相关知识点,把我认为非常好的文章发给大家共同学习,非软文。
文章来源:科来公众号
科来官网:https://www.colasoft.com.cn/training
文章中使用的软件为科来抓包软件技术交流版(科来官网免费下载),和试用方法和wireshark类似,多了很多小功能。之前也说过,作为客户曾参加科来的网络分析培训,推荐大家试用国产软件,有部分很好的功能:数据包属于哪个进程、哪个应用、矩阵等功能。个人认为分析会话数据流和数据包交互比wireshark更直观,如果是看数据包字段解码更推荐用wireshark。
前言
前面《速通常见应用层协议:从流量视角打开HTTP(中)》,我们在流量分析角度介绍了HTTP协议的概念、原理、发展历程、流量解码和简单的分析方法之后,又讲了两个重要的指标:请求方式和状态码。今天为大家带来短篇系列的第三篇文章,聊聊重要的HTTP首部字段,它们将对我们进行流量分析提供很大的帮助。
本期互动问题,欢迎大家评论区一起聊聊:
应用负载均衡场景中,要关注哪些首部字段?
首部字段的概念
HTTP首部内容,为客户端和服务器分别处理请求和响应提供所需要的信息,一般使用“key:value”的形式进行挪列(如host:colasoft.com.cn)。这里的每一种key,就是我们标题中提到的首部字段,value是字段的取值。
要做好HTTP流量分析,免不了要详细分析HTTP请求和HTTP响应的信息,而这些详细信息就保存在HTTP的首部中。HTTP首部位置如下图所示(HTTP数据包解码,我们在第一篇文章中已经讲过,这里不再赘述):

如图所示,首部字段根据实际用途分为了4种:
(1)通用首部字段(General Header Fields)
请求报文和响应报文都会使用的首部字段。
(2)请求首部报文(Request Headers Fields)
从客户端向服务端发送请求报文时使用的首部字段。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
(3)响应首部字段(Response Header Fields)
从服务器端向客户端返回响应报文时使用的首部字段。补充了响应的附加内容、也会要求客户端附加额外的内容信息。
(4)实体首部字段(Entity Header Fields)
针对请求报文和响应报文的实体部分(上文中首部和报文主体部分)使用的首部字段。补充了资源内容更新时间等与实体相关的信息。
其中http/1.1规范定义了47种首部字段(后来又根据不同协议场景扩展了很多字段)。下面我们就对日常流量分析中常用到的字段作详细讲解。

请求首部字段
(1)host字段
在讲host字段前,先介绍一个重要概念——URL,看下图:

URI统一资源标志符,是一个用于标识某一互联网资源名称的字符串。它又包含了两个子集URL和URN。
-
URL统一资源定位符:是URI的子集,是因特网上标准的资源的地址。
-
URN统一资源名称:也是URI的子集,期望为资源提供持久的、位置无关的标识方式,并允许简单地将多个命名空间映射到单个URN命名空间。
URL和URN本来算孪生兄弟,后来URN基本被遗忘,只剩下URL。
因此要通过HTTP访问服务器上的资源,就必须提供具体的URL!URL的组成如下:

回到HTTP协议本身。HTTP请求中把URL分成了两部分,其中请求行中包括了URL中的协议类型和“资源路径”部分(见上图)。而服务器信息中的host部分,单独列为了一个首部字段(参见上图host位置)。
Host字段可以是主机名称(域名),也可以是IP+端口(为什么不直接列IP地址?因为一个服务器实际可以搭建很多个网站,而用host或不同端口来表示这些不同的网站)。
明确Host字段很重要,例如服务器被控,如果服务器上建有多个网站,找出哪个网站被攻击导致服务器失陷是前提条件,对后面的应急和漏洞修复很重要。
(2)User-Agent字段
代表客服端代理,其实就是客户端安装的浏览器。

流量分析中能够通过这个字段收集内网信息,User-Agent相当于是一种指纹,通过它可以知悉发出HTTP请求的浏览器信息,甚至系统信息,如:

在知晓了这些信息的前提下,就能够知道资产是否存在操作系统版本是否过低、浏览器版本过低的安全风险。
(3)Referer字段
HTTP请求中URI的原始获取方式,简单说就是当前网页是从什么网站跳转过来的。为我们掌握用户访问行为提供了非常大的帮助。

该字段在流量分析中,常用于分析溯源。
(4)Accept字段
指明用户代理(浏览器)可处理的媒体类型。后面的Value值为MIME(Multipurpose Internet Mail Extensions)标准形式,MIME把数据分为了八大类,每个大类下面还有子类,格式为type/subtype。HTTP中常用的有text(文本)、image(图片)、audio/video(音视频)、application(应用)等,比如:application/json。

有时会看到“*”,它是通配符,代表任意类型;还会有一个权重值q,这是期望优先级,最大取值为1,数值越接近1代表期望值越高;
(5)Accept-Charset、Accept-Encoding、Accept-Language字段
Accept-Charset:告知用户代理支持的字符集和相对优先顺序。
Accept-Encoding:告知服务器用户代理支持的内容编码及优先级顺序。
Accept-Language:告知服务器用户代理自然语言集及优先级顺序。
以上字段都可以一次指定多种不同的类型,并用权重值q表示相对优先级。

(6)If-Match字段
这个字段稍微复杂一些,会去比较资源ETag的值(ETag也是一个首部字段)。仅当If-Match字段和ETag值一致时,才会执行请求,反之,会返回状态码412 Precondition Failed(见上篇文章《HTTP请求方式和状态码》)。另外,可以使用“*”为If-Match字段的值,此时服务器会忽略ETag的值,只要资源存在就处理请求。
作流量分析时,这个字段对我们诊断HTTP业务故障会有一定帮助。
(7)其余首部字段
| 首部字段名 | 字段说明 |
| Authorization | Web认证信息 |
| Expect | 期待服务器的特定行为 |
| From | 用户的电子邮箱地址 |
| If-Modified-Since | 比较资源的更新时间 |
| If-None-Match | 比较实体标记(与 If-Match 相反) |
| If-Range | 资源未更新时发送实体 Byte 的范围请求 |
| If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
| Max-Forwards | 最大传输逐跳数 |
| Proxy-Authorization | 代理服务器要求客户端的认证信息 |
| Range | 实体的字节范围请求 |
| TE | 传输编码的优先级 |
响应首部字段
(1)Age字段
这个字段是推算出的,具体算法可以参考RFC7234(RFC2616也有,但RFC7234的方法更科学)。可以简单认为是从资源创建(原始服务器创建资源,而不考虑中间代理服务器存储的时间)到接收到响应的时间。包括了中间网络传输的时间。

(2)ETag字段
ETag是Entity Tag的缩写,是HTTP协议提供的缓存机制中的一种Web缓存验证机制,使缓存变得更加高效,能节省带宽。下面简单描述这种缓存机制:
-
在大多数场景下,当一个URL被请求,Web服务器会返回资源和其相应的ETag值,它会被放置在HTTP响应头的ETag字段中;
-
客户端可以决定是否缓存这个资源和它的ETag;
-
以后,如果客户端想再次请求相同的URL,将会发送一个包含已保存的ETag和If-None-Match字段的请求;
-
客户端请求之后,服务器可能会比较客户端的ETag和当前版本资源的ETag。如果ETag值匹配,这就意味着资源没有改变,服务器便会发送回一个极短的响应,包含HTTP “304 未修改”的状态。304状态码告诉客户端,它的缓存版本是最新的,可以直接使用它。

(3)Location字段
首部字段Location可以将响应接收方,引导至某个与请求URI位置不同的资源上。该字段多会配合3xx:Redirection的响应,提供重定向的URI。几乎所有的浏览器在接收到包含首部字段Location的响应后,都会强制性地尝试对已提示的重定向资源的访问。

(4)Server字段
Server字段包含了HTTP服务器的安装信息。

从流量中可以被动收集对面服务器或主机的信息。
(5)其余响应字段
| 首部字段名 | 字段说明 |
| Accept-Ranges | 是否接受字节范围请求 |
| Proxy-Authenticate | 代理服务器对客户端的认证信息 |
| Retry-After | 对再次发起请求的时机要求 |
| Vary | 代理服务器缓存的管理信息 |
| WWW-Authenticate | 服务器对客户端的认证信息 |
通用首部字段
(1)Cache-Control字段
这是一个缓存控制字段,是前端开发中一个很重要的部分,在首部中显示为Cache-Control:XXXX。它的Value对应的取值很多。从流量分析视角,让大家能理解字段含义就行,不去作缓存的深入讲解,把指令通过表格的方式为大家做一个简单的挪列:
i.缓存请求指令:
| Cache-Control的值 | 说明 |
| no-cache | 强制向原服务器再次验证 |
| no-store | 不缓存请求或响应的任何内容 |
| max-age = [秒] | 响应的最大Age值 |
| max-stale( = [秒]) | 接收已过期的响应 |
| min-fresh = [秒] | 期望在指定的时间内的响应仍有效 |
| no-transform | 代理不可更改媒体类型 |
| only-if-cached | 代理不可更改媒体类型 |
| cache-extension | 新指令标记(token) |
ii.缓存响应指令:
| 指令 | 说明 |
| public | 可向任意方提供响应的缓存 |
| private | 仅向特定用户返回响应 |
| no-cache | 缓存前必需先确认其有效性 |
| no-store | 不缓存请求或响应的任何内容 |
| no-transform | 代理不可更改媒体类型 |
| must-revalidate | 可缓存但必须再向源服务器进行确认 |
| proxy-revalidate | 要求中间缓存服务器对缓存的响应有效性再进行确认 |
| max-age=[秒] | 响应的最大Age值 |
| s-maxage=[秒] | 公共缓存服务器响应的最大Age值 |
| cache-extension | 新指令标记(token) |
特别注意:no-cache并非代表不缓存,而是代表不缓存过期的资源。缓存会向源服务器进行有效期确认后处理资源。no-store才是真正地不进行缓存。
(2)Connection字段
Connection首部字段具备如下两个作用:
-
控制不再转发给代理的首部字段
-
管理持久连接
HTTP/1.1版本的默认连接都是持久连接。因此,客户端会在持久连接上连续发送请求。当服务器端明确想断开连接时,则指定Connection首部字段的值为Close。

(3)Date字段
首部字段Date表明创建HTTP报文的日期和时间。

(4)Pragma字段
Pragma是HTTP/1.1之前版本的历史遗留字段,仅作为与HTTP/1.0的向后兼容而定义。规范定义的形式唯一:Pragma: no-cache。该首部字段属于通用首部字段,但只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。
为什么不直接用上面讲过的Cache-Control: no-cache?主要是为了避免中间有服务器没有使用HTTP/1.1版本,因此常常在请求中会同时存在两个字段:Cache- Control: no-cache和Pragma: no-cache。

(5)Upgrade字段
首部字段Upgrade用于检测HTTP协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。例如微信,抓到包是HTTP包,但指定了用它自己的加密应用层协议mmtls:

使用首部字段Upgrade时,常常会额外指定Connection:Upgrade。
(6)其余通用首部字段
| 首部字段名 | 说明 |
| Trailer | 报文末端的首部一览 |
| Transfer-Encoding | 指定报文主体的传输编码方式 |
| Via | 代理服务器的相关信息 |
| Warning | 错误通知 |
前面请求、响应和通用首部字段都比较好理解,除此之外怎么还有个实体首部字段?大家想想上篇文章中讲解码时,请求有请求实体,响应也有相应的内容(响应实体)。因此,实体首部字段就是专门用来描述这些请求和响应主体部分内容(实体)的。
实体首部字段
(1)Content-Encoding字段
Content-Encoding字段会告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩方式。

(2)Content-Length字段
Content-Length字段表明了实体主体部分的大小(单位是字节)。对实体主体进行内容编码传输时,不能再使用Content-Length首部字段。

(3)Content-Type字段
Content-Type字段说明了实体主体内对象的媒体类型。和首部字段Accept一样,字段值用type/subtype形式赋值(见前文请求首部字段部分)。

(4)Last-Modified字段
首部字段Last-Modified指明资源最终修改的时间。一般来说,这个值就是Request-URI指定资源被修改的时间。但类似使用CGI脚本进行动态数据处理时,该值有可能会变成数据最终修改时的时间。

(5)其它实体首部字段
| 首部字段名 | 说明 |
| Allow | 资源可支持的HTTP方法 |
| Content-Language | 实体主体的自然语言 |
| Content-Location | 替代对应资源的URI |
| Content-MD5 | 实体主体的报文摘要 |
| Content-Range | 实体主体的位置范围 |
| Expires | 实体主体过期的日期时间 |
扩展首部字段
HTTP的首部字段类似上篇文章讲过的状态码,它是可扩展的。因此,我们在进行流量分析时,常常会见到很多前面没有讲过的首部字段。下面将一些分析中会遇到的扩展字段,做讲解:
(1) 带X的首部字段
大家平时分析时,常常会看见一些用X开头的字段。这些字段要么是已经被弃用的字段,要么是某种设备添加的扩展字段。如下图:

在RFC4229和RFC6648中提到,很多字段是“deprecated”,即过时了。但它们仍然会提供很多信息,RFC中也没有说带X的字段是禁用的,只是不推荐。有时这些带X的字段不仅不应该弃用,还会提供极大的便利。因此,要根据具体的场景来决定是否使用X开头的字段。我们也不用去强制记忆它们的功能(服务器和客户端能识别并交流不就行了?)。下面马上介绍用得最多的X开头的字段:X--Forwarded-For、X-Real-IP。
(2) X-Forwarded-For、X-Real-IP、Remote-addr字段
-
X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP。只有在通过HTTP代理或者负载均衡服务器时才会添加该字段(一般需要人为进行配置,设备默认不会自动添加)。这在追踪溯源时由为重要,如果没有该字段,你看到的安全设备告警可能会是:内网服务器一直被负载设备攻击!一般做了SNAT(源地址转换)的设备,将转换前的真实IP写在XFF字段中,让服务器知晓真实的访问IP。

-
X-Real-IP:一般是nginx作反向代理时,使用$remote_addr变量获得用户的真实ip。但X-Real-IP有个问题,就是如果通过cdn访问过来的,那么后面web服务器获取到的是cdn的ip而非真实用户ip。因此,当分析溯源时,XFF比X-Real-IP更优先、更可靠。

-
Remote-addr:类似X-Real-IP,不同的是X-Real-IP可以记录每一跳代理的IP,而Remote-addr记录的是最远端客户的IP。

因此,我们在进行流量分析时(常常是溯源取证),可以按优先级X-Forwarded-For>X-Real-IP>Remote-addr来筛选信息。
(3) HTTP安全字段
-
请求头的安全字段
请求头由客户端发送给服务器,包含有关请求的详细信息,以下是一些关键的安全防护请求头字段:
Referer:该字段指示了当前请求的来源页面(前文已经介绍,此处不再赘述)。
User-Agent:该字段标识了客户端的浏览器类型和版本(前文已经介绍,此处不再赘述)。
Origin:该字段用于跨域请求,指示了请求的源。通过验证Origin字段,服务器可以防止跨站请求伪造(CSRF)攻击。

-
响应头的安全字段
以下是一些关键的安全防护响应头字段:
Content-Security-Policy (CSP):该字段定义了一组策略,限制了页面可以加载的资源类型和来源。通过配置CSP,可以有效防止XSS攻击和数据注入。

Strict-Transport-Security (HSTS):该字段强制客户端在未来的请求中使用HTTPS,从而防止中间人攻击。启用HSTS后,即使用户尝试通过HTTP访问网站,浏览器也会自动重定向到HTTPS。

X-Frame-Options:该字段控制了页面是否可以在iframe中显示。通过设置X-Frame-Options为DENY或SAMEORIGIN,可以防止点击劫持攻击。

X-XSS-Protection:该字段启用了浏览器的XSS过滤器,可以帮助检测和阻止XSS攻击。虽然现代浏览器默认启用了这一功能,但显式设置该字段可以增加安全性。

通过合理配置这些安全防护头字段,可以显著提高HTTP通信的安全性,保护用户数据免受攻击者的威胁。其余的一些安全相关的HTTP首部字段挪列如下:
| 首部字段名 | 说明 |
| X-Content-Type-Options | 用于防止MIME类型嗅探攻击 |
| X-Forwarded-Proto | 确认原始请求的协议类型 |
| Content-Security-Policy-Report-Only | 用于测试和调试CSP策略 |
| Referrer-Policy | 控制Referer字段的值,包括有: no-referrer、no-referrer-when-downgrade、same-origin、strict-origin-when-cross-origin |
| X-Permitted-Cross-Origin-Request-Headers | 用于控制跨域请求中允许的自定义头字段。 |
| X-Content-Security-Policy | 是CSP的一个变体,主要用于兼容旧版浏览器。 |
| Feature-Policy | 用于控制浏览器中的各种功能和API。 |
| Expect-CT | Certificate Transparency,简称CT。是一种确保SSL/TLS证书真实性的技术,通过将证书信息记录在公共日志中,使得任何人都可以验证证书的有效性。 |
| Report-To | 用于收集和报告安全事件。常于CSP及其他安全头部字段共同构建一个全面的安全报告机制。 |
注:在过滤字段时请注意,“Referer”字段是个错别字,单词中的r没有进行双写,却写进RFC成为了事实标准。但“Refferer-Policy”的其他Referer单词都修正了过来。因此,在查找字段(过滤)时,要注意拼写问题。
(4) Set-Cookie字段
Set-Cookie比较常见,因此单独把它列了出来,其实它也是一个HTTP安全首部字段。Set-Cookie是服务器设置客户端cookie信息,以便管理客户端状态。其中的HttpOnly属性是Cookie的扩展功能,它使JavaScript脚本无法获得 Cookie。其主要目的为防止XSS对Cookie的信息窃取。

流量分析举例
例1. 在研究WebShell冰蝎通信时,因为冰蝎使用了加密通信,通信内容无法知晓。而它在通信阶段无强特征进行识别,这时,我们可以通过冰蝎HTTP流量中,会包含的多个首部字段弱特征,进行组合,形成检测规则。当数据流中(传统安全设备只能进行单包检测)匹配中组合的规则,即能进行告警。(本例以冰蝎3举例,旨在提供一种流量检测思路)。
分析:通过对冰蝎3WebShell管理工具的研究,和抓取的流量进行调研,发现HTTP有如下流量特征:
(1)Content-Type: application/octet-stream;
(2)User-Agent,冰蝎3内置了15种,但都比较老旧,可以作弱特征进行判断;
(3)Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2;
(4)Cache-Control: no-cache;
(5)Pragma: no-cache
当同时满足以上5个首部字段弱特征,并后续进行加密流量通信,则进行告警。(还可以添加更多流量特征,如上传动作,访问脚本文件等等,留给读者去发散)。

例2. 某用户被浏览器升级钓鱼网站欺骗,被安装了木马,造成损失。如何确定:用户浏览器版本是否真的过低?它是怎么访问到钓鱼网站的?
分析:(1)过滤出HTTP流量,可以通过User-Agent字段判断用户浏览器版本;


可以看到确实是老旧浏览器,因此用户轻信了钓鱼网站让升级浏览器的话术。
(2)可以通过查看Referer字段来判断用户是否从其他页面跳转到钓鱼页面;
通过Referer字段,可以看到,用户是在浏览www.stmarybahrain.com/new/链接到钓鱼网页的。
结语
从流量角度学习HTTP协议这个短篇系列教程到此就完结了,希望大家通过阅读这三篇文章,对HTTP有了更深入的认识。


1万+

被折叠的 条评论
为什么被折叠?



