ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

响应被压缩过了:内容编码的协商与还原

响应被压缩过了:内容编码的协商与还原 授权与合规声明本文全部操作对象均为自建隔离靶场本机容器或隔离虚拟机涉及安全测试的环节必须以取得合法授权为前提。未经授权的渗透测试违反《中华人民共和国网络安全法》与《刑法》相关条款须承担相应法律责任。本文只讲环境配置、版本对照与靶场隔离不含任何攻击步骤、利用载荷与绕过手法请勿将文中环境指向任何非自有系统。一、现象同一个地址换个客户端这个头就不见了1.1 三个初学者真的会遇到的画面画面一同一个地址换个客户端那个头不见了。抓包工具里某个响应清楚写着Content-Encoding: gzip换一个客户端——命令行工具、另一个浏览器、某个程序自带的网络面板——请求同一地址同一个头却没有了看上去时有时无。画面二同一个页面里有的请求带它、有的不带。翻一整个页面的请求列表有些响应带Content-Encoding有些干干净净。画面三抓包工具里内容那一栏一会儿是原文、一会儿提示要解码。同一个工具、同一个页面有的响应体你看得懂有的它却提示需要先解压。1.2 这不是服务器时好时坏而是两端在协商最省事的解释是服务器不稳定但它站不住。真正的答案是Content-Encoding出现与否从来不是单方面能决定的事。它要成立得一端愿意收这种编码另一端才会用这种编码。这两件事分别落在两个头字段上一个写在请求里一个写在响应里。三个画面于是都通了。变的不是服务器而是客户端的另一半——它说的那句话不一样了。其中画面三属另一层工具把内容显示成什么样是工具自己的事这一点标为待验证BX01因为各工具的显示形态与开关名本文未核到官方文档级口径。1.3 先划清一条边界这里说的不是字符编码字符编码管的是字符怎么变成字节——一个字对应哪几个字节。内容编码管的是字节怎么被压缩——已经是一串字节了为了少占地方用某种算法把它变换得更短。前者讨论字符与字节的对应关系后者讨论字节序列本身的变换。本文只讲后一件。⚠️代码待验证# 本文未实测只看响应头不看响应体# 把地址换成本机自建靶场即可不要指向任何非自有系统curl-Ihttp://127.0.0.1:8080/index.html# 观察输出里有没有 Content-Encoding 这一行以及它是哪一个值本章可以带走的一句Content-Encoding出现与否是两端协商的结果不是服务器单方面决定的。二、两个字段各管一半一个在请求里一个在响应里2.1Accept-Encoding请求里那句我能接受什么规范对Accept-Encoding给了两个方向的定位很多人第一次看会漏掉E12。第一个方向用户代理在请求中发送Accept-Encoding时表示的是响应中可接受的 content coding。白话就是——这句话由客户端说“我这边能接受哪些编码”是一句意向声明不是事实陈述。第二个方向服务器在响应中发送它时提供的是对该资源的后续请求内容中首选哪些 content coding的信息E12。关键词是后续请求——描述的是下一次该用什么不是这一次的响应用了什么。同一个字段名出现在两个方向上说的却是两件事。所以看到头字段先看的不是它什么意思而是它出现在哪个方向上。2.2Content-Encoding响应里那句我用了什么Content-Encoding指示哪些 content coding 已经被施加到表示上媒体类型固有编码之外的那部分以及为得到Content-Type所指媒体类型的数据需要施加哪些解码机制E01。规范的例子很直白Content-Encoding: gzipE02。它是一句事实陈述不是我能接受什么而是我已经用了什么你按这个还原。配套还有一条硬规则若一个或多个编码已被施加施加编码的发送方 MUST 生成Content-Encoding头字段并按施加顺序列出这些 content codingE03。所以它不是可选装饰——只要真的施加了编码就必须写。2.3 一句话对照想回答的问题字段出现在哪一侧谁在说说的是什么我方这边能接受哪些编码Accept-Encoding请求里用户代理响应中可接受的 content codingE12后续请求首选哪些编码Accept-Encoding响应里服务器对该资源后续请求内容的首选编码信息E12这一次实际用了哪些编码Content-Encoding响应里施加编码的发送方已施加的 content coding以及还原所需的解码机制E01这张表想说一句话一个字段管意向一个字段管事实意向那一半由客户端说事实那一半由施加方说。所以谁决定要不要压缩这个问法不够准——准确的说法是客户端先划出范围施加方在范围内选择并如实报告。⚠️代码待验证# 本文未实测在请求里显式声明我能接受哪些编码# 这一句是客户端说的属于意向声明不是事实curl-HAccept-Encoding: gzip, deflatehttp://127.0.0.1:8080/index.html# 换成别的客户端、别的取值再请求同一地址观察响应头里的 Content-Encoding 是否随之改变本章可以带走的一句Accept-Encoding说我能收什么Content-Encoding说我用了什么前者管意向、后者管事实两句都在才算协商。三、表示与消息是两个层面3.1 内容编码是表示的属性规范有一句逐字的对照值得原样抄下来E05Unlike Transfer-Encoding (Section 6.1 of [HTTP/1.1]), the codings listed in Content-Encodingare a characteristic of the representation; the representation is defined in terms of the coded form, and all other metadata about the representation is about the coded form unless otherwise noted.白话就是Content-Encoding里列出的编码是表示本身的属性。规范接着说它是以编码后的形式被定义的除非另有说明关于它的其它所有元数据说的也都是编码后的那一份。这解释了为什么它通常只在渲染前才被解码E05这份表示被定义的那一刻它就是压缩后的样子。顺便提一句邻居传输编码那一层讲的是消息的属性不是表示的属性——这正是 E05 那句 “Unlike Transfer-Encoding” 的落脚点。那一层另有专文本文不重写。3.2 媒体类型自带的编码不重复声明规范写明若媒体类型本身含固有编码比如一种总是压缩的数据格式那么即使算法与某个 content coding 相同也不会在Content-Encoding里被重复声明E06只有它以某种奇怪的理由被第二次施加形成这份表示时才会列出E06。它意味着Content-Encoding里的编码指的是在媒体类型之外额外加上的那一层。所以看到某个响应没有Content-Encoding不能立刻断定它没被压缩过——有可能它本来就是压缩格式压缩被算在媒体类型里了。3.3identity为什么不该出现在Content-Encoding里identity被用作无编码的同义词表达不偏好任何编码E13。规范明确名为identity的编码是为它在Accept-Encoding中的特殊作用而保留的因此SHOULD NOT出现在Content-Encoding中E04。注意这里用的是SHOULD NOT不是必须不——规范给的是应当遵守的规则不要把 SHOULD NOT 读成必须不能。道理好懂identity的含义是没有编码。既然Content-Encoding报告的是施加了哪些编码没有编码本身没什么可报告。在Accept-Encoding里它是有效选项在Content-Encoding里它是多余的。要判断的事结论依据Content-Encoding里的编码附着在谁身上附着在表示上表示以编码后的形式被定义E05表示被解码的时机通常只在渲染前才解码E05媒体类型自带的编码要不要重复声明不重复声明只有被第二次施加时才列出E06identity能不能出现在Content-Encoding里SHOULD NOT出现它为Accept-Encoding的特殊作用保留E04identity的含义“无编码的同义词表达不偏好任何编码”E13本章可以带走的一句内容编码属于表示这一层指的是媒体类型之外额外施加的那一层identity是给Accept-Encoding用的记号不该写进Content-Encoding。四、谁能接受什么是甲方说的三条判定规则4.1 语法编码名、“identity”、星号与质量值客户端那句话怎么写规范给了完整语法E14Accept-Encoding #( codings [ weight ] )其中codings content-coding / identity / *。三个要点。第一每个值 MAY 带一个关联的质量值weight表示对该编码的偏好——是MAY即可以带不是必须带。第二星号*匹配任何未在该字段里被显式列出的可用 content codingE14相当于一句其余的按这个办。第三identity也是合法取值之一含义回到第三章那句无编码。4.2 服务器判断可接受的三条规则情形判定结果请求里没有Accept-Encoding头字段任何content coding 都视为用户代理可接受表示本身没有content coding默认可接受除非被identity;q0或*;q0明确排除且没有更具体的 identity 条目表示的 content coding出现在Accept-Encoding列表里可接受除非它附带的 qvalue 为0qvalue 为 0 意为不可接受最反直觉的是第一行不说话等于什么都接受。请求里压根没有这个头时规范把任何编码都当成用户代理可接受的E15。第三行则解释了质量值为 0 的特殊含义一个编码出现在列表里并不自动等于可接受只有附带 qvalue 为 0 时它才是明确被拒绝的E15。4.3 空值、一个都不可接受时怎么办还有一个特例一个空的Accept-Encoding字段值意味着用户代理不想要任何 content codingE16。这一条和 4.2 表第一行正好相反——那是没有这个字段这是有这个字段但值是空的。两者看起来都像客户端没说什么含义却掉了个头一定要分开记。收尾规则是若请求中存在非空的Accept-Encoding而响应没有任何可用表示的 content coding 被列为可接受源服务器 SHOULD 发送不带任何 content coding 的响应——除非 identity 编码被指示为不可接受E17。两处值得停一下。第一用的词是SHOULD即应当不是必须。第二它给了兜底方向谈不拢时默认退回到不压缩只有当连不编码这条路都被客户端明确堵死identity 被指示为不可接受时才需另想办法。⚠️代码待验证# 本文未实测把 Accept-Encoding 显式置为空值# 注意这一句和完全不发这个头是两件不同的事E15 第一行 / E16curl-HAccept-Encoding:http://127.0.0.1:8080/index.html# 再把 -H 整行删掉发一次对比两次的响应头差异本章可以带走的一句不说话等于全都接受空值等于什么都不要标了 0 才是明确拒绝谈不拢时规范让服务器退回到不编码。五、具体有哪几种编码5.1 content coding 值的通用性质规范写明content coding 值表示已施加、或可施加于表示的编码变换主要用于压缩或作其它有用变换并且不丢失底层媒体类型的身份、不丢信息同时所有 content coding 都是大小写不敏感的E08。两个信息量很大的点。第一它说的是已施加或可施加——同一个名字既用来报告我用了它也用来表示我可以用它是哪一种看它出现在哪个字段里。第二不丢信息、不丢媒体类型身份是它和加密这类变换的根本区别内容编码是可逆的信息保持变换还原后得到的就是Content-Type所指的那种数据本身。5.2 三种编码compress、deflate、gzip编码名它是什么官方出处compress一种自适应 LZW编码通常由 UNIX 的compress程序产生接收方SHOULD视x-compress与compress等价E09deflatezlib 数据格式RFC 1950内含一个deflate 压缩数据流RFC 1951使用LZ77 与 Huffman 编码的组合E10gzip一种带32 位循环冗余校验CRC的LZ77编码通常由 gzip 程序产生RFC 1952接收方SHOULD视x-gzip与gzip等价E11两处要单独拎出来。第一处compress和gzip各有一个老名字。规范说接收方SHOULD把x-compress与compress视作等价E09把x-gzip与gzip视作等价E11。又是SHOULD不是必须看到带x-前缀的名字不必惊讶语义上它对应去掉前缀的那个编码。第二处deflate的定义里藏着一条官方注释。规范明确deflate是zlib 数据格式里面包着一条 deflate 压缩数据流E10同时注明部分不合规实现发送的 deflate 压缩数据不带 zlib 包装E10。这是规范自己写下的注释是一手事实。5.3 多个编码时顺序是施加顺序回到第二章那条硬规则施加编码的发送方 MUST 生成Content-Encoding并按施加顺序列出这些 content codingE03。这句话的分量全在施加顺序三个字上这个字段是有序的不是一堆并列的名字——列在前面的先被施加列在后面的后被施加还原时顺序就得反过来走。所以光看有哪些编码不够还得看按什么次序写的。⚠️代码待验证# 本文未实测观察 Content-Encoding 里多个值时是怎么排的# 该字段按施加顺序列出E03所以顺序本身携带信息curl-Ihttp://127.0.0.1:8080/index.html|grep-icontent-encoding# 若输出里有多个值记下先后次序再对照本地靶场的配置去理解谁先谁后完整版环境对照表这一章把三种 content coding 的名字 — 它是什么 — 出处整理成一页速查还附了一张字段出现在哪一侧、谁在说的方向对照和本章讲的编码语义是同一份材料的两面。放在资料包里扫码即可获取本章可以带走的一句compress是自适应 LZW、deflate是带 zlib 包装的 deflate 流、gzip是带 32 位 CRC 的 LZ77多个编码时字段里的顺序就是施加顺序。六、协商失败会怎样415 这条线6.1 不可接受的 content coding用 415 回应规范给了答案源服务器 MAY 对请求消息中带不可接受 content coding 的表示回 415Unsupported Media TypeE07。这里的MAY是可以即规范允许这么做是服务器的一种可选处置方式。注意 415 这个名字——“不支持的媒体类型”。有意思的地方就在这儿一个关于编码的问题用的却是一个名字里带媒体类型的状态码。6.2 这个头为什么出现在 415 里是有讲究的规范里有一句关键说明Accept-Encoding最常见的用途恰恰是在415 响应中E18——回应客户端对 content coding 的乐观使用。然后是本文最想讲清的一条规则E19因不支持的 content coding 而失败的服务器 ought to 回 415并在该响应中「包含」Accept-Encoding头字段让客户端能区分与 content coding 有关的问题和与媒体类型有关的问题反过来出于与 content coding 无关的原因以 415 失败的服务器MUST NOT 包含该头字段E19。情态词要一个字一个字看清一边是ought to“应当”一边是MUST NOT“必须不”。规范并没有把带上这个头写成 MUST倒是把不该带的时候不要带写成了 MUST NOT。这次 415 是因为什么失败的该不该在响应里带Accept-Encoding为什么因不支持的 content coding而失败ought to带上E19让客户端能区分与 content coding 有关的问题和与媒体类型有关的问题因与 content coding 无关的原因而失败MUST NOT带E19否则两类问题会被混在一起客户端会误判方向这张表恰好回答了 6.1 留下的疑问。415 说的是媒体类型可它同时被用来表达两类问题一类真和媒体类型有关另一类其实是和 content coding 有关。光看状态码分不出来得看响应里有没有那个头字段——有它说明问题出在编码这条线上没有则与编码无关。6.3 它不只出现在 415 里还有一点容易被忽略它在 415 里虽然是最常见的用途却并不是唯一用途E18。规范同时说明它也可以用来表明支持 content coding从而优化后续交互——给了一个具体场景某个资源在请求内容大到值得压缩、而客户端并没有这么做时服务器可以在一个2xx 响应里带上它E18。这正好补上第二章讲过的第二个方向服务器在响应里发这个字段说的是对该资源的后续请求我这边首选哪些编码E12。它在 2xx 里作用不是报错而是给下一次交互递话同一个字段在 415 里是你这个问题出在编码上在 2xx 里是下次你可以这么发。⚠️代码待验证# 本文未实测观察一个 415 响应里有没有跟着 Accept-Encoding# 判据来自 E19因 content coding 失败 → ought to 带上与 content coding 无关 → MUST NOT 带curl-ihttp://127.0.0.1:8080/index.html# 先看状态行是不是 415再看响应头里有没有 Accept-Encoding本章可以带走的一句415 同时承担两类问题靠有没有带Accept-Encoding来区分带是 ought to不该带时是 MUST NOT两者力度并不对称。七、把它用在抓包上一套判断顺序7.1 看到内容不对劲时按这个顺序看第一步先看响应头里有没有Content-Encoding。没有说明这次响应根本没施加内容编码媒体类型固有编码除外见 E06问题不在这条线上有才继续。第二步看它是哪一种编码。对照第五章那张表gzip、deflate、compressE09、E10、E11。这一步只告诉你用了什么算法不告诉你内容是什么后者走的是 E01 说的那件事——为得到Content-Type所指媒体类型的数据需要施加哪些解码机制。第三步回头看请求端的Accept-Encoding说了什么。用不用是两端协商出来的E12、E15换个客户端结果就变多半是这一步取值不一样。第四步最后再考虑会不会是工具显示形态的问题。各家工具默认怎么显示、开关叫什么名字属实现细节本文未核到官方文档级口径标为待验证BX01。第五步若看的是 415顺带确认它有没有带Accept-EncodingE19别把与编码无关的问题当成编码问题查。顺序看什么这一步能回答什么依据 / 状态一响应头有没有Content-Encoding这次到底有没有施加内容编码E01、E06二它是哪几种编码之一被施加的是哪一类变换E09、E10、E11三请求端Accept-Encoding写了什么两端有没有谈成换客户端为何结果不同E12、E15、E16四是不是工具显示形态的差异大概率是但具体开关名未核BX01待验证五415 响应里有没有Accept-Encoding这次失败属不属于 content coding 那一类E197.2 三条必须先说清的边界第一本文不给任何针对真实站点的实测样例。上面每条判断依据的都是规范写下的字段语义不是在某个真实地址上抓到的结果示例命令也一律未实际运行逐个保留代码待验证标记。第二还原在这里指的是协议语义层面的解码不是一份操作流程。它的完整含义只有一句某个字段指示了已经施加过哪种编码变换接收方据此还原出Content-Type所指的那种数据E01。这是字段语义不是步骤教程本文不把去掉内容编码后看到原文当成做任何事的手段来写。第三字段的语义是稳定的工具的表现是可变的。前者有一手出处可回溯附表 A 逐条列了后者属实现细节未核到官方文档级口径的一律标待验证。把这两类信息分开存放是看包时不至于混淆的底线。补一句时效话本文字段语义均取自 RFC 9110HTTP Semantics截至 2026-10-06本文引用的即该规范对应章节的现行文本见附表 A 核验日期一列。7.3 收束回到标题。响应被压缩过了从来不是服务器单方面做的决定客户端先用Accept-Encoding划出一句我能接受哪些施加方在这个范围内选一个用上再用Content-Encoding如实报告我用了哪一个、按什么顺序施加。所以为什么同一个请求换个客户端就变了答案落在请求那一侧的那句话上——变的不是服务器是另一半说了什么。⚠️代码待验证# 本文未实测把第七章的判断顺序收成一份清单按顺序逐项看# 1. 响应头有没有 Content-Encoding - 没有则这条线不成立E01/E06curl-Ihttp://127.0.0.1:8080/index.html|grep-icontent-encoding# 2. 它是哪一类编码gzip / deflate / compressE09/E10/E11# 3. 请求端 Accept-Encoding 写了什么 - 没有全接受空值都不要q0明确拒绝E15/E16curl-I-HAccept-Encoding: gzip, deflatehttp://127.0.0.1:8080/index.html# 4. 若怀疑是工具显示形态问题注意各家开关名本文未核BX01待验证# 5. 若是 415看它有没有带 Accept-Encoding - 带了说明与 content coding 有关E19完整版环境对照表这套五步判断顺序连同四种取值情形不发 / 空值 / 列出 / 标 0的对照、以及 415 那条线的判据一起收进资料包扫码即可获取本章可以带走的一句先看有没有Content-Encoding、再看是哪种、再回看请求端说了什么、最后才怀疑工具显示本文不给真实站点实测样例也不把还原写成操作步骤。附表 A本文引用事实与官方出处对照表#事实陈述一手出处来源名 URL核验日期本文位置1E01Content-Encoding指示哪些 content coding 已施加到表示上媒体类型固有编码之外以及还原到Content-Type所指媒体类型的数据需要什么解码机制用途是在不丢底层媒体类型身份的前提下压缩RFC 9110 §8.4 — https://www.rfc-editor.org/rfc/rfc9110.txt2026-10-06第二、三、五、七章2E02语法Content-Encoding #content-coding官方示例Content-Encoding: gzipRFC 9110 §8.42026-10-06第二章3E03已施加编码时施加编码的发送方MUST生成该字段并按施加顺序列出这些 content codingRFC 9110 §8.42026-10-06第二、五章4E04identity为它在Accept-Encoding中的特殊作用保留因此SHOULD NOT出现在Content-Encoding中RFC 9110 §8.42026-10-06第三章5E05逐字Unlike Transfer-Encoding (Section 6.1 of [HTTP/1.1]), the codings listed in Content-Encoding are a characteristic of the representation; the representation is defined in terms of the coded form, and all other metadata about the representation is about the coded form unless otherwise noted.编码是表示的属性通常只在渲染前才解码RFC 9110 §8.42026-10-06第三章6E06媒体类型的固有编码不重复声明仅被第二次施加形成表示时才列出RFC 9110 §8.42026-10-06第三、七章7E07源服务器MAY对带不可接受 content coding 的请求表示回415Unsupported Media TypeRFC 9110 §8.42026-10-06第六章8E08content coding 值表示已施加或可施加的编码变换用于压缩等变换不丢媒体类型身份与信息所有 content coding大小写不敏感RFC 9110 §8.4.12026-10-06第五章9E09compress为自适应 LZW通常由 UNIX 的compress程序产生接收方SHOULD视x-compress与compress等价RFC 9110 §8.4.1.12026-10-06第五、七章10E10deflate为 zlib 数据格式RFC 1950内含 deflate 流RFC 1951LZ77 与 Huffman 组合官方注部分不合规实现不带 zlib 包装RFC 9110 §8.4.1.22026-10-06第五、七章11E11gzip为带 32 位 CRC 的 LZ77 编码RFC 1952通常由 gzip 程序产生接收方SHOULD视x-gzip与gzip等价RFC 9110 §8.4.1.32026-10-06第五、七章12E12两个方向——用户代理在请求中发送时表示响应中可接受的 content coding服务器在响应中发送时给出后续请求首选哪些编码的信息RFC 9110 §12.5.32026-10-06第二、六、七章13E13identity是无编码的同义词表达不偏好任何编码RFC 9110 §12.5.32026-10-06第三章14E14语法#( codings [ weight ] )codings content-coding / identity / *每个值MAY带质量值weight*匹配未显式列出的可用 content codingRFC 9110 §12.5.32026-10-06第四章15E15三条规则——① 无该头则任何 content coding 均视为可接受② 表示无 content coding 则默认可接受除非被identity;q0或*;q0且无更具体 identity 条目明确排除③ 编码在列表中则可接受除非附带 qvalue 为0RFC 9110 §12.5.32026-10-06第四、七章16E16空的该字段值意味着用户代理不想要任何content codingRFC 9110 §12.5.32026-10-06第四、七章17E17有非空该头而无任何可用表示的编码被列为可接受时源服务器SHOULD发不带任何 content coding 的响应——除非identity 被指示为不可接受RFC 9110 §12.5.32026-10-06第四章18E18该头最常见用途是在415 响应中也可用于表明支持 content coding如请求内容大到值得压缩而客户端未这么做时在 2xx 里带上它RFC 9110 §12.5.32026-10-06第六章19E19因不支持的 content coding失败者ought to回 415 并包含该头让客户端区分与 content coding 有关和与媒体类型有关的问题因与 content coding 无关的原因失败者MUST NOT包含该头字段RFC 9110 §12.5.32026-10-06第六、七章20本文未实测各抓包工具对压缩内容的显示形态与开关名属实现细节未核到官方文档级口径标待验证BX01本文未核BX01待验证第一、七章21本文未实测全部示例命令curl相关均未在本机实际运行逐个保留⚠️ 代码待验证标记不给任何针对真实站点的实测结果本文未实测2026-10-06第一、二、四、五、六、七章附表 B术语速查表术语一句话解释内容编码content coding对字节序列施加的可逆变换主要用于压缩不丢信息、不丢底层媒体类型身份E08Content-Encoding响应头报告已经施加了哪些 content coding以及还原所需的解码机制E01Accept-Encoding请求头也可出现在响应里请求侧表示响应中可接受的 content coding响应侧表示后续请求首选哪些E12表示representation这份资源呈现出来的那一份东西Content-Encoding列出的是表示的属性E05消息message传输编码那一层所附着的东西那层另有专文E05identity无编码的同义词E13为Accept-Encoding的特殊作用保留SHOULD NOT出现在Content-Encoding中E04质量值weight / qvalue附着在编码取值后的偏好数值qvalue 为0表示不可接受E14、E15星号*匹配任何未在该字段中显式列出的可用 content codingE14compress自适应 LZW 编码通常由 UNIX 的compress程序产生E09x-compress视同它deflatezlib 数据格式RFC 1950内含 deflate 流RFC 1951LZ77 与 Huffman 的组合E10gzip带 32 位 CRC 的 LZ77 编码RFC 1952E11x-gzip视同它施加顺序Content-Encoding里多个编码的排列次序 它们被施加的先后E03415Unsupported Media Type一种状态码既用于与媒体类型有关的问题也用于与 content coding 有关的问题靠有无Accept-Encoding区分E07、E19待验证BX01各抓包工具对压缩内容的显示形态与开关名本文未核到官方文档级口径代码待验证该代码块中的命令未在本机实际运行过写在最后这篇用到的资料写这篇文章时我一直在想初学者那个最常见的困惑同一个地址为什么换个客户端那个Content-Encoding就没了。理清楚之后发现它根本不是服务器时好时坏而是两端各说了一句话——一句我能接受哪些一句我用了哪个。顺手也整理了几份配套的东西靶场环境对照表DVWA、upload-labs 在 Windows / macOS / Linux 三平台的可行性与推荐路径Web 安全学习路线图从基础打牢到安全管理四个阶段各学什么常用靶场清单每个靶场练什么、适合哪个阶段资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「靶场」优先通过。拿到之后建议先看环境对照表那一份再回头把本文第二章那张两个字段各管一半的方向对照过一遍——下次再遇到换个客户端就变了你就知道该去看请求那一侧说了什么。
返回列表