一. 引言
大家好,我是来自银基安全实验室的Cure,今天为大家介绍侧信道攻击方法之一,Timing侧信道。
随着软件安全攻防技术的螺旋式进步,安全隐患也更加多样化,有关静态分析、动态调试、远程渗透的技术技巧层出不穷。而侧信道攻击,作为一种剑走偏锋的攻击方式,也愈发引起业界的重视。
与常规攻击方法不同,侧信道攻击的关注点不再是系统的直观行为,而是由系统行为引起的诸如执行时间、功率损耗、无线电信号等间接表现的变化。所谓Timing侧信道,即基于执行时间的差异而进行的侧信道攻击。这种攻击在web服务场景或其他网络应用的场景都存在着一定程度上的适用性,更可以与其他手段进行配合。
本文首先从一个简单示例入手,介绍Timing侧信道的原理;再给出一个基于C语言实现的简单Demo,以更清晰地表述Timing侧信道的操作方法。
本文提供的技术探索与Demo,仅起到抛转引玉的作用,希望能够为初学者提供些许思路与参考。
二. Timing侧信道概念
Timing侧信道通过系统在不同行为流程下所表现出的执行时间差异,推断有用的信息,以达成或辅助攻击。本章给出一个基于泛化PHP代码的概念性介绍。
假设Web 网站采用了如下代码:
其逻辑可以简要归纳为:
① 若用户名不存在,则登录失败;
② 若用户名存在但密码不正确,则登录失败;
③ 只有当用户名和密码都正确,才返回成功。
其中,逻辑①的道理在于,当发生基于字典的爆破攻击时,由于涉及的查表列数只有1列,能够一定程度上减小服务器的开销。同时,由于逻辑①和逻辑②返回的信息字符串完全相同,避免了攻击者根据该信息判断出用户名是否存在,而进行后续的针对性的爆破。
然而,看似缜密的设计仍然能够受到Timing侧信道的有效攻击。具体方式如下:
① 攻击者从本地提交post请求,其中,变化username,而保持password为任意固定值,例如“123456”。
② 攻击者统计每次从发出请求起到收到服务器回执所耗费的时间,对于同一组用户名和密码,也可以通过测量多次取平均值、中值等方法消除网络延迟引入的时间抖动。
③ 对于统计时间较长的请求,认为其所对应的用户名是存在的。
④ 基于存在的用户名,进一步发动针对性的爆破。
本例中,Timing侧信道的立足点在于用户名是否存在所引入的访问时间的差异。具体地,若用户名不存在,则网站服务器仅执行逻辑①的相关判断,所耗费时间较短;若用户名存在,则网站服务器还需额外执行逻辑②的判断(即使密码错误),所耗费时间较长。由此,虽然用户名存在与否对返回的信息字符串并无影响,但攻击者可以从消耗时间长短不同的角度入手,推断出真正存在的用户名。
三. Timing侧信道Demo
本章首先阐述Demo对应的场景,再给出攻击思路,最后展示Timing侧信道攻击的实施方法与运行效果。
3.1 场景说明
本demo模拟了出题人和解题人的交互。
① 出题人设定了一个字符串secret(内容为happy),不直接公布其内容,如下图所示。
② 出题人提供了一个猜测其内容的接口guess_the_secret,该接口接收一个所猜测字符串作为参数,并返回猜测是否正确的结果。出题人对该接口的调用次数不设置限制。接口实现如下图所示。
其中,old_strcmp的实现采用了旧版C库的常见实现方式,即字符串逐个对比法,具体代码如下图所示。
③ 解题人可以通过编写相应程序调用该guess_the_secret并取得返回值不断猜测,直至找出出题人设定的字符串。若找到,则解题成功。
3.2 攻击思路
本节给出算法复杂度较高的直观方法和算法复杂度较低的Timing侧信道方法。
3.2.1 直观方法
直观上,解题人可以采用暴力遍历的方法对目标字符串进行破解,大体思路如下:
① 规定一个由目标答案中可能涉及的字符组成的字符集。
② 设置字符串长度为1,遍历地构造字符串,对所构造字符串调用guess_the_secret接口,查询其是否为目标字符串。
③ 以1为间隔,逐步增加所构造字符串的长度,重复进行过程②,直至找到答案。
然而,上述方法引入了指数级的时间复杂度,消耗资源较多,尤其在目标答案很长的情况下,不具备短时间内解决问题的实操性。
3.2.2 Timing侧信道方法
本Demo中,出题人提供的guess_the_secret接口调用的是基于逐字符对比的字符串比较函数,该函数的实现存在安全问题:当攻击者使用不同的字符串进行试探时,若所构造字符串与目标字符串从首字符起匹配的内容较长,则函数执行耗时较长;若匹配内容较短,则函数执行耗时较短,即,执行时间的差异一定能够反映两个字符串的匹配度,这正是Timing侧信道所依赖的攻击点。
故而,解题者可以基于“可能存在逐字符对比”的前提下,尝试性地发动Timing侧信道攻击,若不成功,再考虑其他方法或降级至3.2.1所述的直观方法。
值得注意的是,Timing测信道方法提供的时间复杂度不再是指数级,而是O(n)级,具体原因不妨结合3.3进行理解。
3.3 攻击实施
本Demo中,Timing侧信道攻击的具体实施方案如下。
① 依次尝试使用a, b, c,…, z等长度为1的字符串,用其作为参数,调用guess_the_secret接口。其中,h字符串与目标字符串happy的第一个字符对比成功,进而进入第二个字符的操作阶段,耗时较长;而其他字符串与目标字符串happy在第一个字符就对比失败,直接返回,耗时较短。由此,比较各执行时间得知,h是目标字符串的第一个字符。
② 固定h,依次在其后接a, b, c,…, z,并将这些长度为2的字符串,分别作为参数调用guess_the_secret接口。类似地,ha字符串作参数时,执行时间最长,而其他h*字符串的执行时间则略短。由此,比较各执行时间得知,ha是目标字符串的前两个字符。
③ 依此类推 …
④ 经过以happ*(*为a到z)为参数调用guess_the_secret接口,并对比执行时间,确定第五个字符为y。由于以happy为参数调用guess_the_secret返回值为0,故猜测终止,得到题解即happy。
其中,对各字符进行猜测的示例代码如下图所示。
其中,字符集范围选择了a-z。同时,通过rdtsc指令进行高精度的时间获取与执行时间测量,进一步地,通过多次执行对单词消耗的时间进行放大,使得不同字符之间的时间差异更加明显。最终,通过遍历字符集,选取出耗时最长的情形所对应的字符,并认为该字符即目标字符串当前位置的字符。
本例的执行效果如下图所示。
本Demo中,通过Timing侧信道攻击,将解题所需要的指数级时间复杂度简化为O(n)级时间复杂度,故而能够迅速取得结果。
四. Timing侧信道的防御
基于前面的讨论,本章给出针对Timing侧信道的一些防御手段,供参考。
① 对于安全敏感的业务逻辑,减少不必要的分支,使得同一业务逻辑在不同场景下的耗时尽可能相近。
② 针对涉及网络传输的场景,可以在报文中引入MAC作为校验,以降低攻击者通过中间人方式获得原始传输内容,并通过调整内容实施Timing侧信道攻击的可行性。
③ 针对诸字符串对比场景,可选方法如下:
1> 可以引入hash操作。例如,对于安全敏感场景,不再诸个字符地对比两个字符串,而是逐个字符地对比两个字符串的hash值。
例如,自首个字符起局部匹配的两个字符串,其hash值可能相差极大,对比过程会立刻返回,这样一来,无法通过调整局部匹配的长度可控地影响对比时间,从而使Timing侧信道失效。
2> 可以采用已知安全的库函数或实现相对更加安全的constant-time对比操作。
示例实现为:
值得注意的是,该方法中,同样存在Timing侧信道攻击点,然而,通过攻击只能得到秘密字符串的长度,而当秘密字符串很长时,爆破其具体内容仍然是十分困难的。
参考文献
[1] Mayer J S D, Sandin J. Time trial: Racing towards practical remote timing attacks[J]. Black Hat US Briefings, 2014.