2. HTTP协议基础:HTTP请求与响应、状态码、Cookie与Session、HTTPS原理

各位同学好,我是你们这堂课的老朋友。今天咱们聊聊HTTP协议。说实话,搞Web安全这么多年,我见过太多漏洞的根源,其实就是对HTTP协议理解不透彻。你想想看,连通信的规矩都没搞明白,怎么去发现和修复漏洞?

我个人习惯,在讲任何攻击手法之前,先把协议层的东西夯实了。这一章,咱们就把HTTP协议扒开来看一看。嗯,内容不少,但都是干货。

2.1 HTTP请求与响应:客户端和服务器的对话

HTTP协议,说白了就是浏览器(客户端)和服务器之间的一种对话规则。你发一个请求,我回一个响应,就这么简单。但简单背后,藏着很多细节。

2.1.1 HTTP请求报文

一个标准的HTTP请求,长什么样?我直接给你看个例子:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Cookie: sessionid=abc123

这个请求报文,主要包含三部分:

  • 请求行:第一行。包含请求方法(GET)、请求路径(/index.html)、协议版本(HTTP/1.1)。
  • 请求头:从第二行开始,到空行结束。携带了各种元信息,比如浏览器类型、接受的内容类型、Cookie等。
  • 请求体:空行之后的内容。GET请求一般没有请求体,POST请求才会有。
我的经验: 做渗透测试时,我习惯先看请求头里的User-Agent和Referer。很多WAF(Web应用防火墙)就是靠这两个字段做初步判断的。我曾经遇到一个案例,攻击者伪造了Referer头,绕过了简单的防盗链检查。

2.1.2 HTTP响应报文

服务器收到请求后,会返回一个响应。看这个例子:

HTTP/1.1 200 OK
Date: Mon, 23 May 2024 12:00:00 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Set-Cookie: sessionid=xyz789; Path=/

<html>
<body>Hello, World!</body>
</html>

响应报文也分三部分:

  • 状态行:第一行。包含协议版本、状态码(200)、状态描述(OK)。
  • 响应头:携带服务器信息、内容类型、Cookie设置等。
  • 响应体:实际返回的数据,比如HTML页面、JSON数据、图片二进制流等。

2.2 HTTP状态码:服务器的“暗语”

状态码是服务器告诉你“刚才那个请求处理得怎么样了”。我把它分成五类,你记牢了:

状态码范围 类别 常见例子
1xx 信息性 100 Continue(继续发送请求体)
2xx 成功 200 OK(请求成功)、201 Created(资源已创建)
3xx 重定向 301 Moved Permanently(永久重定向)、302 Found(临时重定向)、304 Not Modified(缓存有效)
4xx 客户端错误 400 Bad Request(请求格式错误)、401 Unauthorized(未认证)、403 Forbidden(禁止访问)、404 Not Found(资源不存在)
5xx 服务器错误 500 Internal Server Error(服务器内部错误)、502 Bad Gateway(网关错误)、503 Service Unavailable(服务不可用)
避坑指南: 我曾经在测试一个登录接口时,发现无论密码对不对,都返回200 OK。后来一查,原来是开发把错误信息放在了响应体里,状态码统一用了200。这种做法非常危险,因为WAF和日志系统通常只根据状态码判断请求是否异常。正确的做法是:认证失败返回401,权限不足返回403。

2.3 Cookie与Session:无状态协议下的“记忆术”

HTTP协议本身是无状态的。什么意思?就是服务器默认不记得你是谁。你第一次访问和第二次访问,在服务器看来,完全是两个陌生人。那网站怎么记住你已经登录了呢?靠的就是Cookie和Session。

2.3.1 Cookie:客户端的“小纸条”

Cookie是服务器发给浏览器,然后浏览器存下来的一个小数据片段。每次请求,浏览器都会自动带上它。

看个设置Cookie的例子:

Set-Cookie: sessionid=abc123; Domain=.example.com; Path=/; Expires=Wed, 21 Oct 2025 07:28:00 GMT; HttpOnly; Secure; SameSite=Lax

