- 文档
- 网络安全
- 教程
【免费下载链接】Learn-Web-Hacking
Study Notes For Web Hacking / Web安全学习笔记
HTTP 协议簇是 Web 安全的基石,无论是信息收集、漏洞挖掘还是流量分析,都建立在对 HTTP 报文、头字段、状态码与各版本特性的理解之上。本文以 Learn-Web-Hacking 仓库中 HTTP 协议簇笔记 为主线,系统梳理 HTTP 报文格式、请求/响应头字段、状态码语义、版本演进脉络,并延伸讲解 HTTPS、Cookie、WebSocket、WebDAV 等核心子主题及其在 Web 安全实战中的攻防意义,帮助读者建立从协议到漏洞的完整知识链路。
HTTP 标准与报文格式
HTTP(HyperText Transfer Protocol)是基于 TCP/IP 协议栈的应用层协议,主要规定客户端与服务器之间的通信格式,默认使用 80 端口。HTTP 报文分为请求报文与响应报文两类,二者结构高度对称,均由起始行(start line)、头部(headers)与可选的实体主体(entity-body)三部分组成。
请求报文格式
请求报文的起始行为请求行,格式如下:
<method><request-URL><version> <headers> <entity-body><method>:HTTP 动词(请求方法);<request-URL>:请求的目标资源地址;<version>:报文使用的 HTTP 版本,格式为HTTP/<major>.<minor>;<headers>:零个或多个请求头字段,每个字段形如Name: value,以回车换行(CRLF)分隔;<entity-body>:可选的请求体,与请求头之间以空行分隔。
响应报文格式
响应报文的起始行为状态行,格式如下:
<version><status><reason-phrase> <headers> <entity-body><version>:服务器使用的 HTTP 版本;<status>:三位数字状态码;<reason-phrase>:状态码对应的原因短语(如 OK、Not Found);<headers>与<entity-body>结构与请求报文一致。
字段解释
method(HTTP 动词)
- 常见方法:
HEAD/GET/POST/PUT/DELETE/PATCH/OPTIONS/TRACE; - 扩展方法:
LOCK/MKCOL/COPY/MOVE(多由 WebDAV 扩展引入)。
version(HTTP 版本)
- 报文使用的 HTTP 版本,格式为
HTTP/<major>.<minor>,例如HTTP/1.1。
url(统一资源定位符)
URL 的完整语法格式为:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>各组成要素包括:协议(scheme,如 http/https)、认证信息(user:password@)、主机(host)、端口(port)、路径(path)、参数(params,以分号分隔)、查询串(query,以问号分隔)与片段标识(frag,以井号分隔)。
请求头字段详解
请求头由客户端发送,用于向服务器描述自身的期望、能力与附带的会话信息。完整请求头列表如下:
| 字段 | 含义 | 示例 |
|---|---|---|
| Accept | 指定客户端能够接收的内容类型 | Accept: text/plain, text/html |
| Accept-Charset | 浏览器可以接受的字符编码集 | Accept-Charset: iso-8859-5 |
| Accept-Encoding | 指定浏览器可以支持的 Web 服务器返回内容压缩编码类型 | Accept-Encoding: compress, gzip |
| Accept-Language | 浏览器可接受的语言 | Accept-Language: en,zh |
| Accept-Ranges | 可以请求网页实体的一个或多个子范围字段 | Accept-Ranges: bytes |
| Authorization | HTTP 授权的授权证书 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
| Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control: no-cache |
| Connection | 表示是否需要持久连接(HTTP/1.1 默认进行持久连接) | Connection: close |
| Cookie | HTTP 请求发送时,把保存在该请求域名下的所有 Cookie 值一起发送给 Web 服务器 | Cookie: role=admin;ssid=1 |
| Content-Length | 请求的内容长度 | Content-Length: 348 |
| Content-Type | 请求的与实体对应的 MIME 信息 | Content-Type: application/x-www-form-urlencoded |
| Date | 请求发送的日期和时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
| Expect | 请求的特定服务器行为 | Expect: 100-continue |
| From | 发出请求的用户的 Email | From: user@email.com |
| Host | 指定请求的服务器的域名和端口号 | Host: www.github.com |
| If-Match | 只有请求内容与实体相匹配才有效 | If-Match: "737060cd8c284d8af7ad3082f209582d" |
| If-Modified-Since | 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回 304 代码 | If-Modified-Since: Sat, 29 Oct 2018 19:43:31 GMT |
| If-None-Match | 如果内容未改变返回 304 代码,参数为服务器先前发送的 Etag,与服务器回应的 Etag 比较判断是否改变 | If-None-Match: "737060cd8c284d8af7ad3082f209582d" |
| If-Range | 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体,参数也为 Etag | If-Range: "737060cd8c284d8af7ad3082f209582d" |
| If-Unmodified-Since | 只在实体在指定时间之后未被修改才请求成功 | If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
| Max-Forwards | 限制信息通过代理和网关传送的时间(跳数) | Max-Forwards: 10 |
| Pragma | 用来包含实现特定的指令 | Pragma: no-cache |
| Proxy-Authorization | 连接到代理的授权证书 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
| Range | 只请求实体的一部分,指定范围 | Range: bytes=500-999 |
| Referer | 先前网页的地址,当前请求网页紧随其后,即来路 | Referer: http://www.zcmhi.com/archives/71.html |
| TE | 客户端愿意接受的传输编码,并通知服务器接受尾加头信息 | TE: trailers,deflate;q=0.5 |
| Upgrade | 向服务器指定某种传输协议以便服务器进行转换(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
| User-Agent | 内容包含发出请求的用户信息 | User-Agent: Mozilla/5.0 (Linux; X11) |
| Via | 通知中间网关或代理服务器地址、通信协议 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
| Warning | 关于消息实体的警告信息 | Warn: 199 Miscellaneous warning |
安全视角下的请求头:在信息收集阶段,User-Agent、Referer、Cookie等字段可用于判断客户端类型与访问来源;Host字段是虚拟主机路由的基础,也是缓存投毒、请求走私等攻击中被反复利用的对象(详见后文安全章节)。
响应头字段详解
响应头由服务器发送,用于描述响应实体的属性、缓存策略与安全约束。完整响应头列表如下:
| 字段 | 含义 | 示例 |
|---|---|---|
| Accept-Ranges | 表明服务器是否支持指定范围请求及哪种类型的分段请求 | Accept-Ranges: bytes |
| Access-Control-Allow-Origin | 配置有权限访问资源的域 | Access-Control-Allow-Origin: <origin>\|* |
| Age | 从原始服务器到代理缓存形成的估算时间(以秒计,非负) | Age: 12 |
| Allow | 对某网络资源的有效请求行为,不允许则返回 405 | Allow: GET, HEAD |
| Cache-Control | 告诉所有的缓存机制是否可以缓存及哪种类型 | Cache-Control: no-cache |
| Content-Encoding | Web 服务器支持的返回内容压缩编码类型 | Content-Encoding: gzip |
| Content-Language | 响应体的语言 | Content-Language: en,zh |
| Content-Length | 响应体的长度 | Content-Length: 348 |
| Content-Location | 请求资源可替代的备用的另一地址 | Content-Location: /index.htm |
| Content-MD5 | 返回资源的 MD5 校验值 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
| Content-Range | 在整个返回体中本部分的字节位置 | Content-Range: bytes 21010-47021/47022 |
| Content-Type | 返回内容的 MIME 类型 | Content-Type: text/html; charset=utf-8 |
| Date | 原始服务器消息发出的时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
| ETag | 请求变量的实体标签的当前值 | ETag: "737060cd8c284d8af7ad3082f209582d" |
| Expires | 响应过期的日期和时间 | Expires: Thu, 01 Dec 2010 16:00:00 GMT |
| Last-Modified | 请求资源的最后修改时间 | Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT |
| Location | 用来重定向接收方到非请求 URL 的位置来完成请求或标识新的资源 | Location: http://www.zcmhi.com/archives/94.html |
| Pragma | 包括实现特定的指令,可应用到响应链上的任何接收方 | Pragma: no-cache |
| Proxy-Authenticate | 指出认证方案和可应用到代理的该 URL 上的参数 | Proxy-Authenticate: Basic |
| Refresh | 应用于重定向或新的资源被创建,在 5 秒之后重定向(由网景提出,被大部分浏览器支持) | Refresh: 5; url=http://www.zcmhi.com/archives/94.html |
| Retry-After | 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 | Retry-After: 120 |
| Server | Web 服务器软件名称 | Server: Apache/1.3.27 (Unix) (Red-Hat/Linux) |
| Set-Cookie | 设置 HTTP Cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
| Strict-Transport-Security | 设置浏览器强制使用 HTTPS 访问 | Strict-Transport-Security: max-age=1000; includeSubDomains |
| Trailer | 指出头域在分块传输编码的尾部存在 | Trailer: Max-Forwards |
| Transfer-Encoding | 文件传输编码 | Transfer-Encoding: chunked |
| Vary | 告诉下游代理是使用缓存响应还是从原始服务器请求 | Vary: * |
| Via | 告知代理客户端响应是通过哪里发送的 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
| Warning | 警告实体可能存在的问题 | Warning: 199 Miscellaneous warning |
| WWW-Authenticate | 表明客户端请求实体应该使用的授权方案 | WWW-Authenticate: Basic |
| X-Content-Type-Options | 配置禁止 MIME 类型嗅探 | X-Content-Type-Options: nosniff |
| X-Frame-Options | 配置页面是否能出现在<frame>、<iframe>、<embed>、<object>等标签中,防止点击劫持 | X-Frame-Options: deny |
| X-XSS-Protection | 配置 XSS 防护机制 | X-XSS-Protection: 1; mode=block |
字段细节说明:
Strict-Transport-Security(HSTS)的max-age表示在指定秒数内访问对应域名都使用 HTTPS 请求;includeSubDomains表示网站的子域名也启用该规则。X-Frame-Options用于防止点击劫持(Clickjacking),常见取值有deny(禁止任何页面嵌入)、sameorigin等。- 在站点信息收集时,响应头中的
Server、X-Powered-By等字段可用于判断 Web 容器与后端框架,详见仓库中 站点信息收集笔记。
HTTP 状态返回代码
状态码由三位数字组成,首位数字定义了状态码的类别。RFC 标准将其划分为五类。
1xx(临时响应)
表示临时响应并需要请求者继续执行操作的状态代码。
| Code | 代码 | 说明 |
|---|---|---|
| 100 | 继续 | 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分 |
| 101 | 切换协议 | 请求者已要求服务器切换协议,服务器已确认并准备切换(WebSocket 握手即使用该状态码) |
2xx(成功)
表示成功处理了请求的状态代码。
| Code | 代码 | 说明 |
|---|---|---|
| 200 | 成功 | 服务器已成功处理了请求。通常,这表示服务器提供了请求的网页 |
| 201 | 已创建 | 请求成功并且服务器创建了新的资源 |
| 202 | 已接受 | 服务器已接受请求,但尚未处理 |
| 203 | 非授权信息 | 服务器已成功处理了请求,但返回的信息可能来自另一来源 |
| 204 | 无内容 | 服务器成功处理了请求,但没有返回任何内容 |
| 205 | 重置内容 | 服务器成功处理了请求,但没有返回任何内容 |
| 206 | 部分内容 | 服务器成功处理了部分 GET 请求(与Range请求头配合使用) |
3xx(重定向)
表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。
| Code | 代码 | 说明 |
|---|---|---|
| 300 | 多种选择 | 针对请求,服务器可执行多种操作。服务器可根据请求者(user agent)选择一项操作,或提供操作列表供请求者选择 |
| 301 | 永久移动 | 请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置 |
| 302 | 临时移动 | 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求 |
| 303 | 查看其他位置 | 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码 |
| 304 | 未修改 | 自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容(与If-Modified-Since、If-None-Match配合实现条件请求) |
| 305 | 使用代理 | 请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理 |
| 307 | 临时重定向 | 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求 |
4xx(请求错误)
这些状态代码表示请求可能出错,妨碍了服务器的处理。
| Code | 代码 | 说明 |
|---|---|---|
| 400 | 错误请求 | 服务器不理解请求的语法 |
| 401 | 未授权 | 请求要求身份验证。对于需要登录的网页,服务器可能返回此响应 |
| 403 | 禁止 | 服务器拒绝请求 |
| 404 | 未找到 | 服务器找不到请求的网页 |
| 405 | 方法禁用 | 禁用请求中指定的方法 |
| 406 | 不接受 | 无法使用请求的内容特性响应请求的网页 |
| 407 | 需要代理授权 | 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理 |
| 408 | 请求超时 | 服务器等候请求时发生超时 |
| 409 | 冲突 | 服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息 |
| 410 | 已删除 | 如果请求的资源已永久删除,服务器就会返回此响应 |
| 411 | 需要有效长度 | 服务器不接受不含有效内容长度标头字段的请求 |
| 412 | 未满足前提条件 | 服务器未满足请求者在请求中设置的其中一个前提条件 |
| 413 | 请求实体过大 | 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力 |
| 414 | 请求的 URI 过长 | 请求的 URI(通常为网址)过长,服务器无法处理 |
| 415 | 不支持的媒体类型 | 请求的格式不受请求页面的支持 |
| 416 | 请求范围不符合要求 | 如果页面无法提供请求的范围,则服务器会返回此状态代码 |
| 417 | 未满足期望值 | 服务器未满足“期望”请求标头字段的要求 |
5xx(服务器错误)
这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。
| Code | 代码 | 说明 |
|---|---|---|
| 500 | 服务器内部错误 | 服务器遇到错误,无法完成请求 |
| 501 | 尚未实施 | 服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码 |
| 502 | 错误网关 | 服务器作为网关或代理,从上游服务器收到无效响应 |
| 503 | 服务不可用 | 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态 |
| 504 | 网关超时 | 服务器作为网关或代理,但是没有及时从上游服务器收到请求 |
| 505 | HTTP 版本不受支持 | 服务器不支持请求中所用的 HTTP 协议版本 |
安全视角下的状态码:状态码常被用作信息收集与漏洞探测的信号——401/403 可定位认证与访问控制边界,405 可枚举Allow字段以发现 WebDAV 等方法,5xx 错误页可能泄露中间件版本与路径信息。
HTTP 版本演进
HTTP 协议经历了从简单文本协议到二进制多路复用协议的演进,理解各版本特性有助于判断 Web 应用的性能瓶颈与可被利用的协议特性。
HTTP 0.9
HTTP 0.9 最早在 1991 年发布,仅支持 GET 命令,请求格式只有简单的GET /url,服务端仅响应 HTML,响应完毕后关闭 TCP 连接。此时协议尚未引入版本号、请求头与状态码。
HTTP 1.0
1996 年 5 月,HTTP/1.0 版本发布,丰富了传输的格式和内容,并引入了 POST、HEAD 两个动词。从 1.0 开始,必须在报文尾部添加协议版本。同时,HTTP/1.0 引入了:
- 状态码(status code);
- 多字符集支持;
- 多部分发送(multi-part type);
- 权限(authorization);
- 缓存(cache);
- 内容编码(content encoding)。
HTTP/1.0 版的主要缺点是每个 TCP 连接只能发送一个请求:发送数据完毕连接即关闭,若要请求其他资源必须再新建一个连接。由于 TCP 连接的新建成本很高(需要客户端和服务器三次握手,且开始时发送速率较慢,即 slow start),HTTP/1.0 版本的性能比较差。
HTTP 1.1
1997 年 1 月,HTTP/1.1 版本发布,进一步完善了 HTTP 协议,主要引入了:
- 持久连接(keep-alive):允许复用 TCP 连接;
- 管道机制(pipelining):在同一个 TCP 连接里面,客户端可以同时发送多个请求,改进协议效率;
- Content-Length:用于明确报文边界;
- 分块传输编码(chunked transfer encoding):允许响应体按块流式传输;
- 新方法:PUT、PATCH、HEAD、OPTIONS、DELETE 等动词方法在 HTTP/1.1 版本引入;
- Host 字段:用于指定服务器的域名,这也是后来虚拟主机得以发展的基础。
HTTP/1.1 的局限在于:虽然允许复用 TCP 连接,但同一个 TCP 连接里面所有的数据通信按次序进行,服务器只有处理完一个回应才会进行下一个回应。如果有一个请求很慢,就会阻塞后面的请求,即队头阻塞(head-of-line blocking)问题。
SPDY
2009 年,谷歌公开了自行研发的 SPDY 协议,用于解决 HTTP/1.1 效率不高的问题,后被当做 HTTP/2 的基础。
HTTP/2
2015 年,HTTP/2 发布。HTTP/2 是一个二进制协议,头信息和数据体都是二进制,统称为帧(frame),帧分为头信息帧和数据帧。HTTP/2 复用 TCP 连接,在一个连接里客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序回应,从机制上缓解了 HTTP/1.1 的队头阻塞问题。
HTTPS 与 SSL/TLS
HTTPS(HyperText Transfer Protocol over Secure Socket Layer)可以理解为 HTTP + SSL/TLS,即在 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL/TLS。默认使用 443 端口。仓库中关于 SSL/TLS 的更深入内容参见 SSL/TLS 笔记。
证书验证阶段
- 浏览器发起 HTTPS 请求;
- 服务端返回 HTTPS 证书,其中证书包含:颁发机构信息、公钥、公司信息、域名、有效期、指纹;
- 客户端验证证书是否合法,如果不合法则提示告警。
数据传输阶段
- 当证书验证合法后,客户端在本地生成随机数;
- 客户端通过公钥加密随机数,并把加密后的随机数传输到服务端;
- 服务端通过私钥对随机数进行解密;
- 服务端通过客户端传入的随机数构造对称加密算法,对返回结果内容进行加密后传输。
CA(证书颁发机构)
CA(Certificate Authority)是颁发数字证书的机构,是负责发放和管理数字证书的权威机构,并作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任。
安全视角下的 HTTPS:HTTPS 保护的是传输层点对点安全,其安全目标包括认证性(借助数字证书认证服务端和客户端身份,防止身份伪造)、机密性(借助加密防止第三方窃听)、完整性(借助消息认证码 MAC 保障数据完整性,防止消息篡改)与重放保护(通过隐式序列号防止重放攻击)。HSTS(Strict-Transport-Security头)可强制浏览器使用 HTTPS 访问,防止 SSL Stripping 降级攻击。
Cookie 机制
Cookie(复数形态 Cookies)类型为“小型文本文件”,指某些网站为了辨别用户身份而储存在用户本地终端上的数据。Cookie 通过Set-Cookie响应头设置,并由客户端在后续请求中通过Cookie请求头携带。
Cookie 属性
| 属性 | 说明 |
|---|---|
| name | Cookie 的名称 |
| value | Cookie 的值 |
| expires | 过期时间。当 Expires 属性缺省时,表示是会话性 Cookie,在用户关闭浏览器时失效 |
| max-age | 可以为正数、负数、0。为正数时浏览器会将其持久化;为负数时表示该 Cookie 只是一个会话性 Cookie;为 0 时会立即删除该 Cookie。Expires 和 max-age 都存在时,max-age 优先级更高 |
| domain | 指定 Cookie 的域名,默认是当前域名。domain 设置时可以设置为自身及其父域,子域可以访问父域的 Cookie,反之不能 |
| path | 指定一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送对应的 Cookie |
| secure | 只能通过 HTTPS 传输 |
| httponly | 限制 Cookie 仅在 HTTP 传输过程中被读取,一定程度上防御 XSS 攻击 |
| SameSite | 支持 Strict / Lax / None 三种值。Strict 最为严格,完全禁止第三方 Cookie,跨站点时任何情况下都不会发送 Cookie;Lax 允许部分第三方请求携带 Cookie,主要是链接、预加载、GET 表单三种情况;SameSite 属性为 None 且设置了 Secure 时,无论是否跨站都会发送 Cookie |
安全视角下的 Cookie
- httponly 的绕过与限制:在 Cookie 为 httponly 的情况下,攻击者仍可通过 XSS 直接在源站完成操作而不获取 Cookie;有登录操作的站点部分情况下直接发送登录请求可能带有 Cookie;特定版本的浏览器可能在 httponly 支持/处理上存在问题;低版本浏览器支持 TRACE / TRACK 方法,可获取敏感的 header 字段;phpinfo 等页面可能回显包含 HTTP 头的服务器信息;还可通过 XSS 劫持页面钓鱼、伪造 OAuth 等授权请求实现远程登录。详见仓库 httponly 笔记。
- CSRF 与 Cookie:跨站请求伪造(CSRF)依赖浏览器自动携带目标站点 Cookie 的特性,通过资源包含(
<img>、<script>等标签)、表单自动提交或 XMLHttpRequest 伪造受害者请求。防御上可借助 CSRF token、验证码、校验 Referer/Content-Type、对修改类操作强制使用 POST,并避免全站通用 Cookie、严格设置 Cookie 的域。详见仓库 CSRF 笔记。 - 同源策略与 Cookie:Cookie 使用与页面不同的源定义方式——页面可以为本域和任何父域设置 Cookie(只要父域不是公共后缀)。不管使用哪个协议(HTTP/HTTPS)或端口号,浏览器都允许给定域及其任何子域名访问 Cookie,因此
https://localhost:8080/与http://localhost:8081/的 Cookie 是共享的。详见仓库 同源策略笔记。
WebSocket
WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。
握手过程
握手阶段和 HTTP 协议较为类似,RFC 文档中给出的握手示例如下。
客户端请求:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13服务端响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=关键点:
Upgrade的值必须为websocket,Connection的值必须为Upgrade,合起来表示客户端希望将连接升级到 WebSocket 协议;Sec-WebSocket-Key是一个随机值;Sec-WebSocket-Accept是Sec-WebSocket-Key拼接特定字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11计算 SHA1 摘要后的 Base64 编码值。示例中s3pPLMBiTxaQ9kYGzzhZRbK+xOo=就是dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11对应的 SHA1 摘要。
握手完成后,连接状态码切换为 101,双方在既有的 TCP 连接上开始全双工的数据帧通信。从协议角度看,WebSocket 握手本质上是借助 HTTP 的Upgrade/Connection头完成的协议升级——这一点与Upgrade请求头字段的语义(向服务器指定某种传输协议以便转换)完全对应。
WebDAV
WebDAV(Web-based Distributed Authoring and Versioning)是一种基于 HTTP/1.1 协议的通信协议。它扩展了 HTTP/1.1,在 GET、POST、HEAD 等几个 HTTP 标准方法以外添加了一些新的方法,使应用程序可对 Web Server 直接读写,并支持写文件锁定、解锁以及版本控制等功能。
支持的方法
| 方法 | 用途 |
|---|---|
| OPTIONS | 获取服务器的支持能力 |
| GET / PUT / POST / DELETE | 资源操作 |
| TRACE | 跟踪服务器 |
| HEAD | 获取响应头 |
| MKCOL | 创建集合(目录) |
| PROPFIND / PROPPATCH | 获取/设置资源属性 |
| COPY / MOVE | 复制/移动资源 |
| LOCK / UNLOCK | 锁定/解锁资源 |
相关 CVE
- CVE-2015-1833:Apache Jackrabbit WebDAV XXE;
- CVE-2015-7326:Milton WebDAV XXE。
安全视角下的 WebDAV:WebDAV 扩展方法(尤其 PUT、PROPFIND、MOVE、COPY)常被用于向服务器写入 WebShell 或探测目录结构,是中间件与文件上传攻防中需要重点探测的能力面。若服务器错误开放了 WebDAV 且未做认证与上传限制,攻击者可直接通过 PUT 上传恶意文件,或以 PROPFIND 枚举服务器目录信息。
HTTP 协议簇的安全攻防纵深
围绕 HTTP 协议本身还存在多个高价值攻击面,仓库笔记中均有对应章节,在此梳理其与上述协议机制的关联。
HTTP 请求走私
HTTP 请求走私是一种干扰网站处理 HTTP 请求序列方式的技术,最早在 2005 年的一篇文章中被提出。请求走私大多发生于前端服务器和后端服务器对客户端传入的数据理解不一致的情况——这是因为 HTTP 规范提供了两种不同的方法来指定请求的结束位置,即Content-Length和Transfer-Encoding标头。分类与典型攻击形态如下:
- CLTE:前端服务器使用
Content-Length头,后端服务器使用Transfer-Encoding头; - TECL:前端服务器使用
Transfer-Encoding标头,后端服务器使用Content-Length标头; - TETE:前端和后端服务器都支持
Transfer-Encoding标头,但可以通过某种方式诱导其中一个服务器不处理它。
例如 CL 不为 0 的 GET 请求场景:当前端服务器允许 GET 请求携带请求体,而后端服务器不允许时,后者会忽略 GET 请求中的Content-Length头。前端按Content-Length解析,后端则基于 pipeline 机制把剩余内容视为独立请求,从而造成请求拼接与走私。仓库中 HTTP 请求走私笔记 给出了 CL-CL、CL-TE、TE-CL、TE-TE 等完整攻击报文示例,防御要点包括:禁用后端连接重用、确保连接中所有服务器配置一致、拒绝有二义性的请求。
Web Cache 欺骗攻击
Web Cache 欺骗攻击与 RPO 相对路径重写攻击类似,都依赖浏览器与服务器对 URL 的解析方式。当访问不存在的 URL(如http://www.example.com/home.php/non-existent.css)时,服务器可能返回home.php的内容,同时 URL 地址仍为请求中的不存在路径,且 HTTP 头(缓存头、Content-Type等)与直接访问home.php相同。若代理服务器按扩展名缓存静态文件并忽略 caching header,个人敏感页面就可能被缓存并被公开访问。防御要点包括:仅缓存 HTTP caching header 允许的文件、按 content-type 缓存、对不存在的页面返回 404 或 302。详见仓库 Web Cache 欺骗攻击笔记。
CORS 与跨源安全
跨域资源共享(CORS)通过响应头Access-Control-Allow-Origin等字段允许浏览器读取跨域资源。安全配置建议包括:如非必要不开启 CORS、定义详细白名单不使用通配符、配置Vary: Origin头、如非必要不使用Access-Control-Allow-Credentials、限制缓存时间。仓库 同源策略笔记 中给出了 CORS 常见请求头与响应头的完整说明。
小结
本文以仓库 HTTP 协议簇笔记 为核心,完整覆盖了 HTTP 报文格式、请求/响应头字段、五类状态码语义、HTTP/0.9 至 HTTP/2 的版本演进,并延伸到 HTTPS 证书体系、Cookie 属性、WebSocket 握手与 WebDAV 扩展方法。在安全实战层面,理解Content-Length/Transfer-Encoding的边界判定、Cookie 的 SameSite/httponly 语义、状态码的语义差异与版本特性差异,是分析请求走私、缓存欺骗、CSRF、XSS 等漏洞的必备前提。建议按仓库笔记大纲顺序,先掌握本部分协议基础,再结合 常见漏洞攻防 与 SSL/TLS 等章节进行交叉学习,即可建立从协议到攻防的完整知识链路。
- 文档
- 网络安全
- 教程
【免费下载链接】Learn-Web-Hacking
Study Notes For Web Hacking / Web安全学习笔记
相关推荐
深入理解 HTTP 协议:报文格式、请求/响应头与状态码全解析(Learn-Web-Hacking 安全学习笔记)
深入理解 HTTP 协议:报文格式、请求/响应头与状态码全解析(Learn Web Hacking 安全学习笔记) 导读 HTTP(HyperText Tran
文档网络安全教程HTTP 协议版本演进完全指南:从 HTTP/0.9 到 HTTP/2(Learn-Web-Hacking 学习笔记)
HTTP 协议版本演进完全指南:从 HTTP/0.9 到 HTTP/2(Learn Web Hacking 学习笔记) 本文以 Learn Web Hackin
文档网络安全教程SSL/TLS 协议基础与 Web 安全实战解析(Learn-Web-Hacking 学习笔记)
SSL/TLS 协议基础与 Web 安全实战解析(Learn Web Hacking 学习笔记) 本文是 Learn Web Hacking https://l
文档网络安全教程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考