今天我们的某条业务线终于用上了HTTPS。 由于实在是忍受不了某动,某通等经营商的内容劫持。不但会嵌入广告, 而且会嵌入少量js代码,导致整个web都崩溃掉。在这个过程中也比较深入的理解了一下HTTPS协议。这里做一个记录。
实际上HTTPS我个人了解起来就是 HTTP over TLS(transport layer security), 因而本篇文章的重点也就是TLS的协议。 我们将重点分析TLS是如何建立起来的,以及https 的 hack 方法。
少量基础姿势
RSA
关于RSA加密相信每一个搞计算机的人可能都理解过(但弄明白的很少吧, 数学的东西推导起来头都大了)。非对称加密,故名思意也就是使用公钥来加密的,使用私钥来解密 。这也是我一开始对于RSA的认知。然而也听说过RSA可以使用做签名, 使用私钥签名使用公钥来验证签名。对于这一点我感到非常的迷惑。How it works? 原来使用私钥加密的内容,可以使用公钥来解密。公钥和私钥的称谓可能本身具备肯定的迷惑性,然而他们本身没有什么本质的区别,使用一把钥匙加密,使用另一把钥匙解密,这是个双向的。
RSA的证实太过复杂,我们也不做赘述。这里只说两个结论
另外非对称加密的方式也不只有RSA一种,比方后面我们提到的Diffie–Hellman也是一种非对称的加密的方式,这种加密方式在密钥交换的过程(key exchange)中还蛮有做使用呢。
数字证书(Digital Certificate)
一个小小的故事
密码学有三个名人 Alice, Bob和 Eve。 我们仍然使用他们三个来讲故事。
这个问题说明只有公私钥对还是处理不了问题的。我们需要一个方法来保证公钥不会被篡改。又是一个Authentication(Ensure the users of the network are who they say they are) 的问题。 假如信任一个人,需要信任他的公钥, 然而如何做到公钥是可信的?(这里出现了肥皂距离的狗血剧情,既然你不相信我, 那你去问你信任的人好了。问一问他我说的是不是真的。)
后来Bob找到了Alice信任的人 — 一个叫CA的机构。 这个机构比较权威比较出名, 大家都知道他的公钥(由于所有人都知道所以没办法伪造)。 CA将Bob的公钥和Bob的名字以及其余信息放一个文件中,并使用自己的私钥对这个文件进行签名,同时将签名放在这个文件的结尾,于是一个高大上的证书就生成了。
Alice 拿到 Bob 的证书后,首先使用CA的公钥(这里实际上是一个自签名的根证书) 对Bob的证书进行完整性校验,确保的确是由CA颁发的。而后检查证书里面的信息的确是Bob, 这样 Alice即可以确信证书里面的公钥的确是Bob的公钥, 使用他来验证Bob的信息没有问题。
上面的故事已经很好的解释了什么是数字证书及他的做使用。 我们在详情一下现实世界中的证书
现实世界中的证书
在公共网络中,首先有几个比较知名的大的CA机构比方VerSign他们会颁发根证书self-signed root certificate 我们的浏览器或者者电脑会有一个信任根证书列表默认保存这些我们信任的根证书。 以MAC电脑为例, 默认信任列表长这样
为了保证根证书颁发机构密钥的安全性,他们会很吝啬的用自己的密钥,但是有很多人需要去取得证书,肿么办? 于是CA只好去找几个有资质的机构,为他们颁发中间证书(Intermediate certificate authority),拥有这些中间证书的机构又能为自己信的过的机构颁发中间证书(Intermediate certificate authority) 这样就形成了证书链。
使用户可以向任意一家CA去申请自己的证书。申请下来的证书长这样
可见www.dbbar.net的域名证书是由CA 沃通免费SSL证书G2颁发的。 这个CA机构也有自己的证书长这样
总结起来,现实世界按功能分为三种
证书验证过程
写这篇文章的时候,我一直在想:既然信任链可以延续下去,那我们完全可以申请一个证书而后使用这个证书来颁发其余的证书啊。 这样证书不就不可信了么。
猜想程序对证书的验证过程应该是这样的,首先从根证书到要验证证书的证书链。而后检查除要验证证书证书链以上的所有证书的类型能否是self signed root certificate 或者者 intermediate certificate authority 假如不是,那么这个要验证的证书就验证不通过。
我们只能寄希望于所有的CA都是公开,公平,公正的了。他们会对每一个下级CA进行严格的审查, 以确保CA中不会有坏人。(万一哪天某动或者者某通成了CA就不好说了,他们会直接伪造证书,进行中间人吧。)
HTTPS建立的过程
HTTPS 建立的前几秒主要是完成用户端对服务端的验证Authentication, 通信过程中使用的加密方式,数据校验方式的协商, 通信过程中要用的密钥(master key)的交换等过程。 由于后续的通信是加密的,可以防止监听(Confidentiality) 同时会进行数据的校验以防止内容被篡改(Integrity)
网上有好多详情https的过程的,这里简单给一个时序图,感兴趣的同学可以去深入理解
解释:
如api.dbbar.net返回的Server Hello包长这样
这里可以看到Server端选使用的加密套机是TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(我们将在后文中解释Cipher Suite)
一个比较直观的看ssl建立链接的过程是使用openssl, 执行openssl s_client -debug -connect api.dbbar.net:443 或者者采使用wireshark抓包的方式会看到比较完整的连接建立信息这里不做赘述。
Cipher Suite
前面已经屡次提到了cipher suite 到底什么是cipher suite? wiki上给的答案是 A cipher suite is a named combination of authentication, encryption, message authentication code (MAC) and key exchange algorithms used to negotiate the security settings for a network connection using the Transport Layer Security (TLS) / Secure Sockets Layer (SSL) network protocol. 简单的来说一个加密套件规定了TLS建立连接过程的具体细节如: 如何进行加密,如何产生信息校验码, 如何进行密钥交换。
一个Cipher Suite 比方我们前面提到的TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 定义了具体的密钥交换算法,块加密算法, 信息校验码产生算法, 及具体的密码推导算法 pseudorandom function(PRF) 在这个例子中
当然TLS协议定议了很多cipher suite, 每一个cipher suite 的安全性也不太一样,对CPU性能的占使用也不太一样。
HTTPS下如何去抓包
HTTPS进行抓包,实际上是进行了一次中间人攻击。 我们需要伪造一个假的证书,并让用户端去信任这个证书。而后用户端与中间人即可以建立起TLS链接。而后中间人再去代理商真正的用户端请求服务端。这样处理问题的方式就是这样的了:
那如何才能伪造假证书呢? 这时我们就需要在用户端安装一个我们知道密钥的根证书并信任它。这样我们就能使用我们的密钥去颁发假的证书。而由于用户端信任了我们的根证书,所以它也会认为我们颁发的假证书是真正的证书, 这样真真假假就傻傻分不清楚了。
关于假证书的问题,记得前几年前goagent还存在的时候曾经报出个0 day 漏洞。由于好多人安装并信任了goagent的证书。并且goagent的证书的密钥是公开的。所以可以中间人攻击https服务。做法就是用goagent的密钥来签名伪造的证书。这样屡试不爽。
我们以BurpSuite为例,验证一下这个思路
HTTPS hacker
step1: 将Burpsuite的自签名证书导入firefox并信任。 step2: 设置firefox代理商到burpsuite
我将使用wareshare抓从firefox到burpsuite的包来分析流量
果然:这里使用了一个我们之前信任的PortSwigger CA 证书签名了api.dbbar.net 域名。这样来实现中间人攻击。验证了之前的猜想
中间人攻防治
可以才使用HTTP Public key Pinning的方式来固定用户端只用哪个证书来达到防治的目的
总结