本文根据深信服 SCSA-S 课程《HTTP 协议》七节课件整理,讲 HTTP 的基础:起源、网络基础、URL、六个特点、请求方法、状态码与请求响应过程。

报文结构、首部字段、HTTPS 与协议安全见配套文章《HTTP 报文与 HTTPS》;靶场实战见《HTTP 实战:CTFHub 入门五题》。

为什么安全人要从 HTTP 学起

如果只能选一个协议来代表 Web,那一定是 HTTP。

浏览器地址栏里的一次回车、一个登录表单的提交、一次 API 调用、一次漏洞利用,底层都是 HTTP 报文。SQL 注入注入的是 HTTP 参数,XSS 输出的是 HTTP 响应体,越权修改的是 HTTP 请求中的对象 ID,请求走私利用的是 HTTP 首部的解析差异,CSRF 利用的是 HTTP 自动携带 Cookie 的机制。

可以说,Web 安全的大部分问题,都能还原成”某个 HTTP 字段被当成了可信输入”。

这篇文章按下面的顺序展开:

  1. HTTP 的诞生与版本;
  2. HTTP 依赖的网络基础(TCP/IP、TCP、DNS);
  3. URL 与 URI;
  4. HTTP 的六个特点;
  5. 请求方法;
  6. 状态码;
  7. 一次请求的完整过程。

一、HTTP 的诞生与版本演进

1.1 万维网的三项核心技术

课件把万维网的构建技术归纳为三样:

技术 全称 作用
HTML HyperText Markup Language,超文本标记语言 定义文档的结构与内容
HTTP HyperText Transfer Protocol,超文本传输协议 定义浏览器与服务器之间的通信规则
URL Uniform Resource Locator,统一资源定位符 标识资源的位置

三者分工明确:URL 负责”找到”,HTTP 负责”取回”,HTML 负责”呈现”。缺了任何一个,万维网都跑不起来。

1989 年 3 月,Tim Berners-Lee 在 CERN 提交万维网构想;1990 年 11 月,第一台 Web 服务器和浏览器诞生;1991 年,系统正式发布。此后三十多年,Web 的技术栈经历了多轮演进,但这三项技术始终没变。

1.2 浏览器简史

浏览器是 HTTP 最典型的客户端。课件提到几个关键节点:

  • Mosaic:1993 年 1 月由美国国家超级计算机应用中心(NCSA)研发,随后被移植到 Windows、Mac,是第一个让普通用户用上图形化 Web 的浏览器;
  • Netscape Navigator:1994 年网景公司研发,1995 年与微软爆发”浏览器大战”;
  • 当前主流:国外 Chrome、Firefox、Safari、Edge;国内 QQ 浏览器、UC 浏览器、傲游、搜狗浏览器。

浏览器大战的结果,是浏览器成了”操作系统之上的操作系统”。今天的安全研究,很大一部分是在研究浏览器怎么解析 HTML、怎么执行 JS、怎么管理 Cookie 和同源策略——这些都属于 HTTP 生态的一部分。

1.3 HTTP 是什么

课件给 HTTP 的定义可以拆成六句话:

  • 1990 年提出,当前广泛使用的版本是 HTTP/1.1;
  • 是万维网交换信息的基础;
  • 规定浏览器和服务器之间相互通信的规则;
  • 允许将 HTML 文档从 Web 服务器传送到 Web 浏览器;
  • 是请求与响应对应的协议:客户端发送请求,服务器对收到的请求给出响应;
  • 使用可靠的 TCP 连接,默认 TCP 端口是 80。

再补一句本质:HTTP 是一个”应用层文本协议”。它把语义写在人类可读的文本里——方法、路径、状态码、首部名,全是 ASCII 单词。这带来了极低的学习和调试成本,也带来了后面要讲的解析歧义与走私风险。

1.4 版本演进

版本 时间 关键变化
HTTP/0.9 1991 年 只有 GET,没有首部,返回纯 HTML,连接用完即断
HTTP/1.0 1996 年(RFC 1945) 引入首部、状态码、Content-Type;默认非持久连接,每个请求一次 TCP
HTTP/1.1 1997 年(RFC 2616) 默认持久连接、必需 Host 首部、分块传输(chunked)、管线化;至今仍是最广泛部署的版本
HTTP/2 2015 年(RFC 7540) 二进制分帧、多路复用、HPACK 首部压缩、服务端推送;解决队头阻塞
HTTP/3 2022 年(RFC 9114) 基于 QUIC(UDP),0-RTT 建连,进一步降低延迟

课件重点讲的是 1.1,原因很简单:它既是考试和面试的重点,也是渗透测试中最常遇到的版本。很多老系统、内网设备、中间件仍然跑在 1.1 上,而请求走私、Host 头攻击、分块编码绕过等经典手法,全都建立在 1.1 的文本解析规则之上。

补充说明:HTTP/1.1 的原始标准是 RFC 2616,后来被 RFC 7230–7235 拆解修订,2022 年又被 RFC 9110–9112 取代。日常说”HTTP/1.1”时,指的都是这套语义。


二、HTTP 的网络基础

HTTP 不是凭空跑的。一个请求从浏览器到服务器,要经过 DNS 解析、TCP 连接,底层还要靠 IP 寻址。理解这些,才能看懂抓包、理解代理、想明白 SSRF 和 DNS 劫持是怎么回事。

2.1 TCP/IP 四层模型

课件把 TCP/IP 分为四层:

层次 职责 代表协议
应用层 处理特定应用的细节 HTTP、DNS、FTP、SMTP、SSH
运输层 为两台主机上的应用提供端到端通信 TCP、UDP
网络层 处理分组在网络中的活动,如选路 IP、ICMP、IGMP
链路层 处理与电缆、网卡等物理媒介的接口细节 Ethernet、ARP、PPP

