今天我抓了个 HTTPS 的包

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了今天我抓了个 HTTPS 的包脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

之前写过一篇讲 HTTPS 的思想的文章

破玩意 | 用 HTTPS 传纸条

后来又写了篇用更凝练的语言总体描述了 HTTPS 的主干。

叮咚 | HTTPS 的分支和主干

想必通过这两篇文章,HTTPS 为什么要这么设计,以及它是用来解决什么问题的,大家已经心中有数了。

那接下来就是细节了。

由于之前已经把思想讲过了,本篇就通过抓包的方式,专注于 HTTPS 的过程,我会像个无情的流水账一样,给大家把一个 HTTPS 的包挖干净。

先普及一个知识点,HTTPS = TLS + HTTP。

HTTP 我们很熟悉了,所以我们想知道的 HTTPS 的知识,本质上是想知道 TLS 协议的规范,以及为什么这样设计。所以我们本文展开讲解 TLSv1.2 协议的内容。

我们开始吧!

直接 postman 发起一个 HTTPS 的 POST 请求,这个 IP 是微博首页。

今天我抓了个 HTTPS 的包

Wireshark 抓包,过滤出 tls 协议的包,看到如下结果。

今天我抓了个 HTTPS 的包

一下就可以看到整个 HTTPS 握手的过程了。

这个抓包数据可以加我好友,朋友圈有下载链接。但其实你自己随便访问一个网站用 wireshark 抓一下也行。

学一个协议,最科学也是最方便的办法,就是看官方文档。

我们看 TLS 1.2 的官方文档,Rfc-5246,其中 section-7.3 为我们描绘了整个握手过程。

今天我抓了个 HTTPS 的包

由于我们只是客户端验证服务端证书,而没有服务端验证客户端证书的过程,所以我们的包里,是不包含 Server CertificateRequest(请求客户端证书)、Client Certificate(客户端证书)、CertificateVerify(客户端证书有效性验证)这三项的。

下面我们一个一个过程拆开来看。

 

ClientHello

 

当 client 连接到一个 server 时,第一个发送的包就是它。

今天我抓了个 HTTPS 的包

具体包含以下内容:

client_version

客户端希望的,也是客户端能支持的最高的 TLS 版本号,这里是 TLS 1.2 版本。

random

由客户端生成的随机数,之后会用到,我们称之为随机数 1。

ee8880e816ac14ca5b69bde656c188f37a08bcf2052a550b7867b041f6c1ab48

session_id

用于复用 TLS 连接,止资的浪费。但这个要服务端支持才行。

cipher_suITes

客户端支持的密码学套件,按客户端偏好排序,如果服务端没有可支持的,那就回应错误(returns a handshake failure alert)并关闭连接。

本次一共发了 18 个密码学套件

今天我抓了个 HTTPS 的包

我们拿其中一个密码学套件举例

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

我们知道,HTTPS 的原理就是用非对称加密的方式来交换秘钥,用对称加密的方式来通信,然后里面夹杂着哈希算法用于验证签名等。

所以这个密码学套件就包含了这三个部分。

ECDHE_RSA 指的是秘钥协商算法AES_128_GCM 是最终通信的对称加密算法SHA256 是哈希算法

以此来确定整个握手过程所需要的算法都用什么。

comPression_methods

压缩算法

extensions

扩展字段

由此看出,本次 clientHello 最重要的信息就俩,一个随机数,一组支持的密码学套件。

接着往下看

 

ServerHello

 

服务端给客户端发送的包,响应 ClientHello。

今天我抓了个 HTTPS 的包

 具体包含以下内容:

server_version

TLS 的版本,具体是服务端支持的最高版本以及客户端支持的最低版本。

random

服务端生成的随机数,且生成规则不能依赖于客户端的随机数,我们称为随机数 2。

3ad03af5b8a5ebfe7902a250406b2e99d2667e37e524e0e5c333c0e0b9a637e8

session_id

服务端返回的会话 ID。

如果客户端刚刚发过来的 session_id 服务端已经有了缓存,并且同意复用连接,则返回一个和客户端刚刚发来的相同的 session_id。

也可以发送一个新的 session_id,以便客户端下次将其携带并且复用。

也可以回复一个空值,表示不缓存 session_id,因此也不会复用。

cipher_suite

选择的加密套件。

刚刚客户端传来 18 个加密套件,服务端选择了一个回应,此处回应的是。

0xc02f

表示

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

这个刚刚解释过了,表示用 ECDHE_RSA 作为秘钥交换算法,用 AES_128 作为通信时的对称加密算法,用 SHA256 作为哈希算法。 

