HTTP 三件事一件都没有:不加密(内容能被看)、不验身份(对方可能是假的)、 不做完整性校验(内容能被改)。它设计的时候是个学术文档协议,没人想到会被拿来转账。
十章讲完了「Web 是怎么搭起来的」。这一章反过来问:搭起来的每一样东西,能被怎么拆。
一、三件缺失的事
第七章已经拆过一遍:明文意味着能被看,不验证身份意味着可能是假的,
没有完整性校验意味着能被改。这三条在攻击视角下更刺眼。
第一个后果是窃听。同一条 Wi-Fi 下的任何人都能看到你请求里的一切:URL、cookie、正文。
8.5.2 那个会话 ID 就在里面。
第二个后果是篡改。
Demo 里把 GET /me 改成 GET /admin、把会话 ID 换成全零,
服务端收到之后照单全收,回的都是 200——它没有任何手段判断这份请求是不是被改过。
第三个后果是伪装。攻击者可以假扮服务器给你返回一个登录页,也可以假扮你给服务器发请求。
HTTP 层面没有「我是谁」这个概念。
二、为什么当年没人管
HTTP 诞生的时候,用途是「共享学术文档」。文档被看、被改都不致命,所以协议里压根没设计这些东西。 等到 Web 变成银行、变成商城、变成公司系统,协议已经铺开了,改不动了——于是补丁打在外面: TLS 包裹传输,cookie 管状态,各种框架管校验。 所以今天你看到的「安全的 Web」是一层层外挂堆出来的,不是协议自带的。 理解这一点,才能理解为什么漏洞总是出在「某一层以为下一层管了」的地方。
三、这一章的分类方式
教材把攻击按「输出转义」「设置缺陷」「会话管理」三类来分(11.2、11.3、11.4), 最后一节讲其他(11.5)。这个分法很好用,因为它对着「哪一层没做好」来的。 输出转义类:服务端把用户输入当成了代码或者结构,于是被注入。 SQL 注入、命令注入、XSS 都属于这一类,也是数量最多的一类。 设置缺陷类:代码本身没错,是配置或者设计漏了。 目录列表没关、报错太详细、跳转不校验——修起来往往只要改一行配置。 会话管理类:身份靠一个 ID,而 ID 能被偷、被固定、被借用。这一类的共同点是「用户什么都没做错」。
四、动手 Demo:把请求改一半,服务端毫不知情
本机起一个服务端,它只回一句话:你带来的 Cookie 是什么。 先发一个正常请求,再把路径和会话 ID 都改掉转发过去,对比服务端看到的和回的。
ORIGIN = req(u'GET', u'/me', [(u'Cookie', u'SESSIONID=8f2a1c9d4e6b7a30')])
TAMPERED = ORIGIN.replace(b'8f2a1c9d4e6b7a30', b'0000000000000000')
TAMPERED = TAMPERED.replace(b'GET /me', b'GET /admin')
send(ORIGIN) # 服务端看到 GET /me + 真会话
send(TAMPERED) # 服务端看到 GET /admin + 全零会话
实跑输出:
--------------------------------------------------------------------
HTTP 没有安全功能:请求在路上能被随便改
--------------------------------------------------------------------
原始请求(客户端以为发出去的东西):
GET /me HTTP/1.1
Host: 127.0.0.1
Cookie: SESSIONID=8f2a1c9d4e6b7a30
中间人改完之后的请求(服务端实际收到的):
GET /admin HTTP/1.1
Host: 127.0.0.1
Cookie: SESSIONID=0000000000000000
服务端对原始请求回 200
服务端对改后请求回 200
第二次服务端看到的 Cookie SESSIONID=0000000000000000
它带的第一行 GET /admin HTTP/1.1
两次都是 200,服务端**完全不知道**中间有人动过。因为 HTTP 是明文,而且它自己不带任何完整性校验。
原始请求三行:GET /me、Host、Cookie: SESSIONID=8f2a1c9d4e6b7a30。
改完还是三行,只是路径变成 /admin、ID 变成十六个零。
两次都回 200。服务端完全不知道中间有人动过——因为它能看到的只有「最后到手的这几行字节」。
这正是第七章那一整章存在的理由:加密、验身份、验完整性,HTTP 一件都没有,只能靠 TLS 在外面裹一层。
换个角度看也很清楚:HTTP 里没有一处签名。
任何能碰到这些字节的人,都能改完再放行,收方无从分辨。
30 秒实验
- 用
curl -v看一次明文 http 请求,注意整段路上都是可读的。 - 把同一个请求换成 https 再抓一次,看还能不能读出内容。
- 想一想:如果只加加密、不加完整性校验,攻击者还能做什么?
常见误区
- 「HTTPS 是 HTTP 的新版本」——是给 HTTP 加了一层 TLS,协议本身没变。
- 「内网就不用管这些」——内网一样能被横向移动,窃听成本同样很低。
- 「HTTP 里带了 cookie 就算认证了」——cookie 只是张纸,谁拿到都能用。
自测三问(点开对答案)
1. HTTP 缺哪三样安全能力? —— 加密(防窃听)、身份验证(防伪装)、完整性校验(防篡改)。 2. 为什么说「安全的 Web 是外挂堆出来的」? —— 协议本身没这些功能,全靠 TLS、cookie、框架一层层补。 3. 这一章的三类分法是什么? —— 输出转义类、设置或设计缺陷类、会话管理疏忽类。第一件要说清的事:客户端提交的一切,都不可信。
- ☐ (本节完,下一节 11.1.2 在客户端即可篡改请求)