2.2 封装与拆封

发送方将数据自上而下交给每一层,每经过一层就添加一个首部;接收方自下而上处理,每经过一层就移除对应的首部。这个过程叫封装与拆封。各层通过首部承载本层所需的控制信息,上层数据作为下层的数据载荷。

+-----------------------------+
| HTTP 报文 | 应用层数据
+-----------------------------+
| TCP 首部 | 数据 | 运输层:加端口号、序号、校验和
+-----------------------------+
| IP 首部 | TCP 首部 | 数据 | 网络层:加源/目的 IP
+-----------------------------+
| 帧头 | IP 首部 | ... | 帧尾 | 链路层:加 MAC 地址、CRC
+-----------------------------+

抓包工具观察到的是逐层封装后的结构。在 Wireshark 中展开一个 HTTP 包,可以看到 Ethernet → IP → TCP → HTTP 的完整层次,这对分析请求走私、分片和异常首部非常有用。

2.3 IP 协议:负责”送到哪”

IP(网际协议)是 TCP/IP 的核心协议,上层协议(TCP、UDP 等)的数据包都要用 IP 包承载传输。它的两个关键词是:

  • 不可靠:不保证送达,不保证顺序,丢了不重传;
  • 无连接:不维护连接状态,每个包独立选路。

IP 负责的是”寻址 + 路由”:给每个包写上源 IP 和目的 IP,然后由路由器一跳一跳转发。IPv4 是 32 位地址,IPv6 是 128 位地址。

正因为 IP 只负责”尽力而为”,可靠性才需要由 TCP 在上层补上。这也是为什么 HTTP 选择 TCP 而不是直接用 IP。

2.4 TCP 协议:负责”可靠地送到”

TCP(传输控制协议)是运输层协议,提供面向连接的、可靠的字节流传输。课件强调了三个机制:

  • 三次握手:先建立连接,再传输数据;
  • 滑动窗口:实现可靠传输、超时重传、流量控制;
  • 四次挥手:双向分别中断。

三次握手

客户端 服务器
| ------ SYN (seq=x) ---------------> |
| <----- SYN+ACK (seq=y, ack=x+1) --- |
| ------ ACK (ack=y+1) -------------> |
| ========== 连接建立,开始传数据 ========== |

为什么是三次而不是两次?因为双方都要确认各自的发送与接收能力:客户端确认服务器收到了自己的 SYN,服务器确认客户端收到了自己的 SYN+ACK。两次握手无法让服务器确认客户端已收到自己的 SYN,容易受到历史连接请求的干扰。

四次挥手

客户端 服务器
| ------ FIN -----------------------> | 客户端没有数据要发了
| <----- ACK ------------------------ |
| <----- FIN ------------------------ | 服务器也没有数据要发了
| ------ ACK -----------------------> |
| ========== 连接关闭 ================= |

TCP 是全双工的,两个方向要分别关闭,所以需要四次。主动关闭方最后会进入 TIME_WAIT 状态,等待 2MSL,确保最后的 ACK 能到达,并让旧连接的数据包在网络中消散。

滑动窗口

TCP 不是”发一个等一个 ACK”,而是允许发送方连续发送多个段,接收方通过窗口字段通告可用接收窗口大小。窗口机制同时实现了:

  • 可靠传输:丢包重传;
  • 流量控制:别把接收方撑爆;
  • 拥塞控制:别把网络撑爆(慢启动、拥塞避免、快重传、快恢复)。

安全视角

  • 端口扫描:利用 SYN、ACK、FIN 等不同标志位的响应差异判断端口状态;
  • SYN Flood:伪造大量 SYN,占满半连接队列;
  • 会话劫持:猜出或窃取序列号,插入伪造数据;
  • RST 注入:伪造 RST 包强制断开连接;
  • 慢速攻击:Slowloris 用极慢的请求头占住连接。

2.5 DNS 协议:负责”找到名字对应的地址”

DNS(域名解析协议)的作用只有一句话:把域名解析为 IP 地址。

课件区分了两种查询方式:

方式 过程 特点
递归查询 客户端问本地 DNS,本地 DNS 负责问到底,最后把结果返回 客户端省事,本地 DNS 压力大
迭代查询 本地 DNS 逐级查询根、顶级域和权威服务器,每次获得下一跳地址 服务器省事,查询方要多次往返

一次完整的解析大致是:

浏览器缓存 → 操作系统缓存 → hosts 文件 → 本地 DNS 服务器
→ 根域名服务器(返回 .com 的地址)
→ .com 顶级域服务器(返回 example.com 的权威服务器)
→ 权威 DNS(返回最终 IP)

常见记录类型:

类型 含义
A 域名 → IPv4 地址
AAAA 域名 → IPv6 地址
CNAME 别名,指向另一个域名
MX 邮件服务器
NS 该域名的权威 DNS 服务器
TXT 文本记录,常用于 SPF、域名验证

安全视角

  • DNS 劫持:篡改解析结果,把用户引到钓鱼站;
  • DNS 缓存投毒:污染本地 DNS 的缓存;
  • DNS 隧道:把数据封装在 DNS 查询里外传,绕过防火墙;
  • hosts 文件篡改:本机层面的劫持;
  • 虚拟主机:一个 IP 上跑多个站点,服务器靠 HTTP 的 Host 首部区分——这也是 Host 头攻击的根源。

2.6 为什么安全人必须懂这些

因为很多 Web 漏洞的根因不在 Web 层:

  • SSRF 能打内网,是因为服务器能发起 TCP 连接;
  • 请求走私能成功,是因为前后端对 HTTP 报文的边界理解不一致;
  • 缓存投毒能成功,是因为 CDN 按 Host/URL 做缓存键;
  • DDoS 打的是 TCP 连接和带宽;
  • 中间人攻击发生在 TCP/TLS 层。

