HTTPS
HTTP
HTTP连接过程
建立TCP连接,
[客户端发送HTTP request,服务端回复HTTP response] x n,
关闭TCP连接。
HTTP长短连接:
HTTP 1.0协议版本默认是短链接,每次HTTP请求都需要重新TCP握手建立连接,HTTP回复后需要四次挥手关闭TCP连接。
然而在访问dustball.top时,浏览器会自动请求界面上的所有资源,包括头像、目录等等,这就需要多次HTTP请求,如果每次都要重新建立TCP连接,就会有大量TCP握手挥手的额外开销。
因此在HTTP request和response头中都带上
Connection: keep-alive
字段,就可以让双方保持TCP连接的打开状态,复用这个通道。保持一段时间如果一直没有新的请求,则服务器主动关闭TCP连接。或者服务器已经打开的长连接通道已经达到上限,就需要挑一些幸运通道关闭。HTTP 1.1之后默认长连接,除非显示带上
Connection: close
,就成为了短连接
建立TCP连接由客户端发起,
关闭TCP连接可以是客户端也可以是服务端。
为什么引入HTTPS协议?
或者说HTTP协议存在什么缺点?
HTTP明文传播,面临被窃听,被篡改,被冒充 三种风险。
- 被窃听指攻击者可以在路由器上捕获到受害者的HTTP数据包,并直接看到其中明文信息。
- 被篡改指攻击者可以在路由器上拦截到受害者的HTTP数据包,修改其中的值后再放行给服务器。
- 被冒充指攻击者可以在路由器上拦截到受害者的HTTP数据包后,冒充自己是服务器,直接回复受害者,不再放行HTTP数据包。攻击者也可以在日后重放受害者的HTTP数据包给服务器,冒充自己是客户。
因此引入HTTPS协议,目的有三:
引入HTTPS协议的目的
所有信息加密传播,无法窃听
具有校验机制,被篡改可以被通信双方发现
具备身份证书,防止冒充
HTTPS
HTTPS = HTTP + TSL/SSL

HTTPS(Hypertext Transfer Protocol Secure,超文本传输协议安全),在HTTP基础上加入了SSL(Secure Sockets Layer,安全套接层)。
目前SSL协议已经被TLS(Transport Layer Security,安全传输层协议)协议取代。TLS是基于SSL 3.0改进的。
TLS/SSL不止可以与HTTP协议结合,也可以与FTP、SMTP等协议结合。
HTTPS连接过程
建立TCP连接,
建立TLS连接,
[客户端发送加密的HTTP request, 服务端回复加密的HTTP response] x n,
关闭TCP连接。

如图1775、1780、1781三帧首先建立TCP连接
接下来1782、1791、1794是TLS握手过程
TLS握手目的
客户端验证服务器的证书是否可信
客户端与服务端协商一个公认的对称密钥
此后的通信使用该对称密钥加密传输
TLS握手过程
TLS握手发生在TCP三次握手建立TCP连接之后,HTTP请求之前
- Client Hello,客户端发起,携带客户端随机数Client Random
- Server Hello,站点回应,携带服务端随机数Server Random,TLS证书链(包括站点证书、中间证书、根证书)
2.1. 客户端收到后,首先校验证书合法性。
客户端收到后,会校验证书可信性,校验方式:
从站点证书开始,证书链上溯,直到某个授信的CA,则认为整个证书链可信
比如西电站点的证书就是第三级证书,
![]()
CA,Certificate Authority,证书颁发机构。低级证书由高级CA颁发,比如西电的证书由中间机构GlobalSign RSA OV SSL CA 2018颁发。
浏览器在安装时会自动集成GlobalSign这种根证书,但是它不知道xidian的证书是什么玩意儿,也不知道中间证书GlobalSign RSA OV SSL CA 2018是个什么玩意儿。
可以在浏览器的 设置/隐私、搜索和服务/安全性/管理证书/Microsoft受信任的根证书计划存储区 找到GlobalSign的记录。浏览器在校验过西电证书链中,根证书的sha256指纹值后,发现等于自己预存的GlobalSign证书的SHA256指纹值CBB522...,于是就认为这个证书绝对可信了。
![]()
虽然证书链的根证书可信,但是中间证书和服务器证书是否可信呢?这个证书是否已经过期被吊销了呢?这个证书是否是伪造的呢?这个怎么验证呢?证书链验证过程:
首先看CA给站点颁发证书的过程:
- 站点向CA申请一个数字签名:站点填一张表单,包括站点公钥,站点基础信息等,然后表单交给CA。
- CA给出一个数字签名:CA使用站点表单计算出一个摘要值,然后使用CA私钥加密这个摘要值,加密值作为数字签名交给站点。
- 站点组装证书:站点保持公钥和站点基础信息不变,组装上数字签名,形成站点证书。
浏览器访问站点时,站点会一并发送站点证书、中间CA证书、根CA证书链
浏览器验证站点证书过程:
- 浏览器从中间CA证书中拿到中间CA的公钥
- 浏览器使用中间CA的公钥,解密站点数字签名,得到摘要值A
- 浏览器使用站点证书公钥与基本信息,使用相同的摘要算法,计算出一个摘要值B
- 浏览器比较摘要值A和B,如果相同则通过站点证书校验
- 浏览器沿着证书链校验中间CA证书
中间CA可能是伪造的,但是这条证书链最终需要根CA的私钥加密第一个中间CA的摘要值。而操作系统会预装根CA证书,浏览器直接拿来用,认为根CA证书可信。因此自然情况下,只要是这一条证书链都校验通过,就不存在伪造证书的可能。
当然如果非要伪造也不是不行,由于浏览器使用的是本地保存的根CA证书,可以伪造根CA证书,或者说可信CA证书放在本地,浏览器上溯到这个证书就认为证书链可信了。
在通过了证书链验证之后,浏览器还会验证证书是否过期等等
这可以使用证书包含的基本信息,比如有效期等进行验证,由于该证书已经被CA计算过摘要然后加密成签名,因此站点不可能篡改证书的有效期,否则:摘要值就会变,导致数字签名就会变,导致浏览器根据站点证书计算的摘要值和使用CA公钥解密数字签名得到的摘要值就不同,导致证书验证失败。
如果证书链不完整,确实某些中间证书,则浏览器会根据下级证书的颁发者字段,去公共存储库寻找上级证书。找不到就认为证书链校验失败。
2.2. 客户端校验证书通过后,客户端生成一个PreMaster Key,
2.3. 然后客户端根据Client Random、Server Random、PreMaster Key三值生成对称密钥
2.4. 客户端从站点证书中拿到站点公钥,使用站点公钥加密对称密钥
- 客户端向站点发送 经过站点公钥加密的对称密钥
站点收到后使用自己的私钥解密得到对称密钥
到此双方就协商好了此后HTTPS通信加密使用的对称密钥
显然此次握手中客户端发送的握手包中已经可以携带http请求了
HTTPS抓包实验
HTTPS抓包必须是中间人攻击,
中间人必须让客户端认为自己就是站点,自己的证书就是站点的证书
中间人必须让站点认为自己就是客户
原理如图,图片参考BurpSuite抓取https包原理_burpsuite拦截原理-CSDN博客:

burpsuit 抓HTTPS包
- 使用burpsuit在本地8080端口上开启代理,

- 使用edge浏览器,不使用burpsuit自带的浏览器时,此时通过proxySwitchOmega插件,让edge浏览器走本地8080代理

- 在edge浏览器上访问baidu.com,会报告隐私错误,高级里面也没有无视风险继续访问🤣

此时查看证书,可以发现baidu的证书是由根PortSwigger CA签发的,然而这个PortSwigger CA就是burpsuit伪装的CA,这个CA不在操作系统信任根CA列表里,因此浏览器认为这个CA不可靠,于是禁止了访问。

这个证书是burpsuit硬造的,浏览器验证证书链发现不可信于是不让访问
如何让浏览器能够继续访问呢?将burp根证书添加到操作系统可信证书列表中即可
- 在burpsuit/Proxy/Options导出证书为der文件,然后安装

此时在浏览器的证书管理界面的中间证书颁发机构就可以看到这个证书了

此时访问baidu.com还是隐私错误,这是因为根证书仍然不可信
因此在这个界面上将PortSwigger CA导出为Base64编码的cer格式,然后在受信任的根证书颁发机构里重新导入cer格式证书,就可以让该证书成为受信任的根证书了。
- 将PortSwigger CA证书安装为可信根证书
此时就可以访问baidu.com了,可以看到虽然证书都是假的,但是我们自欺欺人地认为是真的

此时就可以用burpsuit抓baidu登录包了,虽然这个登录包的内容是经过前端加密的

wireshark抓HTTPS包
直接用wireshark抓https包,效果是能看到tls握手过程,握手之后的http数据全都是加密传输的tcp数据包,看不到http请求头,也看不到请求体,就是一个tcp头加上tcp数据体。
这是因为wireshark不知道客户端与服务端协商的对称加密密钥是多少,不知道如何解密这些tcp数据包。
因为如果能够捕获到客户端与服务端协商的对称加密密钥,就可以破解https包。
这个对称加密密钥是在客户端处生成,经过站点公钥加密传输给站点的
因此显然可以让客户端操作系统在生成对称加密密钥时,直接把密钥记录一下,在windows上可以指定SSLKEYLOGFILE
环境变量,让所有tls对称加密密钥输出到一个文件中。
- 任意目录下新建一个
ssl.log
文件,在windows环境变量里加入一个SSLKEYLOGFILE
,值为ssl.log的绝对地址

- 此后浏览器只要是访问
https
网站,就会在这个ssl.log
中保留tls
握手信息,包括

这个文档长这样:

关于其格式可以参考The SSLKEYLOGFILE Format for TLS
- 在
wireshark/编辑/首选项/Protocols/TLS
中指定Pre-Master-Secret log filename
位置

之后就可以使用wireshark
看到http
的请求和回复内容了
比如这里访问了baidu.com
的登录接口

同理在Linux
上也可以设置这么一个环境变量
1 | export SSLKEYLOGFILE=~/.sslkeylogfile |
python 网络编程中使用TLS
浏览器和站点使用HTTPS协议交互的过程中,可以看到TLS发挥了协商加密公钥的作用,
如果不使用浏览器,不使用HTTPS协议,而是其他协议套上TLS,应该如何实现呢?
除了浏览器外的其他客户端比如一个安卓程序或者一个GUI程序, 在与服务器通信时,怎样使用TLS协议呢?客户端又是如何校验证书的呢?
显然也需要实现ssl库