这篇文章上次修改于 832 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

虽然我知道这可能有些过于敏感了
但是QICQ协议(QQ)是可以被诸如深信服之类的第三方旁路软件截获的
这意味着什么呢?
所有网络连接(包括私有网络内进行的)均有被截获的可能性。
我今天下午自习的时候想了一下具体思路,发现有一种思路几乎可以应用于所有协议的解密,无论你是否加TLS。
具体怎么操作呢?
我们先讲讲相关原理

明文

由于明文通讯太过简单,直接截取数据包即可,故此处不讨论这种场景。

对称/非对称加密

HTTPS

众所周知,HTTPS是先走对称加密,再转换到非对称加密的,那么有没有什么方法“伪造”TLS报文呢?

设备的证书信任机制

我们在此处先假设五个实体

  1. 用户的设备
  2. 网站
  3. SSL证书(SSL Cert)
  4. 可信CA列表(Root CA PublicKey)
  5. 根CA(Root CA PrivateKey)

我们先回顾一下SSL证书的签发过程

SSL证书可以由任何人签发,因为SSL证书是按照X.509标准的公私密钥对,关于X.509的相关定义,团子可以查看→X.509_百度百科
(不想看的话直接看下面的内容就行)
根据百科的内容我们可以总结出:

  1. SSL证书签发需要Root CA(即根CA),就相当于要拿着请假条出校门,上面必须有班主任的签名。
  2. Root CA签发的SSL证书具有可辨识性,即保安(任何人)可以根据签名字迹判断请假条上的签名是不是班主任签的、请假日期对不对、请假的人是不是你。
    注: 用户相当于保安

设备为什么信任网站?

自签证书

正如上一段提到的,任何人都可以签发SSL,只需要先自己签发一张Root CA,再用这张自签的Root CA签发一张SSL证书即可。
(这种行为相当于你用你自己的字迹签请假条)

信任机制

上一段同样有提到,“Root CA签发的SSL证书具有可辨识性,即保安(任何人)可以根据签名字迹判断请假条上的签名是不是班主任签的、请假日期对不对、请假的人是不是你。”。
这意味着如果有哪个倒霉蛋想自签请假条(证书)逃课,那么他将被保安拦截下来。
那么,保安又是怎么知道字迹是不是班主任的呢?
很简单,保安只需要存储一份班主任字迹的特征,再进行比对就可以了。这相当于“可信CA列表”,即用户本地存有Root CA的公钥,这个公钥无法用于生成证书,但可以用于对证书进行校验(通俗点讲就是比对字迹)。
Root CA的公钥在用户本地有两个作用:

  1. 检验SSL证书签名是否有效(你的请假条上班主任的字迹是不是伪造的)
  2. 检验SSL证书的签名方是否可信(你请假条上写的班主任是不是真的班主任)

如果这些校验全部通过了,保安(用户的设备)才会放行(信任证书并继续访问网站)。

这意味着,如果一个网站要被用户正常访问,它需要满足以下条件:

  1. 网站的SSL证书是由受信的RootCA签署的(请假条是由班主任签署的)
  2. 网站的SSL证书没有过期(请假条时间对的上)
  3. 网站的SSL证书上授权的域名是被访问的域名(请假条上写的请假人是你)

上述情况是正常访问一个网站(请假)的相关流程。

例子

团子应该还记得之前遇到过星河云服务面板的证书不被团子电脑上的操作系统信任的情况,实际上这种情况的核心问题就是:系统的CA信任证书列表里没有对应的Root CA
怎么解释呢?
假设我是C4,我需要向团子老师请假,那么我需要找团子开一张请假条。
开完请假条我准备出门了,但是保安不认识团子,更无法验证签名的人是不是团子,就把我拦下来了。
这就是问题所在。

如何绕过这一机制?

我们在假设保安有正常工作的情况下(访问时验证SSL证书有效性)来探讨这一问题。
如果C4偷偷往保安的信任列表里加一份伪造的“班主任C44”的信息,那么会导致以下后果:
C4哪天想逃课了, 自签了一张请假条,签名为“C44老师”,那么保安在验证班主任的名字是否受信和签名合法性无误后,将打开校门,此时逃课将顺利进行。
把这些东西换到网站上也是一样的,我如果自签了一份Root CA,然后把公钥塞到操作系统的“可信CA列表”里,那么这份自签的Root CA将在这个操作系统上被完全信任,而用它签名的CA证书也将同样被信任。

其他协议

团子完全可以把上述HTTPS的逻辑代入到其他协议里,因为无论是什么协议,加密方式基本都是对称/非对称加密,而这两种方式的弱点是一样的。

如何利用这一机制窃取用户数据?

我们先假设一些东西:
一个内网:10.1.2.0/24(10.1.2.0~10.1.2.254)//内网
一个公网出口:12.22.23.34 //公网
一个路由地址:10.1.2.1(暂称为网关)//内网
一个联网客户端:10.1.2.2(暂称为用户)//内网
远端服务器: exmpale.net(12.22.1.1)//公网

利用此机制监听用户

前面的【如何绕过这一机制?】说过,“我如果自签了一份Root CA,然后把公钥塞到操作系统的“可信CA列表”里,那么这份自签的Root CA将在这个操作系统上被完全信任,而用它签名的CA证书也将同样被信任。”。
窃取的方式非常简单也非常容易实现:在用户的设备上安装内网路由的CA证书,以实现在路由上监听用户发出的任何报文。
具体怎么实现呢?

  1. 路由签发一对SSL证书:Trust.RSAPub/Trust.RSAPriv
  2. 在所有内网设备上安装 Trust.RSAPub
  3. 监听所有来自内网的请求
  4. 在有TCP握手包到来的时候,充当“代理人”,将用户的连接拦截在内网,伪装成exmpale.net返回握手请求。
  5. TCP握手成功后,用Trust.RSAPriv签发一张对应域名的SSL证书—“Trust-exmpale.net”,然后用生成的SSL证书签名并伪造TCP报文返回,完成SSL握手。
  6. SSL握手成功后,用户发来请求的时候就把用户的请求内容存储下来,再将请求内容发送至真正的exmpale.net,再把exmpale.net的返回记录下来。

如此一来,用户的隐私就在不知不觉中被泄露了。

总结

由此可见,在未受信的内网进行互联网访问是非常危险的。
而团子今天中午跟我说的那些东西一旦泄露出去,我们都将承担非常严重的法律责任。
所以以后如果涉及一些不能被他人知道/不能泄露的机密,我们还是尽量在可信任的私人网络下发送,而上述情况也只是监听手段中非常简单的一种,如果要列举其他情况我还可以再写个几千字。
现在在商业化,我们还是得多注意一下这些东西,把柄是绝对不能留在他人手里的。