只学 HTTP 语法,看到的是”字段”;懂了网络基础,看到的是”数据怎么流动”。


三、URL 与 URI:资源怎么被定位

3.1 URL 的语法

课件给出的 URL 语法规则是:

scheme://host.domain:port/path/filename

各部分的含义:

部分 含义 示例
scheme 因特网服务的类型,最常见的是 http http、https、ftp
host 域主机,http 的默认主机是 www www
domain 因特网域名 sangfor.com
port 主机上的端口号,http 默认 80 80、8080
path 服务器上的路径,省略时文档必须位于网站根目录 /dir/
filename 文档/资源的名称 index.html

一个完整的例子:

http://user:[email protected]:80/dir/index.html?uid=1#ch1
└─┬─┘ └──┬───┘ └──────┬──────┘└┬┘└─────┬─────┘└──┬──┘└─┬─┘
协议 登录信息 服务器地址 端口 文件路径 查询字符串 片段标识

每个部分的细节:

  • 协议(scheme):指定访问资源所用的协议。除了 http/https,还有 ftp、file、mailto、data 等。
  • 登录信息(userinfo):user:pass@ 的形式,现在基本被浏览器废弃,但仍可能出现在钓鱼链接里。
  • 服务器地址(host + domain):可以是域名,也可以是 IP。
  • 端口(port):省略时用协议默认端口。
  • 文件路径(path):服务器上的资源路径。
  • 查询字符串(query):?key=value&key2=value2,是 GET 请求传参的主要方式,也是注入类漏洞的高发区。
  • 片段标识(fragment):# 后面的部分,只给浏览器看,不会发送给服务器。这一点非常关键——DOM 型 XSS 经常就藏在 fragment 里,服务端日志里根本看不到。

3.2 URL 编码