comPRession_method

选择的压缩算法,同上

extensions

扩展字段,同上

由此看出,本次 serverHello 最重要的信息也是俩,和上面的 clientHello 一样,也是一个随机数,还有一个从客户端发来的一组密码学套件中选择的一个。

至此,服务端和客户端都拥有了随机数 1 和随机数 2,并且选定了共同确定的密码学套件。

双方互相 hello 的过程就此结束了。

接着往下看

 

Server Certificate

 

服务端发完上面的 ServerHello 后立即发这个包,这个包非常简单

今天我抓了个 HTTPS 的包

只有一个 Certificates 结构体,就是我们常说的证书。

而后缀还加了个 s,因此翻译成证书链,是由一组证书组成的,最上面的是服务端本身的证书。

我们把这个服务端的证书的关键信息都展开看一下:

今天我抓了个 HTTPS 的包

这个证书在默认情况下都是 X.509 格式的,除非明确协商说明。

别怀疑,RFC-5246 中就是这样写的。

今天我抓了个 HTTPS 的包

这种格式的结构定义在 RFC-1422 的 3.3 节中有说明。

今天我抓了个 HTTPS 的包

别废话了,展开讲一下吧。

version

证书版本号,v3

serial number

证书序列号,这个每个颁发机构是唯一的,此处为:

0x0de81066db219caef5ecb01ba273CAD1

signature

签名算法,仅仅是一个算法哟。

此处是 1.2.840.113549.1.1.11

表示 sha256WithrSAEncryption

这就表示用 sha256 这个哈希算法对证书进行哈希生成摘要,然后再用 RSA 这个非对称加密算法,用 CA 的私钥加密刚刚生成的摘要,形成数字签名。

issuer name

颁发者信息,我们展开看一下

RDNSequence item: item (id-at-countryName=US)RDNSequence item: item (id-at-organizationName=DigiCert Inc)RDNSequence item: item (id-at-organizationalUnitName=www.digicert.COM)RDNSequence item: item (id-at-commonName=GeoTrust CN RSA CA G1)@H_512_318@

 

validity PEriod

证书有效期,比如本案例中的

notBefore: utcTime (0)    utcTime20-06-09 00:00:00 (UTC)notAfterutcTime (0)    utcTime22-05-15 12:00:00 (UTC)

 

subject name

证书持有者信息

rdnSequence: 5 items    RDNSequence item: 1 item (id-at-countryName=CN)        RelativeDistinguishedName item (id-at-countryName=CN)            Id2.5.4.6 (id-at-countryName)            CountryNameCN    RDNSequence item: 1 item (id-at-stateOrProvinceName=Beijing)        RelativeDistinguishedName item (id-at-stateOrProvinceName=Beijing)            Id2.5.4.8 (id-at-stateOrProvinceName)            DirectoryStringprintableString (1)    RDNSequence item: 1 item (id-at-organizationName=Sina.com TechnoLOGy(China)Co.,ltd)        RelativeDistinguishedName item (id-at-organizationName=Sina.com Technology(China)Co.,ltd)            Id2.5.4.10 (id-at-organizationName)            DirectoryStringprintableString (1)    RDNSequence item: 1 item (id-at-organizationalUnitName=Sina.com Technology(China)Co.,ltd)        RelativeDistinguishedName item (id-at-organizationalUnitName=Sina.com Technology(China)Co.,ltd)            Id2.5.4.11 (id-at-organizationalUnitName)            DirectoryStringprintableString (1)    RDNSequence item: 1 item (id-at-commonName=weibo.cn)        RelativeDistinguishedName item (id-at-commonName=weibo.cn)            Id2.5.4.3 (id-at-commonName)            DirectoryStringprintableString (1)                printableStringweibo.cn

太乱了,简化下就是

countryName=CNstateOrProvinceName=BeijingorganizationName=Sina.com Technology(China)Co.,ltdorganizationalUnitName=Sina.com Technology(China)Co.,ltdcommonName=weibo.cn

顾名思义,就是微博网站这个颁发机构的信息

 

subject public key

证书的公钥信息,本案例中是:

