这篇文章是介绍 TLS 自动机设计和实现理念的,是我写在博客上的文章,转过来发一下,博客上的 CVE 的分析就比这里的多几句话,看这个就对一般协议实现者够用了。 这里的 TLS 自动机设计和总结不会设计加到线程安全,因为那个纯属于实现级别。
设计时,我们的理念就三种:
这三条理念说起来都很短的,但是实际上的理念是高度集成的,我们一条一条分开说:
简单的概念包含三种:
相比较简单而言,分层的概念简单多了,就两种:
TLS 状态机设计里面实际上安全是最难实现的,安全的原则说简单也简单,说难也难,抽象起来就两种:
下面针对性的给出我们做自动机的时候遇到的困难和问题,并简单描述我们给出的解决方案。这里需要注意的是里面一部分问题是理念导致的,一部分是实现导致的,在写代码的时候要区分开抽象和具体的区别。
分层理念带来了逻辑的简单,但也带来了一些比较麻烦的问题。
问题 1,Record Layer 层的饿死:和 handshake layer 不同,record layer 实际上是无状态的,因此如果有报文加密又有报文解密的时候 record layer 应当向上驱动还是向下驱动呢? OPENSSL 将 record layer 包含在 handshakel layer 里解决这个问题,我的解决方法是如果上次是解密,此时有加密就先做加密。
问题 2,上下层的通信:通常来说层与层之间只有依赖,而没有通信,但 TLS1.3 里的 0-RTT 导致 1record layer 和 handshake layer 需要通信决定 lazy alloc enc/dec ctx 2 0-RTT 加密 /解密失败时候需要丢弃数据,而不是丢弃自动机,这两个情况就需要设计两个层的通信。我目前没有给出这个问题的规整解决,只是看 EARLY_DATA_STATUE,如果复杂化了再建立通信机制。
问题 3,0-RTT 的自驱动:TLS1.3 之前,自动机都是由数据驱动的,因此都是 RECORD LAYER 驱动了 HANDSHAKE LAYER,但是 0-RTT 导致了一个自驱动。正是这个自驱动导致 TLS 自动机的 RECORD LAYER 和 HANDSHAKE LAYER 分层复杂化,解决方法也不难,在 handshake layer 添加一个自己触发自己的状态,该状态会频繁触发 record layer 的自驱动(这里面隐藏着一个问题 1 )。
下面我会列出一些 CVE,这些 CVE 就是由于不遵守相应的理念导致的问题,作为一个安全协议的实现人员(分析人员),一定不要忽视小小的问题。有一点需要注意,我并不只列出 OPENSSL 的 cve,其他软件也会有,不过基本都是我修过 /探究过的。除此之外,我写过很多好玩的东西,比方说假 SNI 做代理,但这些都不属于标准行为,不具备任何参考价值。
这里的优化并不是单纯针对三种理念的,是一种杂糅的优化策略,有的优化访问速度,有的优化安全性能。
厂商大多不关心安全,只关心效益,是目光短浅吗? 写到这里差不多就可以结束了,就不多说了。TLS 这块还有啥不明白的直接告诉我就成了
提到安全开发头头是道,真到开发的时候抓瞎了。身为一个从预研到开发的程序工程师,我来简单说说我所认识到的安全开发。由于我是单纯从开发干起,很多东西都是(我自己总结的)从开发的角度来谈的,因此难免有局限性。
安全开发名字高大上,但是实际上是个苦差事,因为安全并不是水桶,而是一个气球:哪里扎破一个洞,立刻整个就崩了。因此初期把握好安全开发就很重要,我比较喜欢从下面几个方面来分析:
上面几个问题实际上是安全开发当中大的目标,分析好上面几个问题之后,最大的问题就来了,怎么落地?说起来也不难:
多赘述一点东西:安全属性不是隔离的,端到端加密是很多功能的保证,但是奥卡姆的剃刀原则务必不要忘记,如无必要勿增实体,不要把其他层的东西放到本层来做!
安全开发流程中期实际上是个工程师埋头干活,抬头开会报进度的流程,这阶段的关注点在于project leader上。project leader不但要对项目进度做好把握还要把握好需求变更的问题。project leader还需要检查行为变化,细化安全规范。这就需要project leader能够明确安全的行为,并且能够根据具体的功能黑盒灵活的改变行为。
坦白讲,做TLS自动机研发的时候,虽然复用和0-RTT是我负责,但是关于排期这事我没咋催,主力是我,小功能分出去的时候我会提前培训开发的同事;每天问问进度和问题;明确行为规范。所以没啥排期的变更,行为这块一开始三个核心争了很久,也很确定,所以没遇到啥大问题。
安全开发流程后期实际上主要的关注点不再开发工程师上了,在于QA和运营人员:运营人员要执行静态检测和动态监测;QA要执行模糊测试,输入测试等多种功能,这都不是问题。问题在于:project leader和开发者要在开发前期和开发后期以高度透明的角度,参与QA的测试CASE制定!换言之QA和开发必须都审核过测试CASE,从而避免出现什么“现实不可能发生,测试不全面”的扯皮。
此外,需要记录开发过程当中遇到的实际问题和BUG,并且将这些问题归类,加入到安全规范中。一方面能够给工程师提供具体的案例分析,另一方面能够很明确的细化规范和经验。实际上关于0-RTT的DDOS攻击我在分析OPENSSL的时候虽然想到了但是没明确,是后来QA参与进来我们才定性规定这是个问题的。
最后,最蛋疼的收尾工作来了:
简单说说我们在开发过程当中遇到的一些实际问题:
我只所以又加了一段这个有两个原因,一个是因为昨天晚上11点,我们的SE忽然给我打电话,说了一个卡顿的问题,然后说是必须明天10点给回复,然后我去看了下BUGZILLA对应的页面,前几天我在里面回复的要查询测试的点一个都没做/然后说好的统计数据和日志也没有上传。另一个事情是看FREEBUF上安全甲方群的讨论,里面的几个回复有所感慨,还是以开发的角度来聊聊技术支持和安全运营。
从我的观点来看,安全运营实际上分为两个方向:对内--针对开发和测试,对外---对客户。这两点说完了,再写一点对SE的建议。
对客户而言,SE是问题的解决者,在解决问题的时候应当:
除此之外,由于我们是TOB的,漏洞的发现往往会早于客户环境遇到,因此应该:
对内,或者说对开发和测试工程师而言,SE是寻求帮助的人,SE应当:
我不是SE,但是我想所有的问题都是一致的。
1
iloveayu 2022-07-28 15:28:19 +08:00
感谢分享,OCSP STAPLING 搜过来的。
|