Terrapin Attack 漏洞是由这边的几个安全研究员提出的漏洞模型,这个漏洞有一阵子特别火,所以我特别想好好的研究一下,然而这个漏洞(的背景)相当的复杂,得从一些密码学相关的前置知识慢慢学习,这边先简单的把基础知识给过一遍
SSH 前置知识学习
整个加密中扯到了相当多的密码学知识,这边从一开始的部分开始讲起
密码学前置知识
加密算法本身在网上有非常多的优秀资料。这边仅对部分信息进行展开叙述。
以AES为例,AES的加密算法至今为止还是非常稳定的,然而这类算法称作块加密算法(与之相对的还有流加密算法),其作用的对象仅针对128bit|16bytes 192bit|24bytes 256bit|32bytes
这三种长度的数据进行加密。而现实中待加密的数据总是非常的长,这就需要对原数据进行一定的处理。这种不同的处理方式通常称作块加密模式(Block cipher mode)
,为了方便,在本文称作加密模式
加密模式
在讨论加密模式的时候,我们通常有以下约定俗称的称呼:
- 块(Block):表示当前加密的最小单位
- IV(Initialization Vector):初始化向量,通常与一个Block长度相等。有时候也用于指代由密文生成的参与运算的向量
- Padding:结尾的填充字符串
- Nonce:随机数。这个词在讨论加解密的时候经常使用
Padding
当我们尝试对一个比较长的数据进行加密的时候,需要将数据按照Block大小切分。通常来说,切分的大小都是4字节对齐,然而我们输入的字符根本不能保证长度一定是4的倍数,这个时候程序往往会给数据的末尾增加一些字符用作Padding,例如:
1 | ThisIsAPassword\0x01 |
其中,这里的\x01
正好组成了字符串结尾的最后一个字符,并且这个字符数字是1,表示当前的字符的padding长度为1。这样当解密完成后,程序就会根据padding抛弃最后的字符,得到完整的字符串,上述例子中即为ThisIsAPassword
。当然,这也只是一种约定,作为开发者也可以通过约定,告诉用户你的输入必须要满足为XX的倍数,否则就出错,我们提到的这种padding方式可以在RFC2040这里看到。
ECB(Electronic codebook)
根据前文可知,当遇到多余的字符时,可以使用padding来描述(或者直接要求用户输入为Block对齐)。那现在我们就需要一个方式来进行处理不同的Block,最简单的思路就是直接切分。例如下面的字符串:
1 | FirstPartAAAAAAASecondPartBBBBBB |
加密的时候,简单的分解成
1 | FirstPartAAAAAAA SecondPartBBBBBB |
这样进行加密即可。这种加密方式叫做电子密码本加密模式ECB(Electronic Codebook)
。加密方式如下图:
加密的时候,使用同一个密钥key,将切割后的字符串进行加密。这种加密方法还有几个比较有趣的好处:
- 由于加解密同时发生,所以可以异步发生
- 加解密的时候可以从任意位置开始
其实在现实场景中,除了加密的可靠性,效率也是非常值得考虑的一点。甚至在某些场景下,牺牲一定程度的安全性也是可以被允许的,为了安全而抛弃效率其实是一种过于理想化的状态。
CBC(Chain Block Cipher)
然而,其实有心人稍加考虑就会发现ECB有许多问题:
- 当攻击者知道被加密的数据大致范围的时候,会很容的爆破
- 加密数据混淆程度不高
实际上,wiki中有给出ECB加密算法的一个极端例子:
可以看到,被ECB加密的图片能看到大致的形状。现实中,如果我们企图猜测某个用户输入的密钥,并且知道一个大致的输入范围的话,爆破起来将会非常快,此时的ECB模式就会失去应有的作用。
在这个背景之下,就提出了一种叫做链式块加密CBC的加密模式。这种模式的加密流程如下:
此时能看到其格式大致如下:
其中当i=0的时候,有以下特殊情况
IV为需要用户指定的一个输入长度的字符。
这种加密方式与ECB相比,有以下几个好处:
- 第i个密文会受到前面i-1个所有密文的影响,这就导致特征变得不明显
- 即使密钥和明文一定,只要IV发生变化,密文也会发生变化
- 解密的时候,由于只依赖密文,所以解密步骤依然可以异步指型
此时,解密的时候则需要将上述的流程进行相反的处理:
这种方式为一种比较主流的加密方式。然而其还是有一点缺点:
- 当解密的时候,IV出错只会影响第一个数据块(因为解密的时候,异或步骤依赖的是密文而非明文)
- 由于加密的时候依赖上一个状态,此时加密为非并行
PCBC(Propagating Chain Block Cipher)
上文提到,CBC有一个还算致命的问题,就是IV即使出错了,也只影响一个数据块。所以提出了一种新的加密方式:PCBC,这种方式的加密如图:
可以注意到,此时多了一个异或的操作。也就是说,加密算法改成了:
这样一来,只要IV出错,错误就可以传播给每一个密文。然而这样一改,又引入了新的问题:
- 由于强依赖上一个状态,此时的加解密都无法异步
- 相邻的密文块如果发生颠倒,此时的解密逻辑不受到影响
论证:
假设此时存在三个block,分别为0,1,2.此时已知
则
此时,和顺序调换,并不影响最终答案。
这两条缺点非常明显。所以这个算法并没有特别流行
Cipher feedback (CFB)
这个算法不同于前面两个,并非是明文处理后参与AES这种加密算法,而是IV会参与到加密算法中,加密过程如图:
此时的加解密流程可以参考这个:
其与CBC模式很类似,也是加密的时候无法并行化,但是解密可以。
Output feedback (OFB)
加密算法类似CFB,区别在于IV使用的为加密后的临时状态,而非加密完成后的C:
此时的加解密流程可以参考这个:
同样由于加密过程依赖上下文,所以不能进行并行加密。
CTR(Counter) mode
可以看到,前文提过的加密算法(除了ECB)都有一个比较麻烦的问题:不能并行化。曾经和做密码学的朋友聊过,密码学算法除了加解密的安全性外,其实效率也是非常重要的一环。如果效率不行的情况下,某些所谓的安全信道将会花费大量的时间,这就会导致很多加密算法无法投入到实际生产中。于是这里提出了一种既能够保证安全性,又能并行加密的算法。
这种算法的模式如下:
其中,Counter会组成一个IV,这个IV的大小为每一个Plaintext Block 的大小。每一个Plaintext Block都有一个单独的IV。
首先这里生成一个随机数Nonce
,并且使用任意一种可逆算法F,将随机数和counter组合,形成IV,形如
之后,将这个单独的IV与Key放入对应的块加密算法中,最后用这个加密的到的数值和明文异或。
由于其孤立性的特点,CTR mode的加密算法允许算法进行并行化执行。
MAC 与 AEAD
随着时代的发展,安全攻防也在升级。很多攻击者不但直接对加密算法本身下手,有时候也改而转向对整个通信过程下手,考虑通过截断,丢弃,甚至篡改数据包,起到对数据进行劫持攻击的效果。这种时候,就对加密算法提出了新的需求,即是需要能够保证当前的加密后的数据不被篡改,于是提出了MAC和AEAD的概念。
MAC(Message Authentication Codes)为一种用于保证通信信道完整性的代码。这种能够保证通信过程不被监听的通信方式叫做Authenticated Encryption
认证加密。认证加密能够保证通信的机密性和真实性。
通俗来说,就是保证以下两点:
- 不用密钥解开就不知道通信的内容,又叫做隐私性
- 这个加密只有通信双方能做到,第三者无法伪造同样的内容
为了能够保证上述两点,这种加密过程中会带有一个用于表示认证的标识authentication tag(AD)
。这种数据保证其数据的完整性,同时不被加密,例如网络请求头中存放请求的目标地址。尽管所有的路由都能获得这个地址,但是中途的请求路由却没有一个能获取对应的key。这种带有请求就叫做 authenticated encryption with associated data(AEAD)
。
AE 加密流程
这种AE(Authentication Encryption)加密流程如下
输入参数:
- 明文
- 密钥
- 可选的头部,例如附加认证信息或者关联数据
输出参数:
- 密文
- 认证标记
解密流程如下
输入参数:
- 密文
- 密钥
- 可选头部
- 认证标记
输出参数:
- 明文
- 如果tag无法认证密文或者附加头部,则抛出错误
常见的AEAD加密模式
规范化后的AEAD模式分为这几种
Encrypt-then-MAC (EtM) 加密后添加MAC
这种加密方式是唯一完全符合AE安全标准的。注意这种加密中,两个key一定要是分离的,否则依然会带来认证绕过的风险
Encrypt-and-MAC (E&M) 同时获得密文与MAC
遇上一个的区别是,此时MAC基于明文形成,并且只存在一个密钥,这种方式在某些特定的加密模式下会导致某种变种的Padding Oracle
攻击,详见Plaintext Recovery Attacks Against SSH
概括来说,就是早年的SSH在做出错检查的时候,如果MAC值不对的时候,会发送一个区别其他消息的错误信息。
MAC-then-Encrypt (MtE) 先获取MAC,然后获得明文
首先基于明文生成MAC,然后将明文和MAC一同加密,获得密文。虽然看起来和上面的加密手法是一致的,所以同样也有Padding Oracle
的问题,其出现在历史上著名的针对TLS的攻击Lucky_Thirteen_attack
在过去,ssh会使用CBC模式对包含MAC的数据进行加密,叫做Encrypt-and-MAC
,就是在加密内容的最后增添MAC
值,这样就能够在,这就非常容易导致著名的Padding Oracle
攻击,从而在加密状态下,泄露位于数据末端的MAC
码,实现对请求过程的篡改。
Galois/Counter Mode (GCM)
这个算法将CTR的算法和认证算法结合。明文加密得到密文之后,再使用类似CBC的模式,生成对应的AuthTag。这里可以认为使用了EtA
总结
这篇文章大致上把密码学的一些基本概念过了一遍,之后在分析SSH漏洞的时候,会反复提及。
参考链接
https://datatracker.ietf.org/doc/html/rfc2040
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation