(1)为探查这种缺陷,首先列出应用程序中可能出现的反常事件和条件,以及以非常规方式向浏览器返回有用的用户信息的情况,如返回调试错误消息。
(2)同时以两名用户的名义使用应用程序,使用一名或两名用户系统性地创造每一个条件,并确定另一名用户是否受到影响。
最近,这种逻辑缺陷给几个大型应用程序造成了严重威胁。
1.功能
应用程序执行采用一种安全、多阶段的登录机制,要求用户提交几个不同的证书才能获得访问权限。
2.假设
验证机制接受了大量设计审查与渗透测试。应用程序的所有者确信,攻击者无法向验证机制发动有效攻击,从而获得未授权访问。
3.攻击方法
实际上,验证机制存在一个细小的缺陷。有时,顾客登录后,他可以访问另外一名用户的账户,查看该用户的所有金融信息,甚至使用其他用户的账户进行支付。最初,应用程序的行为完全是随机性的:在获得未授权访问之前,用户并没有执行任何非法操作;再次登录时,反常现象也不会重复出现。
经过一些调查,银行发现,如果两个不同的用户在同一时间登录,就会出现错误。而且,并不是每次出现这种情况都会发生错误(仅在少数情况下错误才会发生)。发生这种错误的根本原因在于,应用程序将与新近通过验证的用户有关的标识符临时保存在一个静态(非会话)变量中。改写这个值不久后,应用程序再读取这个变量的值。如果在这个过程中有另外一个线程(处理另一个登录)写入到变量中,早先登录的用户就会分配到属于随后登录的用户的会话。
这种漏洞源于与前面错误消息示例中相同的错误:应用程序使用静态存储保存应根据独立线程或会话保存的信息。然而,由于这类错误不会反复出现,当前示例中的缺陷更难发现,也更难对其加以利用。
这种缺陷叫做“竞态条件”,因为其中的漏洞仅在某些特殊情况下才会出现,而且存在时间很短。由于漏洞仅在短时间内存在,攻击者面临着一次“竞赛”,必须赶在应用程序关闭它之前对其加以利用。如果攻击者是应用程序的本地用户,他就有可能知道竞态条件出现的具体情景,并在有效的时间内利用漏洞。如果攻击者属于远程用户,要想实施攻击就比较困难。
如果远程攻击者了解到这种漏洞的本质,那么他就可以通过使用一段脚本连续进行登录,并查看被访问账户的详细资料,从而设计出有效的攻击方法。但是,由于这种漏洞可被利用的时间极短,攻击者可能需要提交数目庞大的请求。
鉴于以上原因,我们在正常渗透测试过程中没有发现竞态条件也就不足为怪了。只有当应用程序的用户数量足够庞大、可导致反常现象(由顾客上报)发生时,这种条件才会出现。然而,如果对验证与会话管理逻辑进行严格的代码审查,还是有可能发现此类问题。