这里有几个关键属性,我重点说一下:

  • Domain和Path:限定Cookie的作用范围。只有匹配的域名和路径才会发送。
  • Expires/Max-Age:过期时间。不设置的话,就是会话Cookie,浏览器关闭就没了。
  • HttpOnly:禁止JavaScript读取Cookie。这个属性对防御XSS攻击至关重要。
  • Secure:只在HTTPS连接下才发送。
  • SameSite:控制跨站请求时是否发送Cookie。Lax模式可以防御大部分CSRF攻击。
注意: 我见过很多开发者把敏感信息直接放在Cookie里,比如用户名、角色、甚至密码。这是大忌!Cookie是明文存储的(除非你加密),而且容易被篡改。记住:Cookie里只放一个不透明的标识符(比如sessionid),真正的数据放服务端。

2.3.2 Session:服务端的“档案柜”

Session就是服务端为每个用户维护的一份临时数据。流程是这样的:

  1. 用户登录成功后,服务器创建一个Session,并生成一个唯一的Session ID。
  2. 服务器把Session ID通过Set-Cookie发给浏览器。
  3. 浏览器后续请求都带上这个Cookie。
  4. 服务器根据Session ID找到对应的Session数据,就知道你是谁了。

Session数据存在哪里?常见的有:

  • 服务器内存(单机场景,重启就丢)
  • 数据库(持久化,但慢)
  • Redis/Memcached(推荐,快且支持分布式)
我的建议: 生产环境中,Session一定要设置过期时间,并且每次用户操作后要刷新过期时间。我曾经审计过一个系统,Session过期时间设了24小时,结果攻击者拿到一个Cookie后,可以逍遥一整天。另外,用户登出时,一定要销毁服务端的Session,而不仅仅是清除浏览器Cookie。

2.4 HTTPS原理:给HTTP穿上“防弹衣”

HTTP是明文传输的。你想想看,你在咖啡厅连个公共WiFi,输入密码时,旁边的人用个抓包工具就能看到你的密码。这多可怕?HTTPS就是为了解决这个问题。

HTTPS = HTTP + TLS/SSL。TLS协议在HTTP和TCP之间加了一层加密层。它的核心原理,我拆成三步来讲:

2.4.1 第一步:证书验证与密钥交换

浏览器访问一个HTTPS网站时,服务器会先发来一个数字证书。这个证书里包含:

  • 服务器的公钥
  • 证书颁发机构(CA)的签名
  • 域名、有效期等信息

浏览器会验证这个证书是否合法:

  1. 检查证书是否由受信任的CA签发。
  2. 检查域名是否匹配。
  3. 检查证书是否在有效期内。
  4. 检查证书是否被吊销。

验证通过后,浏览器会生成一个随机的“对称密钥”,然后用服务器的公钥加密这个密钥,发给服务器。服务器用自己的私钥解密,得到这个对称密钥。

关键点: 这里用了两种加密技术。非对称加密(公钥/私钥)用来安全地传输对称密钥。对称加密用来加密后续的通信数据。为什么这么设计?因为非对称加密慢,对称加密快。两者结合,既安全又高效。

2.4.2 第二步:对称加密通信

现在,浏览器和服务器都有了同一个对称密钥。后续的所有HTTP请求和响应,都用这个密钥进行加密传输。抓包工具只能看到一堆乱码,无法解密。

2.4.3 第三步:完整性校验

HTTPS不仅加密,还保证数据没有被篡改。TLS协议使用消息认证码(MAC)来校验数据完整性。如果数据在传输过程中被修改了,接收方会发现MAC不匹配,直接丢弃数据包。

避坑指南: 我曾经在项目中遇到一个“HTTPS降级攻击”。攻击者拦截了用户的请求,强制把HTTPS降级为HTTP。用户看到的是http://开头的链接,但没注意,结果密码被窃取了。解决方案很简单:在服务器响应头里加上 Strict-Transport-Security(HSTS)头,告诉浏览器:这个域名只允许HTTPS访问,永远不要用HTTP。

好了,这一章的内容就到这里。HTTP协议是Web安全的基石,你把这些基础打牢了,后面讲SQL注入、XSS、CSRF的时候,你就能理解为什么那些攻击能成功,以及怎么防御。下一章,咱们聊聊“同源策略与跨域问题”,这也是个容易踩坑的地方。