URL 里有一批”保留字符”(?、&、=、/、#、空格等),如果要把它们当作普通数据传,就需要百分号编码(percent-encoding):

字符 编码
空格 %20(表单里也常用 +)
/ %2F
? %3F
& %26
= %3D
# %23
.. %2E%2E

编码规则是:先把字符按 UTF-8 转成字节,再把每个字节写成 %XX。

安全视角:编码是绕过过滤的常用手段。

  • ../ 被过滤?试试 %2e%2e%2f;
  • 一次解码后又被过滤?试试双重编码 %252e%252e%252f;
  • 空字节截断?%00(老版本 PHP、Java 中常见);
  • 大小写混用、全角字符、Unicode 归一化,都可能造成”过滤器看到 A,解释器执行 B”。

这类问题的本质是解码次数与解码位置不一致:WAF 解一次,后端解两次,差异就是漏洞。

3.3 URL 与 URI 的关系

课件从”定位”和”标识”的角度做了区分:

  • URL 给出资源位于哪里(哪台主机、哪个路径、哪个文件夹);
  • URI 给出具体某资源的定位路径(从资源自身出发,给出可达的路径)。

严格来说,URI(统一资源标识符)是一个更大的概念,URL(统一资源定位符)只是它的一种;另一种是 URN(统一资源名称),比如 urn:isbn:9787115428028。日常开发和文档里,两者经常混用,不必过度纠结,但要知道:

  • 说”这个 URI”时,强调”唯一标识一个资源”;
  • 说”这个 URL”时,强调”能通过它找到资源”。

3.4 常见协议与默认端口

协议 默认端口 说明
HTTP 80 明文 Web
HTTPS 443 HTTP over TLS
FTP 21(控制)/ 20(数据) 文件传输
SSH 22 远程登录
SMTP 25 邮件发送
DNS 53 域名解析
MySQL 3306 数据库
Redis 6379 缓存
Tomcat 8080 Java Web 容器默认端口

端口是资产测绘的重要线索。看到 8080 想到 Tomcat,看到 7001 想到 WebLogic,看到 6379 想到 Redis——这些”默认端口 + 默认配置”的组合,是实战中最常见的突破口。

3.5 URL 层面的攻击面

位置 可能的问题
scheme 伪协议(file://、gopher://、dict://)导致 SSRF/LFI
userinfo 钓鱼链接伪装(http://[email protected])
host Host 头注入、SSRF、DNS 重绑定
port 端口扫描、内网探测
path 目录遍历、路径穿越、解析差异
query SQL 注入、XSS、命令注入、参数污染
fragment DOM 型 XSS(服务端不可见)

同一个 URL,每个部分都可能是入口。 这也是为什么做渗透测试时,第一步往往是”把目标的所有 URL 收集全”。


四、HTTP 的六个特点

课件把 HTTP 的特点归纳为六点:请求与响应、不保存状态、资源定位、请求方法、持久连接与管线技术、Cookie 技术。下面逐条展开,并补上安全含义。

4.1 请求与响应:方向与触发条件

HTTP 规定:请求从客户端发起,由服务端响应该请求并返回。

  • 客户端发起请求,服务端才会响应;
  • 客户端未发起请求,服务端不会主动响应。

这条规则带来两个直接后果:

  1. HTTP/1.1 没有原生的”服务器推送”。想要实时更新,只能用轮询、长轮询、SSE(Server-Sent Events)或 WebSocket 来模拟。
  2. 浏览器会自动发起子资源请求。页面中的图片、CSS、JS、iframe 都会被自动请求;点击链接时,浏览器会携带 Cookie 发起请求。CSRF 之所以成立,就是因为”浏览器会自动带上凭证”这件事不受页面控制。

一个最小的请求响应示意:

客户端 服务器
| ---- GET /index.html HTTP/1.1 -------------> |
| Host: www.sangfor.com.cn |
| <--- HTTP/1.1 200 OK ----------------------- |
| Content-Type: text/html |
| Content-Length: 617 |
| <html>...</html> |

4.2 不保存状态:无状态协议与状态管理

HTTP 协议不保存请求和响应的通信状态,不做持久化处理。每次新的请求,对应一次响应产生。

课件提出了一个问题:

登录后,后续请求如何识别用户身份?

答案是:HTTP 本身不保存状态,登录态由 Cookie、Session 或 Token 维护。三者的区别在于状态保存在哪一方:

  • Cookie:客户端保存的键值对,浏览器按 Domain/Path 规则在后续请求中自动携带;
  • Session:服务端保存的会话记录,客户端只持有 Session ID,服务端据此查找状态;
  • Token:自包含的凭证(如 JWT),客户端保存并在请求头中发送,服务端通过签名或校验接口判断有效性。

无状态的好处:服务器不用为每个用户保存会话,容易横向扩展,请求可以打到任意一台机器。

无状态的代价:每个请求都要自带身份信息;一旦凭证泄露,攻击者可以重放;也正因为如此,才需要 CSRF Token、SameSite Cookie、短期 Token 这些机制来补漏洞。

4.3 资源定位:用 URI 找到资源

HTTP 通过请求 URI 实现对资源的访问。请求行里的路径,就是 URI 的一部分:

GET /zl/china/2021-02-01/zl-ikftssap2140491.shtml HTTP/1.1
Host: finance.sina.com.cn

服务器根据 Host + 路径,定位到具体资源。这也是虚拟主机的工作原理:同一个 IP,靠 Host 区分不同站点。

4.4 请求方法:指定操作类型

方法是 HTTP 的”动词”,用来告知服务器该请求的意图。HTTP/1.1 的主要方法包括:

方法 作用
GET 获取资源
POST 传输实体主体
PUT 传输文件
HEAD 获得报文首部
DELETE 删除文件
OPTIONS 询问支持的方法
TRACE 追踪路径
CONNECT 要求用隧道协议连接代理

这部分内容较多,后面单独展开。

4.5 持久连接与管线化:别为每个请求都握一次手

早期的问题

最早期的 HTTP 版本,发起一次请求就要建立一次 TCP 连接。一个网页往往包含 HTML、CSS、JS、几十张图片,意味着几十次”三次握手 + 四次挥手”。对服务器来说,连接数暴涨、成本很高;对用户来说,页面加载慢。

客户端 服务器
| ---- SYN ------------------------> |
| <--- SYN+ACK --------------------- |
| ---- ACK -------------------------> |
| ---- HTTP 请求 -------------------> |
| <--- HTTP 响应 -------------------- |
| ---- FIN -------------------------> |
| <--- ACK -------------------------- |
| <--- FIN -------------------------- |
| ---- ACK -------------------------> |
| (下一个资源,再来一遍……) |

持久连接(Keep-Alive)

HTTP/1.1 默认开启持久连接:建立一次 TCP 连接后,只要任意一端没有明确提出断开,连接就保持复用。

  • 减少了 TCP 握手/挥手的开销;
  • 降低了服务器压力;
  • 相同时间内能传完更多内容,页面显示更快。

如果想主动断开,可以发送 Connection: close。

管线化(Pipelining)

在持久连接的基础上,客户端可以一次发送多个请求,不必等前一个响应回来,然后按顺序接收多个响应。

客户端:请求1 请求2 请求3 →
服务器: ← 响应1 响应2 响应3

它进一步提升了传输效率,但存在一个关键问题:响应必须按请求顺序返回。如果请求 1 很慢,后续响应必须等待——这就是”队头阻塞”(Head-of-Line Blocking)。HTTP/2 的多路复用就是为了解决它。

安全视角:持久连接和管线化也为请求走私提供了条件。当前端代理和后端服务器对”一个请求到哪里结束”的判断不一致时,攻击者可以将第二个请求嵌入第一个请求的报文中,让后端按两个请求处理。

4.6 Cookie:给无状态协议补上记忆

工作机制

Cookie 通过在请求和响应报文中写入信息来控制客户端状态:

  1. 服务器在响应头里加 Set-Cookie: name=value;
  2. 浏览器保存这个 Cookie;
  3. 下次向同一服务器发请求时,浏览器自动在请求头里加 Cookie: name=value;
  4. 服务器读到 Cookie,就知道”这是谁”。
第一次请求:
GET / HTTP/1.1
Host: example.com
↓
HTTP/1.1 200 OK
Set-Cookie: admin=0; Path=/
后续请求:
GET /index.php HTTP/1.1
Host: example.com
Cookie: admin=0

常见属性

属性 作用 安全意义
Expires / Max-Age 过期时间 会话 Cookie 关闭浏览器即失效;持久 Cookie 可能被窃取后长期利用
Domain 生效域名 设置过宽会让子域共享 Cookie,增加泄露面
Path 生效路径 不是安全边界,别用它做权限控制
Secure 只在 HTTPS 下发送 防止明文网络窃听
HttpOnly JS 读不到 大幅降低 XSS 盗取 Cookie 的危害
SameSite 跨站请求是否携带 Strict/Lax 可缓解 CSRF

Cookie vs Session vs Token

机制 状态存在哪 优点 缺点
Cookie 客户端 简单、浏览器自动携带 可被篡改、窃取;容量小
Session 服务端 数据不落客户端,相对安全 服务器有状态,扩展麻烦
Token(JWT 等) 客户端(自包含) 无状态、易扩展 注销难、泄露后风险大

安全视角

  • 篡改:Cookie 存在客户端,用户可以随意改。如果服务端直接信任 admin=0/1 这种字段,就是典型的越权。CTFHub 的 Cookie 题考的就是这个。
  • 窃取:XSS 可以直接读 document.cookie,所以会话 Cookie 要加 HttpOnly。
  • 伪造:如果 Cookie 里存的是可预测的会话 ID,攻击者可以猜。
  • 固定:攻击者先让受害者用一个已知的 Session ID 登录,之后就能共用这个会话。
  • CSRF:浏览器自动携带 Cookie,所以攻击者可以诱导受害者在他不知情的情况下发出请求;防御靠 CSRF Token 和 SameSite。

五、请求方法详解

5.1 方法的语义:安全、幂等、可缓存

在逐个讲方法之前,先建立三个概念,它们决定了方法该怎么用、代理能不能缓存、浏览器会不会重放:

概念 含义
安全(Safe) 不改变服务器状态,只读取
幂等(Idempotent) 执行一次和执行多次,效果相同
可缓存(Cacheable) 响应可以被浏览器、代理、CDN 缓存
方法 安全 幂等 可缓存 典型用途
GET 是 是 是 获取资源
HEAD 是 是 是 获取首部
OPTIONS 是 是 否 询问支持的方法
TRACE 是 是 否 回显请求
POST 否 否 有条件 提交数据
PUT 否 是 否 写入/替换资源
DELETE 否 是 否 删除资源
PATCH 否 否 否 局部更新
CONNECT 否 否 否 建立隧道

注意:这些是”协议约定”,不是”服务器强制”。很多框架会把 POST 当查询用,也会把 GET 当删除用——约定被破坏的地方,往往就是漏洞。

5.2 GET:获取资源

GET 是最常用的方法,通常用于请求服务器发送某个资源。

GET /index.html HTTP/1.1
Host: www.sangfor.com.cn
Accept: */*
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head><title>SANGFOR</title></head>
...

特点:

  • 参数放在 URL 的查询字符串里:/search?q=keyword&page=1;
  • 安全、幂等,可以被缓存、被收藏、被分享;
  • 参数会出现在浏览器历史、服务器日志、Referer 里,不适合传敏感数据;
  • 受浏览器和服务器对 URL 长度的限制(不是协议限制)。

安全视角:GET 参数是注入类漏洞的主要入口。SQL 注入、XSS、命令注入、SSRF,很多都从 ?id=1 这样的参数开始。另外,如果一个删除操作写成 GET /delete?id=1,攻击者只要诱导用户访问一张图片 <img src="https://target/delete?id=1">,就能完成 CSRF。

5.3 POST:提交数据

POST 用于向服务器输入数据,主要支持 HTML 表单。表单填写好后会被发送给服务器,比如登录窗口输入用户名和密码,供服务器验证身份。

POST /login HTTP/1.1
Host: www.sangfor.com.cn
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=admin&password=123456

特点:

  • 数据放在请求体(body)里;
  • 不天然安全、不幂等、默认不缓存;
  • 常见的 body 编码:application/x-www-form-urlencoded、multipart/form-data(文件上传)、application/json(API)。

课件特别提醒了 POST 与 PUT 的区别:

POST 用于向服务器发送数据,PUT 用于向服务器上的资源(比如文件)中存储数据。

技术上的区别是:POST 将数据提交给目标 URI 标识的资源,由服务端决定如何处理;PUT 要求在目标 URI 上创建或替换资源。

安全视角:POST 并不比 GET 安全。它只是把参数从 URL 挪到了 body,抓包一样能看到;在明文 HTTP 下,body 和 URL 一样会被中间人截获。POST 能减少的是”参数出现在日志/历史记录/Referer 里”的泄露面,以及一些基于 URL 的简单防护。

5.4 PUT:向服务器写文件

PUT 方法向服务器写入文档:用请求的主体创建一个由 URI 命名的新文档;如果该文件已存在,就用主体替换它。

PUT /123.txt HTTP/1.1
Host: www.sangfor.com.cn
Content-Type: text/plain
Content-Length: 18
This is a test file.
HTTP/1.1 201 Created
Location: http://www.sangfor.com.cn/123.txt
Content-Type: text/plain
Content-Length: 47

课件提到:因为涉及内容修改,大部分执行 PUT 方法前会被要求登录。

安全视角:PUT 是”文件上传漏洞”的另一种形态。

  • IIS + WebDAV:如果开启了 WebDAV 且允许 PUT,攻击者可以直接 PUT 一个脚本文件,再用 MOVE 改成可执行后缀;
  • Tomcat CVE-2017-12615:在特定配置下(readonly=false,Windows 环境),可以通过 PUT /1.jsp/(注意末尾斜杠)绕过限制写入 JSP 文件,进而 RCE;
  • 任意文件写入:即使不能执行,也可能覆盖配置文件、写入计划任务、污染日志。

5.5 HEAD:只要首部,不要正文

HEAD 方法与 GET 类似,但只返回首部,不返回实体的主体部分。它可以在不获取实际资源的情况下,对资源做检查。

用途:

  1. 判断资源类型(看 Content-Type);
  2. 通过状态码判断资源是否存在(200 / 404);
  3. 判断资源是否被修改(看 Last-Modified、ETag);
  4. 探测 Content-Length,判断响应大小。

安全视角:HEAD 是很好的”轻量探测”工具。批量 HEAD 可以快速判断路径是否存在、服务器是什么、有没有 WAF。防守方如果在 HEAD 请求上返回了和 GET 不一样的详细错误,也可能泄露信息。

5.6 DELETE:删除资源

DELETE 请求服务器删除请求 URI 指定的资源,但不一定成功。课件解释了不成功的原因:HTTP 规范允许服务器在不通知客户端的情况下撤销请求。

例如请求删除 DVWA 目录下的资源,服务器可能返回 405 Method Not Allowed。

安全视角:如果服务器错误地开启了 DELETE,攻击者可以直接删除文件、数据,甚至删库。很多生产环境会在反向代理层直接禁用 PUT/DELETE/TRACE 等方法。

5.7 OPTIONS:询问支持的方法

OPTIONS 用于询问服务器支持的各种功能:

  • 询问服务器支持哪些方法;
  • 询问某些特殊资源支持哪些方法。

响应里通常会有 Allow 首部:

HTTP/1.1 200 OK
Allow: GET, HEAD, POST, OPTIONS

安全视角:

  • 信息收集:Allow 响应头直接列出服务端支持的方法,可判断 PUT/DELETE 是否开放;
  • CORS 预检:浏览器在跨域发送非简单请求前,会先发一个 OPTIONS 预检,问服务器”允不允许”;CORS 配置错误(如 Access-Control-Allow-Origin: * 且允许携带凭证)是常见的越权入口;
  • 有些 WAF 只检查 GET/POST,OPTIONS 可能被用来探测绕过。

5.8 TRACE:把请求原样回显

TRACE 方法用于跟踪请求经过了哪些中间环节(防火墙、代理等)。每个中间节点可以修改原始 HTTP 请求,增加代表自己的信息(如 Via: 1.1 proxy.sangfor.com.cn),最后的响应服务器把最终的请求头作为响应主体返回给客户端。

安全视角:TRACE 会原样回显请求,包括 Cookie 和认证头,容易造成敏感信息泄露;结合浏览器漏洞还可能形成 XST(Cross-Site Tracing)。现代服务器基本都默认关闭 TRACE。

5.9 CONNECT:建立隧道

CONNECT 要求用隧道协议连接代理,常用于 HTTPS 代理:客户端让代理服务器帮忙连到目标主机的 443 端口,之后就在这条 TCP 连接上跑 TLS。

安全视角:开放代理 + CONNECT 可以被滥用为流量跳板;如果代理配置不当,还可能被用来访问内网。

5.10 PATCH:局部更新

PATCH 不在课件的八种方法里,但在现代 API 中很常见,用于对资源做局部更新(区别于 PUT 的整体替换)。

安全视角:PATCH 的”局部更新”语义经常被实现成”把请求体里的字段直接 merge 进对象”,如果没有做字段白名单,攻击者可以顺手改掉 role、isAdmin 这类不该改的字段——这就是 Mass Assignment(批量赋值) 漏洞。

5.11 GET 与 POST 的六个常见误解

这是面试和实战中都容易混淆的地方,单独澄清:

误解 事实
“POST 比 GET 安全” 错。明文 HTTP 下都能被抓包;HTTPS 下都安全。POST 只是不把参数放在 URL 里
“GET 有长度限制” 协议没有限制;限制来自浏览器(IE 约 2KB,Chrome 约 8KB)和服务器(如 Nginx 的首部缓冲区)
“GET 不能带 body” 协议允许,但很多服务器/框架会忽略;不要依赖这种行为
“POST 不能被缓存” 可以缓存,取决于 Cache-Control 等首部;只是浏览器默认不缓存 POST 响应
“GET 只能读,POST 只能写” 这是约定,不是强制。用 GET 删数据、用 POST 查数据都很常见
“GET 是幂等的,所以可以随便重试” 幂等指”多次执行效果相同”,不代表”没有副作用”;日志、计数、审计都会变

5.12 方法层面的攻击面

把上面的”安全视角”汇总一下:

手法 说明
任意方法绕过 WAF 只拦 GET/POST,换一个没被规则覆盖的方法(如 CTFHUB、PATCH)就可能直达后端
方法覆盖 有些框架支持 X-HTTP-Method-Override: PUT,用 POST 冒充 PUT,绕过只检查方法的防护
PUT 写文件 WebDAV、Tomcat CVE-2017-12615 等
DELETE 删资源 配置不当导致任意删除
TRACE 回显 泄露 Cookie、认证头
OPTIONS 探测 获取 Allow、CORS 配置
405 枚举 根据”方法不允许”和”资源不存在”的差异,判断接口是否存在

配套实战篇的第一题”请求方式”考的就是第一条:服务器只允许 GET,题目却让你用 CTFHUB 方法请求。背后的真实场景是:很多 WAF/路由只对已知方法做校验,遇到未知方法要么放行、要么交给后端,从而形成绕过。


六、状态码:响应结果分类

6.1 状态码的结构

客户端向服务器发出请求,状态码用于描述返回的请求结果。它由三位数字和原因短语组成:

HTTP/1.1 200 OK
└┬┘ └┬┘
状态码 原因短语
  • 首位数字表示响应类别;
  • 后两位是具体编号;
  • 原因短语是给人看的说明,程序判断应以数字为准。
类别 含义 常见状态码
1XX 信息性状态码 100 Continue、101 Switching Protocols
2XX 成功 200、201、204、206
3XX 重定向 301、302、303、304、307、308
4XX 客户端错误 400、401、403、404、405、429
5XX 服务器错误 500、501、502、503、504

课件说常用的共 14 种:200、204、206、301、302、303、304、307、400、401、403、404、500、503。下面按类别讲。

6.2 2XX:成功

200 OK

表示从客户端发来的请求在服务器端被正常处理了,浏览器会接着处理、显示返回的数据。

GET /index.html HTTP/1.1
Host: www.sangfor.com.cn
Accept: */*
HTTP/1.1 200 OK
Content-Type: text/html
<html>...

204 No Content

请求已经执行成功,但不需要做任何响应。204 响应会中断浏览器的页面跳转,浏览器保持原 URL 不变,页面内容也维持原状。响应报文中没有实体的主体部分,主要用于”在不跳转页面的情况下更新页面”(比如刷新一个表单页)。

206 Partial Content

客户端进行了范围请求(Range),服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容,由浏览器进行内容整合。

典型场景:断点续传、视频拖动进度条。

GET /video.mp4 HTTP/1.1
Range: bytes=0-1023
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/1024000

6.3 3XX:重定向

3XX 代表重定向状态码,表明浏览器需要执行某些特殊处理才能正确处理请求。课件列了五个:301、302、303、304、307。

301 Moved Permanently(永久重定向)

请求的资源已被分配了新的 URI,以后应使用资源现在所指的 URI。新地址在响应头的 Location 字段中指定。

302 Found(临时重定向)

请求的资源已被分配了新的 URI,希望用户本次能使用新的 URI 访问。与 301 相似,但 302 表示的不是永久移动,已移动资源对应的 URI 将来还可能改变。

HTTP/1.1 302 Found
Location: https://www.example.com/new-path

303 See Other

由于请求对应的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源。303 和 302 功能相同,但 303 明确表示客户端应当采用 GET 方法获取资源。

浏览器在重定向时对 POST 的处理

课件特别指出:

301、302、303 的响应,浏览器都会把 POST 方法替换为 GET 方法,去除请求里的 POST 数据体部分,并自动重新再发送一次请求。

这是浏览器为了兼容历史实现而形成的惯例,不是 HTTP 规范的硬性要求。

307 Temporary Redirect

临时重定向,与 302 含义相同。区别是:307 会遵照浏览器标准,不会从 POST 变成 GET。不过不同浏览器在处理细节上可能不一致,Web 应用里用得不多。

304 Not Modified

客户端发送附带条件的请求时,服务器允许访问资源,但这次请求的文档和之前请求过的版本相比并没有变化。304 返回时,不包含任何响应的主体部分。

它根据 If-Modified-Since 或 If-None-Match 做条件判断,决定浏览器是否需要更新缓存副本。

注意:304 虽然被分在 3XX 里,但它和”重定向”没有关系,本质是”缓存协商”。

6.4 4XX:客户端错误

400 Bad Request

请求报文存在语法错误。需要修改请求内容后再次发送。

401 Unauthorized

发送的请求需要有通过 HTTP 认证的认证信息。如果之前已经请求过一次,则表示用户认证失败。

含有 401 的响应必须包含一个适用于被请求资源的 WWW-Authenticate 首部,用以质询用户信息:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted Area"

浏览器收到这个响应后,会弹出登录框;用户输入后,浏览器把 用户名:密码 做 Base64 编码,放进 Authorization 首部重新发送:

Authorization: Basic YWRtaW46Y2hlbHNlYQ==

CTFHub 的”基础认证”题考的就是这套机制。

403 Forbidden

对请求资源的访问被服务器拒绝了。服务器没有必要给出拒绝的详细理由;如果想说明,可以在实体的主体部分描述原因。

出现 403 的常见原因:

  • 未获得文件系统的访问授权;
  • 访问权限配置有问题;
  • 所请求的 URL 存在但不能被访问(文件权限不足、规则不允许、授权不足)。

404 Not Found

服务器上无法找到请求的资源,或者服务端拒绝请求但又不想说明理由时使用。通常响应消息体会显示给用户。

403 与 404 的区别:403 表示资源存在但当前身份无权访问;404 表示资源不存在,或服务端不愿暴露其存在。安全上,很多系统用 404 掩盖 403,避免攻击者通过状态码枚举资源。

6.5 5XX:服务器错误

500 Internal Server Error

服务器端在执行请求时发生了错误,也可能是 Web 应用存在 bug 或某些临时故障。

503 Service Unavailable

服务器暂时处于超负载或正在停机维护,现在无法处理请求。可以通过 Retry-After 首部告知客户端重试时间。

6.6 状态码的安全视角

状态码不只是”结果说明”,它也是信息源和攻击面:

状态码 攻击者能读出什么 可能的利用
200 资源存在、请求成功 结合响应体找信息泄露
204 请求被接受但无内容 探测接口、判断逻辑
206 支持范围请求 资源枚举、内容截取
301/302 跳转目标 开放重定向、钓鱼、OAuth token 泄露
304 缓存有效 缓存投毒、判断资源是否变化
400 请求格式问题 探测解析规则、模糊测试
401 需要认证 触发登录框、暴力破解
403 存在但禁止访问 目录/文件枚举、绕过尝试
404 不存在 目录扫描的基线
405 方法不允许 判断接口支持的请求方法
500 服务器内部错误 报错注入、堆栈泄露、探测注入点
503 服务不可用 判断维护窗口、DoS 效果

几个典型场景:

  • 开放重定向:/login?next=https://evil.com 返回 302 到外部站点,常被用于钓鱼和 OAuth 授权码窃取;
  • 认证绕过:某些框架在 302 跳转时没有正确校验目标路径,攻击者构造 next=//evil.com 或 next=/\evil.com 绕过校验;
  • 目录枚举:403/404/200 的差异能帮攻击者画出目录结构;
  • 报错注入:500 页面如果带 SQL 报错,就是注入的”回显通道”。

七、一次请求的完整过程

课件把 HTTP 请求过程拆成八步:

浏览器输入 URL
↓
DNS 域名解析
↓
建立 TCP 连接
↓
发送 HTTP 请求
↓
Web 服务器响应
↓
应用服务器响应
↓
关闭 TCP 连接
↓
浏览器渲染页面

下面把每一步展开,并标出安全上值得关注的点。

7.1 输入 URL:浏览器先看缓存

用户在地址栏输入 URL 后,浏览器并不是立刻发请求,而是先做几件事:

  1. 解析 URL,判断协议、主机、端口、路径;
  2. 检查浏览器缓存(强缓存、协商缓存);
  3. 检查 HSTS 列表:如果该域名在 HSTS 列表里,浏览器会把 http:// 强制升级为 https://;
  4. 检查 Service Worker 缓存;
  5. 都没有命中,才进入 DNS 解析。

安全视角:HSTS 能防降级攻击,但第一次访问仍然可能被中间人劫持(TOFU 问题),所以有了 HSTS Preload 列表。

7.2 DNS 解析:把域名换成 IP

解析顺序大致是:

浏览器 DNS 缓存
→ 操作系统 DNS 缓存
→ hosts 文件
→ 本地 DNS 服务器(递归查询)
→ 根域名服务器 → 顶级域服务器 → 权威域名服务器

安全视角:

  • 本地 DNS 被劫持 → 访问到钓鱼站;
  • hosts 文件被恶意软件篡改 → 定向劫持;
  • DNS 查询默认明文(UDP 53)→ 可被监听、可被投毒;DoH/DoT 可以缓解;
  • 企业内网常用 DNS 做资产发现和流量管控。

7.3 建立 TCP 连接:三次握手

获得目标 IP 后,浏览器向目标端口发起 TCP 连接:

SYN → SYN+ACK → ACK

如果是 HTTPS,还要在 TCP 之上再做 TLS 握手(见《HTTP 报文与 HTTPS》)。

安全视角:端口开放情况、TCP 指纹、TLS 指纹都可以用来识别目标的操作系统、中间件、CDN。nmap 的 -sS、-O、--script 即用于此类探测。

7.4 发送 HTTP 请求

连接建立后,浏览器按 HTTP 格式发送请求:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, deflate, br
Cookie: session=abc123
Connection: keep-alive

请求里通常包含:

  • 请求行:方法、路径、版本;
  • 首部:Host、UA、Accept、Cookie、Referer 等;
  • 主体:GET 一般为空,POST/PUT 才有。

安全视角:这就是 Burp Suite 里看到的”原始请求”。改方法、改路径、改首部、改 body,所有的 Web 漏洞测试都从这里开始。

7.5 Web 服务器响应

Web 服务器(Nginx/Apache/IIS)先处理请求:

  • 如果是静态资源(HTML、CSS、JS、图片),直接读文件返回;
  • 如果是动态请求(.php、.jsp、.do),转发给应用服务器(Tomcat、PHP-FPM、Node.js 等);
  • 可能还有反向代理、负载均衡、WAF、CDN 在中间。

安全视角:

  • 静态文件的解析漏洞(IIS、Apache、Nginx)出在这一层;
  • 目录遍历、目录列表、备份文件泄露也出在这一层;
  • Server 首部暴露中间件版本,方便攻击者选 CVE;
  • WAF 的规则绕过(编码、分块、方法)也发生在这里。

7.6 应用服务器响应

应用服务器执行业务逻辑:

  1. 解析参数;
  2. 校验身份与权限;
  3. 查询数据库、调用外部服务;
  4. 渲染模板,生成 HTML/JSON;
  5. 返回给 Web 服务器。

安全视角:这是漏洞最密集的一层。

  • 参数没校验 → SQL 注入、命令注入、文件包含;
  • 输出没编码 → XSS;
  • 权限没校验 → 越权;
  • 反序列化没限制 → RCE;
  • 依赖有漏洞 → 供应链攻击。

7.7 关闭 TCP 连接

响应完成后,连接可以关闭(四次挥手),也可以复用(Keep-Alive)。

安全视角:

  • 连接复用提高性能,但也让请求走私、连接池污染成为可能;
  • 慢速连接(Slowloris)可以耗尽服务器连接数;
  • 长连接 + 分块传输可以被用来做”慢速 POST”攻击。

7.8 浏览器渲染页面

浏览器收到 HTML 后:

  1. 解析 HTML,构建 DOM 树;
  2. 解析 CSS,构建 CSSOM;
  3. 执行 JS(可能阻塞解析);
  4. 加载图片、字体、iframe 等子资源;
  5. 布局、绘制、合成。

安全视角:

  • DOM 型 XSS 发生在 JS 执行阶段;
  • CSRF 发生在子资源自动请求阶段;
  • 点击劫持 发生在渲染/合成阶段;
  • 混合内容(HTTPS 页面加载 HTTP 资源)会破坏页面安全性。

7.9 用 Wireshark 看一次请求

抓包时常用的过滤条件:

http # 只看 HTTP
http.request.method == "GET" # 只看 GET 请求
http.host == "example.com" # 按 Host 过滤
tcp.port == 80 # 按端口过滤
tcp.flags.syn == 1 # 看握手包

在 Wireshark 中选中一条 TCP 流(Follow TCP Stream),可以完整查看请求和响应的原始文本。这是理解 HTTP 最快的方式之一,也是分析请求走私、异常首部、分块编码的必备技能。


八、总结

HTTP 的基础可以归纳为三句话:

  1. 它是建立在 TCP 之上的请求-响应式文本协议:默认端口 80,客户端不发起请求,服务端不会主动响应。
  2. 它的语义由请求行、状态行和首部共同表达:请求行包含方法、目标 URL 和协议版本,状态行包含状态码,Cookie 用于在无状态协议上维护会话状态。
  3. 一次访问是一条完整的链路:DNS → TCP → HTTP → Web 服务器 → 应用服务器 → 浏览器渲染,每一环都是观测点和攻击面。

报文长什么样、首部字段怎么读、HTTPS 如何保护传输,见配套文章《HTTP 报文与 HTTPS》。