Web协议详解与抓包实战之HTTP1.1【一】
前言
《Web协议详解与抓包实战》课程学习,陶辉老师主讲
学习内容:
-
HTTP–TLS/SSL–TCP/IP自上而下根据应用学习web协议HTTP1.1详细知识
-
结合抓包工具实践验证:chrome下的network面板、Tcpdump、Wireshark
文章目录
HTTP协议
定义:一种无状态的、应用层的、以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动
a stateless application-level request/response protocol that uses extensible semantics and self-descriptive message payloads for flexible interaction with network-based hypertext information systems (RFC7230 2014.6)
ABNF规则
HTTP协议格式:ABNF(扩充巴科斯-瑙尔范式)核心规则,如果不严格遵守ABNF规则,日常工作中则会遇到很多错误~
-
操作符
-
核心规则
HTTP协议格式
OSI概念模型
概念,就是没真正实现,但是必须参考
TCP/IP模型
OSI实际上在互联网的实现就是TCP/IP模型
好处:每一层隔离,只与相邻的层进行交互,其他不用管
缺点:数据处理影响性能
Web架构
本小节等学完等个课程之后在进行补充~
评估Web架构的关键属性
- 性能 Performance
- 可伸缩性 Scalability
- 简单性 Simplicity
- 可见性 Visiable
- 可移植性 Portability
- 可靠性 Reliability
- 可修改性 Modifiability:对系统做出修改的难易程度
5种架构风格
- 数据流风格 Data-flow Styles
- 优点:简单性、可进化性、可扩展性
- 复制风格 Replication Styles
- 分层风格 Hierarchical Styles
- 移动代码风格 Mobile Code Styles
- 点对点风格 Peer-to-Peer Styles
使用Chrome的Network面板
URI格式
URI定义
URI格式
- 组成:scheme, user information, host, port, path, query, fragment
-
URI的ABNF定义
-
四部分组成:scheme, hier-part, query, fragment
-
其中hier-part格式中的authority:
-
其中hier-part格式中的path:
-
-
-
URI与相对URI
URI与URL的关系
HTTP响应码
响应码规范 RFC6585(2012.4)、RFC7231(2014.6)
- 1xx:请求已接收到,需要进一步处理才能完成,HTTP1.0不支持
- 2xx:成功处理请求
- 3xx:重定向使用Location指向的资源或者缓存中的资源。RFC规范中规定客户端重定向次数不应超过5次,以防止死循环
- 4xx:客户端出现错误
- 5xx:服务器端出现错误
- 5xx:服务器端出现错误
后续课程学习中罗列表格进行详细分类!
传输HTTP包体
定长包体:
Content-Length头部明确指明包体长度
- 用10进制表示包体中的字节个数,且必须与实际传输的包体长度一致
使用python socket建立server环境:
'''
Author: f4ke
Date: 2020-11-11 11:00:31
LastEditTime: 2020-11-11 11:32:40
LastEditors: Please set LastEditors
Description: python server_test content-length
FilePath: \python\http_test\testsvr.py
'''
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ("127.0.0.1", 12345)
sock.bind(server_address)
sock.listen(100)
while True:
conn,client_address = sock.accept()
print(conn,client_address)
try:
data = conn.recv(4096)
response = 'HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHelloWorld'
conn.send(response.encode())
finally:
conn.close()
Content-Length小于实际传输包体长度HTTP协议会进行截断
Content-Length大于实际传输包体长度浏览器报错,wireshark抓包如下图
PS: 一般情况下waf是基于Content-Length进行处理,当不使用Content-Length方式时可绕过waf直接访问服务器或数据库
非定长包体
-
发送HTTP消息时不能确定包体的全部长度
- 使用Transfer-Encoding头部指明使用Chunk传输方式
- 含Transfer-Encoding头部后Content-Length头部将被忽略
- 使用Transfer-Encoding头部指明使用Chunk传输方式
-
优点:
- 基于长连接持续推送动态内容
- 压缩体积较大的包体时,不必完全压缩完在发送,可边发送边压缩
- 传递必须在包体传输完才能计算出的Trailer头部
-
chunk传输的格式
待更新:这里延伸出一种漏洞利用方式,分块传输绕过waf直接对数据库进行访问
HTML FORM表单
- HTML并非变成语言,本身没有交互能力与HTTP协议无关
- FORM表单:HTML中的元素,提供了交互控制元件用来向服务器通过HTTP协议提交信息
- 常见控件:
- Text Input Controls:文本输入文件
- Checkboxes Controls:复选框控件
- Radio Box Controls:单选按钮控件
- Select Box Controls:下拉列表控件
- File Select boxes:选取文件控件
- Clickable Buttons:可点击的按钮控件
- Submit(直接发起HTTP请求) and Reset Buttons:提交或重置按钮控件
- 三个核心属性
- action:提交时发起HTTP请求的URI
- method:提交时发起HTTP请求的http方法
- GET
- POST
- enctype:在POST方法下,对表单内容在请求包体中的编码方式
- application/x-www-form-urlencoded(默认)
- 数据被编码成以’&‘分隔的键值对,同时以’='分隔键和值,字符以URL编码方式编码
- multipart(一个包体中多个资源表述)/form-data
- header
- multipart包体格式
- header
- application/x-www-form-urlencoded(默认)
- 常见控件:
断点续传/多线程下载
HTTP Range规范:RFC7233
- 允许服务器基于客户端的请求只发送响应包体的一部分给到客户端,而客户端自动将多个片段的包体组合成完整的体积更大的包体
- 支持断点续传
- 支持多线程下载
- 支持视频播放器实时拖动
- 服务器通过Accept-Range头部表示是否支持Range请求
- Accept-Ranges = acceptable-ranges
- Accept-Ranges: bytes(支持)
- Accept-Ranges: none(不支持)
- Accept-Ranges = acceptable-ranges
使用burp抓包进行实验:
- 如果客户端已经获得Range响应的一部分,想在这部分响应未过期的情况下,获取其他部分的响应
- 常与if-Unmodified-Since或者If-Match头部共同使用
若与之前的ETag字段的值不同,则如下图,服务器返回412条件匹配失败
-
服务器响应
-
206 Partial Content
-
Content-Range头部:显示当前片段包体在完整包体中的位置
-
正好结合B站的视频,在network面板中查看响应包
-
-
多重范围与multipart(与form表单中的多资源表述类似)
- 请求
- Range: bytes=0-50,60-100
- 响应
- Content-Type: multipart/byteranges; boundary=…
- 请求
-
Cookie与Session
RFC6265,HTTP的状态管理机制,保存在客户端,由浏览器维护、表示应用状态的HTTP头部
- 存放在内存或磁盘中
- 服务器端生成Cookie在响应中通过Set-Cookie头部告知客户端
- 客户端得到Cookie后,后续请求会自动携带进请求头中
Cookie与Set-Cookie头部的格式
Cookie使用的限制
- RFC规范对浏览器使用Cookie的要求
- 每条Cookie的长度支持要达到4KB
- 每个域名下至少支持50个Cookie
- 至少要支持3000个Cookie
登录场景下的常见用法
- cookie保存在客户端
- session保存在服务端
第三方Cookie
浏览器允许对于不安全域(非当前访问域)下的资源响应中的Set-Cookie字段进行保存,并在后续访问该域时自动使用Cookie
因为这个浏览器机制常见场景:偷取用户的浏览信息,例如在社交平台发布的内容涉及物品很容易在电商平台上被推荐
由此,为了避免这个问题,浏览器有了同源策略,在其基础上又因为正常服务的访问需求产生了跨域访问
同源策略
限制了从同一个源加载的文档或脚本与来自另一个源的资源进行交互
- 协议、主机、端口必须完全相同
同源策略在可用性和安全性寻找平衡点
-
可用性:HTML的创作者决定跨域请求是否对本站点安全
-
<script><img><iframe><link><video><audio> // 带有src属性浏览器允许进行跨域访问
-
浏览器允许跨域写操作:表单提交或者重定向请求
- CSRF攻击
- 防护方式:浏览器的referrer字段或者下图CSRF token
- CSRF攻击
-
-
安全性:浏览器需要防止站点A的脚本向站点B发起危险动作
- Cookie、LocalStorage和IndexDB无法读取
- DOM无法获得
- AJAX请求不能发送
通过CORS跨域访问
实现跨域访问有很多解决方案,RFC规范或HTTP架构中推荐CORS方案
CORS:Cross-Origin Resource Sharing
-
浏览器同源策略下的跨域访问解决方案
-
如果站点A允许站点B的脚本访问其资源,必须在HTTP响应中显式的告知浏览器:站点B是被允许的
-
两类HTTP请求
-
简单请求的跨域访问
- 请求中携带Origin头部告知来自哪个域
- 响应中携带Access-Control-Allow-Origin头部表示允许 哪些域
- 浏览器放行并进行渲染展示,(不在Access-Control-Allow-Origin头部中的域名浏览器拦截)
预检请求
先进行预检请求,在进行实际的请求
跨域资源访问:请求头部
跨域资源访问:响应头部
Precondition条件请求
目的:
- 由客户端携带条件判断信息,而服务器预执行条件验证过程成功后,在返回资源的表述
常见应用场景
- 缓存的更新更有效率
- 断点续传时对之前内容的验证
- 多个客户端并行修改同一资源时,防止某一客户端的更新被错误丢弃
验证器 validator
根据客户端请求中携带的相关头部,以及服务器资源的信息,执行两端的资源验证
- 强验证器:服务器上的资源表述只要有变动,以旧的验证头部访问一定会导致验证不过
- 弱验证器:服务器上资源变动时,允许一定程度上仍然可以验证通过
验证器响应头部
-
Etag响应头部:用来帮助服务器控制Web端的缓存验证
-
Last-Modified响应头部
条件请求头部
- If-None-Match
验证请求与响应
Nginx处理条件请求的规则
缓存
HTTP缓存:为当前请求复用前请求的响应
- 目标:减少时延,降低带宽消耗
- 可选但却必要
分类
私有缓存:仅供一个用户使用的缓存,通常只存在如浏览器这样的客户端上
共享缓存:可以供多个用户使用的缓存,存在于网络中负责转发消息的代理服务器
- Authentication响应不可被代理服务器缓存
- 正向代理
- 反向代理
浏览器中抓包查看响应包头中是否有age字段,来区分响应资源来自缓存还是源服务器
代理服务器原理
缓存原理图
计算缓存过期的四种方式
判断缓存是否过期
常见的预估过期时间:RFC7234 (DownloadTime - LastModified)* 10%
- Age头部及current_age的计算
- 代理服务器缓存中的age头部
Cache-Control头部
- Cache-Control头部格式
-
Cache-Control头部在请求中的值
-
Cache-Control头部在响应中的值
重定向
为什么需要URI重定向
- 提交FORM表单成功后需要显示的页面
- 站点从HTTP迁移到HTTPS
- 站点部分URI发生了变化,搜索引擎或流量入口站点只收录老URI
- 站点维护中,需要给用户展示不一样的内容
- 站点更换了新域名
- ,…
重定向流程
- 当浏览器接收到重定向响应码时,需要读取响应头部Location的值,获取到新的URI再跳转访问该页面
重定向响应返回码
- 概念
- 原请求:接收到重定向响应码的请求
- 重定向请求:浏览器接收到重定向响应码发起的新请求
重定向响应返回码分类 | 使用GET方法 | 必须使用原请求的方法和包体 |
---|---|---|
永久重定向(会缓存) | 301 | 308 |
临时重定向(不缓存) | 302,303 | 307 |
- 特殊重定向
- 300:告知客户端有多种资源表述,要求客户端选择
- 304:服务器端验证过期缓存有效,要求客户端使用该缓存
重定向循环:浏览器会报错ERR_TOO_MANY_REDIRECTS
HTTP Tunnel隧道
- 用于通过HTTP连接传输非HTTP协议格式的消息,常用于穿越防火墙
- 隧道建立后,不需要遵循HTTP格式,变为双向传输
- 第一步就是CONNECT方法,例如 CONNECT www.example.com:80 HTTP/1.1
- 看到CONNECT方法就知道后续流量都基于隧道传输
HTTP基本认证
- RFC7235,一种基本的验证框架,被绝大部分浏览器所支持
- 明文传输,若不使用TLS/SSL传输则有安全问题
-
认证请求
- 在请求中传递认证信息: Authorization = credentials
- 代理服务器认证: Proxy-Authorization = credentials
-
认证响应