3082010a0282010100c4c84ff479214c5875037500CFc453d676cec0e64c7ab5F14e0284d8b49b6f23ec70f853d38eb60dc91a6fa826d49d188fd20158c3aaa101b4b6a0c89d4DF824fe755ff2cfd4f876bb2dcefe760d6f9ec5e9e2990cab4367949f27062857ca26f2303f07f6c6c953f382cb8a379ae7b28c6234983fd61739550dc6b502c4feb9c9991459265f61471b91e3b592ad3e21a276d14321f462c820477e2b34a7ea16da1f3ffa760d9065ceb5a98ffc3d19da519133d542f74dd70c4366d98d16c36c27e4384cf31130614a1398621c64c260ad91d0de32900e2ac2589029b35d21eacd078bea5cb0a9db4bc3b7ba644d0459c2e0489ae62215cc525c36784191d94b0203010001

除此之外,还剩下两项,证书签名算法(诶?这个刚刚不是已经传过了么),以及证书的签名值

今天我抓了个 HTTPS 的包

从中可以读出,签名算法就是 sha256WithRSAEncryption,签名值我提取出来,如下:

220f0a0d15fa3c3909bb1e9f4d1d78cb9a41983cc9e549a4f8781f483fc18c679421eb84875354e00d86877eb1e80fb691eb0133208a0bee641ca0a7585b0e85818e88557a50f3f6241eebbc9cf49be40dc21f1d82a0cf30de30643cf236b290e74b6dee9bfdb71dab5f03b5cfd965bc16e139bc66f37119fcfc73aaf4c50fda1111bd948f507f85dd239012be73c953234328e332091c2fa38c482b6b4fdba52a26a1cc557a9c95edacea1d7b62f8996c934a5b3d762dd4f3cb88d405b805b7f604c07bd518665940f34fcb9e54121ac724a1ea3a58f42c9556f25058b19afa8c233fdf881bfeff32186051ec104fa23d4024b16b672f8eb33e359c3f813aa1

至于它是怎么算出来的,之前也画过一张图,我就直接放过来了(注意,这里的给服务端,是指 CA 机构给服务端,然后服务端现在又给了客户端)。

今天我抓了个 HTTPS 的包

还记得刚刚的签名算法么?sha256WithRSAEncryption

这个图里的哈希摘要用的算法就是 sha256,而 CA 私钥加密用的算法就是 RSA。

好了,全部证书相关的信息就讲完了,同时也是 Server Certificate 这个环节的唯一信息。

证书一方面可以通过服务端给客户端传递的包解析来看,另一方面,由于浏览器要解析这个证书信息做验证,所以通常浏览器有更直观的方式可以查看,就不用我们费心思了。

点开浏览器地址栏的小锁头。

今天我抓了个 HTTPS 的包

看,和我们刚刚抓包分析出来的信息,一毛一样。

我们继续看下一个包。

我相信你已经不记得整个流程到哪里了,好心的我给你放之前的图。

今天我抓了个 HTTPS 的包

刚刚进行完两个 hello,以及一个传递证书的包 Certificate,接下来就要进行协商对称秘钥的过程了。

这个过程,最简单就是 RSA 算法,用服务端公钥直接加密客户端随机生成的一个对称加密秘钥,发给服务端。

但现在基本上都用更为复杂的秘钥交换算法,我们往下看。

 

Server Key Exchange

 

用于 premaster secret 生成的

今天我抓了个 HTTPS 的包

之前说了,秘钥交换算法是 ECDHE 算法,这里隐含着包含了好多信息。

首先选择的椭曲线是 named_curve 类型,并指定了基点生成一个私钥,这个我们抓包看不见根据私钥和基点,计算出公钥,然后把这个公钥用服务端公钥加密,发送给服务端,这个我们能看到,就是里面的 Pubkey ,值为

2ce174dbdb6f481b6ab9fd37446dca95b6ade3613afba03243d163360f63713b

至于 ECDHE 用到的椭圆曲线秘钥交换算法的细节,这里就不展开讲了,因为我也不会,就知道它最终是为了和服务端协商出来一个 premaster_secret 就好。

接着往下看。

 

Server CertificateRequest

 

请求客户端证书,此案例中没有,一般银行等需要客户端也加密的才有,比如 U 盾。

 

Server ServerHelloDone

 

标识着 serverHello 这个握手过程结束了。

今天我抓了个 HTTPS 的包

 

Client Certificate

 

客户端证书。本案例中没有,也说明了上面服务端确实没有发送 CertificateRequest

 

Client ClientKeyExchange

 

紧接着 ServerHelloDone 发送,用于协商出 premaster_secret,同之前的 ServerKeyExchange 配合使用的。

今天我抓了个 HTTPS 的包

这回轮到客户端给服务端一个用于 ECDHE 算法的公钥了。

f04e0743377afb5e9bf0a84aec5c7257957b85daee98fc48fb8971a26b457077

而同时客户端与这个公钥配对的私钥,我们也无法通过抓包看出来。

 

