📘 第十一章 Web的攻击技术
📄 一句话概括

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 秒实验

  1. 用 curl -v 看一次明文 http 请求,注意整段路上都是可读的。
  2. 把同一个请求换成 https 再抓一次,看还能不能读出内容。
  3. 想一想:如果只加加密、不加完整性校验,攻击者还能做什么?

常见误区

  1. 「HTTPS 是 HTTP 的新版本」——是给 HTTP 加了一层 TLS,协议本身没变。
  2. 「内网就不用管这些」——内网一样能被横向移动,窃听成本同样很低。
  3. 「HTTP 里带了 cookie 就算认证了」——cookie 只是张纸,谁拿到都能用。
自测三问(点开对答案) 1. HTTP 缺哪三样安全能力? —— 加密(防窃听)、身份验证(防伪装)、完整性校验(防篡改)。 2. 为什么说「安全的 Web 是外挂堆出来的」? —— 协议本身没这些功能,全靠 TLS、cookie、框架一层层补。 3. 这一章的三类分法是什么? —— 输出转义类、设置或设计缺陷类、会话管理疏忽类。

第一件要说清的事:客户端提交的一切,都不可信。

相关笔记