生成最终通信的对称加密秘钥master_secret

 

这一步不是抓包的信息,而是客户端和服务端此时都在自己端内所做的事情,非常关键。

就是计算出最终对称加密用的秘钥 ;master_secret,这也是整个花里胡哨的过程,最终且唯一的一个目的,并且两端算出来的结果肯定是一样的。

HTTPS 的目的,不就是双方协商出一个共同的对称加密秘钥么,怕被中间人拦截到,所以做的证书呀,非对称加密算法呀,秘钥协商算法等复杂的规定。

那 master_secret 是怎么计算出来的呢?

还记不记得之前我们得到了三个随机数:

随机数 1(客户端随机数) :在 ClientHello 消息里,由客户端生成的随机数,是 ee8880e816ac14ca5b69bde656c188f37a08bcf2052a550b7867b041f6c1ab48随机数 2(服务端随机数) :在 ServerHello 消息里,由服务端生成的随机数,是3ad03af5b8a5ebfe7902a250406b2e99d2667e37e524e0e5c333c0e0b9a637e8随机数 3(pre_master) :通过秘钥交换算法 ECDHE 计算出的,我们叫它 pre_master。

最终的对称加密秘钥 master_secret,就是根据这三个随机数共同计算出来的。

一旦双方协商出来了这个相同的对称秘钥,那就可以开始愉快地安全通信了,TLS 层的工作也就圆满完成。

所以可想而知,接下来的工作,就都是收尾工作了,因为秘钥已经协商好了。

 

Client CertificateVerify

 

验证客户端证书有效性,本案例中没有。

 

Client ChangeCipherSpec

 

秘钥改变通知,此时客户端已经生成了 master_secret,之后的消息将都通过 master secret 来加密。

今天我抓了个 HTTPS 的包

可以看到,就是个标识,没有携带什么有用的信息。

 

Client Finish

 

这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。

 

Server ChangeCipherSpec

 

也是秘钥改变通知,此时服务端也已经生成了 master_secret 了,后面的通信都用此值加密。

 

Server Finish

 

同 Client Finish,服务器端发送握手结束通知,同时会带上前面所发内容的签名到客户端,保证前面通信数据的正确性。

 

Application Data

 

之后就是真正加密的数据了。

 

今天我抓了个 HTTPS 的包

 

总结

 

 

我们去掉客户端证书这个部分,整个过程简化来说一遍。1. client --> server ClientHello客户端生成随机数,并发送一组密码学套件供服务端选2. server--> client ServerHello服务端生成随机数,并从上述密码学套件组里选一个3. server--> client Certificate服务端发给客户端证书4. server--> client ServerKeyExchange服务端发给客户端秘钥交换算法所需的值5. server--> client ServerHelloDone服务端 hello 阶段结束6. client --> server ClientKeyExchange客户端发给服务端秘钥交换算法所需的值7. client --> server ChangeCipherSpec客户端告诉服务端,我已经知道秘钥了,之后的消息我就都加密发送了。8. client --> server Finish结束并验证7. server --> server ChangeCipherSpec服务端告诉客户端,我已经知道秘钥了,之后的消息我就都加密发送了。9. server--> client Finish

结束并验证

如果不看客户端证书,不看复杂的 premaster_secret 协商算法,不看压缩算法这些细节,其实简单说只有三大步骤。首先第一步,客户端对服务端说 hello,并且发一组密码套件。第二步,服务端对客户端说 hello,并且选择一组密码套件,同时把附带公钥的证书发给客户端。第三步,客户端验证证书,并且把对称加密的秘钥用服务端的公钥加密,发给服务端,服务端用私钥解密出就是对称加密秘钥了。(当然实际情况没这么简单,比如我们本次抓包是用 ECDHE 秘钥交换算法,这也是目前大部分网站的做法)。经此三步之后,客户端与服务端就都拥有了相同的对称加密秘钥,进行简单的收尾工作,也就是通知对方秘钥已生成好的信息,之后就可以开始通信了。最后说一句,本案例的抓包数据可以加我好友,朋友圈有下载链接,当然你也可以自己用 wireshark 抓,随便访问一个网站几乎都是 https 的。

参考资料:

RFC-5246 The Transport Layer Security (TLS) Protocol Version 1.2

RFC-1422 Privacy Enhancement for internet Electronic Mail Part II: Certificate-Based Key Management

脚本宝典总结

以上是脚本宝典为你收集整理的今天我抓了个 HTTPS 的包全部内容,希望文章能够帮你解决今天我抓了个 HTTPS 的包所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。