第7章 攻击会话管理
在绝大多数Web应用程序中,会话管理机制是一个基本的安全组件。它帮助应用程序从大量不同的请求中确认特定的用户,并处理它收集的关于用户与应用程序交互状态的数据。会话管理在应用程序执行登录功能时显得特别重要,因为它可在用户通过请求提交他们的证书后,持续向应用程序保证任何特定用户身份的真实性。
由于会话管理机制所发挥的关键作用,它们成为针对应用程序的恶意攻击的主要目标。如果攻击者能够破坏应用程序的会话管理,他就能轻易避开其实施的验证机制,不需要用户证书即可伪装成其他应用程序用户。如果攻击者以这种方式攻破一个管理用户,那么他就能够控制整个应用程序。
和验证机制一样,通常会话管理功能中也存在着大量缺陷。在最容易遭受攻击的情况下,攻击者只需递增应用程序向他们发布的令牌值,就可以转换到另一名用户的账户。在这种情况下,任何人都可以访问应用程序的全部功能。另一方面,如果应用程序受到严密保护,攻击者必须付出巨大的努力,破解几层模糊处理并实施复杂的自动攻击,才能发现应用程序中存在的细小漏洞。
本章将分析我们在现实世界的Web应用程序中发现的各种漏洞,详细说明发现和利用这些漏洞所需执行的实际步骤。最后还将描述应用程序为防止这些攻击所应采取的防御措施。
错误观点 "我们使用智能卡进行验证,没有智能卡攻击者不可能攻破用户会话。"
无论应用程序的验证机制多么安全稳定,用户随后提出的请求只有通过会话才能与验证机制建立联系。如果应用程序的会话管理存在缺陷,攻击者仍然能够避开可靠的验证机制,危及用户的安全。
7.1 状态要求
从本质上讲,HTTP协议没有状态。它基于一种简单的请求-响应模型,其中每对消息代表一个独立的事务。协议本身并无将某位用户提出的各种请求联系起来的机制,并将它们与Web服务器收到的所有其他请求区分开来。在Web发展的早期阶段,并没有必要建立这种机制:因为Web站点公布的是任何人都可以查阅的静态HTML页面。但如今,情况已经发生巨大变化。
绝大多数的Web"站点"实际为Web应用程序。它们允许用户注册与登录;帮助用户购买及销售产品。它们能够在用户下次访问时记住他的喜好。它们可根据用户的单击和输入,通过动态建立的内容提供丰富、多媒体形式的使用体验。为执行这些功能,应用程序就需要使用会话。
支持登录是会话在应用程序中的最主要用途。输入用户名和密码后,可以用输入的证书所属的用户身份使用应用程序,直到退出会话或由于会话处于非活动状态而终止。用户不希望在每个应用程序页面重复输入密码。因此,一旦用户通过验证,应用程序就为他们建立一个会话,把所有属于这个会话的请求当作该用户提出的请求处理。
不具备登录功能的应用程序通常也需要使用会话。许多出售商品的站点并不要求顾客建立账户。但是,它们允许用户浏览目录、往购物篮中添加商品、提供交货信息并进行支付。在这种情形下,就没有必要验证用户的身份:应用程序并不知道或关心绝大多数用户的身份。但是,为了与他们进行交易,应用程序需要知道它收到的哪些请求来自同一名用户。
执行会话的最简单、也是最常见的方法就是向每名用户发布一个唯一的会话令牌或标识符。用户在随后向应用程序提出的每一个请求中提交这个令牌,帮助应用程序在当前请求与前面提出的请求之间建立关联。
在大多数情况下,应用程序使用HTTP
cookie作为在服务器与客户间传送这些会话令牌的传输机制。服务器对新客户的第一个响应中包含以下HTTP消息头:
客户随后提出的请求中包含如下消息头:
这种标准的会话管理机制非常容易受到各种类型的攻击。当攻击会话机制时,攻击者的主要目标是以某种方式劫持一名合法用户的会话,并因此伪装成这名用户。如果该用户已经通过应用程序的验证,攻击者就可以访问属于这名用户的私有数据,或者以他的身份执行未授权操作。如果该用户未能通过验证,攻击者仍然能够查看用户在会话过程中提交的敏感信息。
和前面示例中运行ASP.NET的Microsoft IIS服务器一样,许多商业Web服务器和Web应用程序平台执行它们自己的基于HTTP
cookie的非定制会话管理解决方案。Web应用程序开发者可使用它们提供的API将会话依赖功能与这种解决方案整合起来。
事实证明,一些非定制会话管理解决方案易于受到各种攻击,导致用户的会话被攻破(这一问题将在本章后面讨论)。此外,一些开发者发现,他们需要比内置解决方案所提供的控制更加全面的会话行为控制,或者希望避免基于cookie的解决方案中存在的一些固有漏洞。鉴于这些原因,安全性至关重要的应用程序(如电子银行)通常使用预定义或并非基于cookie的会话管理机制。
会话管理机制中存在的漏洞主要分为两类:
会话令牌生成过程中的薄弱环节;
在整个生命周期过程中处理会话令牌的薄弱环节。
我们将分别分析这些弱点,描述在现实世界的会话管理机制中常见的各种漏洞,以及发现和利用这些漏洞的实用技巧。最后将描述应用程序为防止这些攻击所应采取的防御措施。
渗透测试步骤
许多应用程序使用标准的cookie机制传输会话令牌,这样可直接确定哪些数据包含令牌。然而,在其他情况下,可能需要进行一番探测才能找到令牌。
应用程序常常使用几个不同的数据共同表示一个令牌,包括cookie、URL参数和隐藏表单字段。其中一些数据可用于在不同的后端组件中维护会话状态。如果没有得到确认,不要想当然地认为某个特殊的参数就是会话令牌,或者只使用一个数据追踪会话。
有时,一些数据似乎是应用程序的会话令牌,其实并非如此。具体来说,由Web服务器或应用程序平台生成的标准会话cookie可能存在,但实际并不被应用程序使用。
用户通过验证后,观察浏览器收到哪些新数据项。应用程序通常会在用户通过验证后建立新的会话令牌。
为确定应用程序到底使用哪些数据项作为令牌,找到一个确信依赖会话的页面(如某一名用户的"用户资料"页面),并向它提出几个请求,系统性地删除疑似被用作令牌的数据。如果删除某个数据后,应用程序不再返回会话依赖页面,即可确定该数据为会话令牌。Burp
Repeater是执行这类测试的有效工具。
会话替代方案
并非每一种Web应用程序都使用会话,一些具备验证机制、功能复杂的安全性至关重要的应用程序选择使用其他技术管理状态。有两种会话替代方案。
HTTP验证。使用各种基于HTTP验证技术(基本、摘要、NTLM验证等)的应用程序有时避免使用会话。在HTTP验证中,客户组件使用HTTP消息头通过浏览器直接与验证机制交互,而不是通过包含在任何单独页面中的针对特殊应用程序的代码与验证机制交互。一旦用户在浏览器对话框中输入他的证书,浏览器将会在随后向相同服务器提出的每个请求中重复提交这些证书(或重复执行任何必要的握手)。这种做法等同于应用程序使用基于HTML表单的验证,并在每个应用程序页面插入一个登录表单,要求用户通过他们执行的每一项操作重复验证自己的身份。因此,如果使用基于HTTP的验证,应用程序可以不必使用会话,而通过多个请求重复确定用户身份。然而,基于因特网的应用程序很少使用HTTP验证。而且,由于发展完善的会话机制能够提供其他用途非常广泛的功能,实际上,几乎所有的Web应用程序都采用这种机制。
无会话状态机制。一些应用程序并不发布会话令牌管理用户与应用程序的交互状态,而是传送所有必要数据(一般保存在cookie或隐藏表单字段中),由客户管理状态。实际上,这种机制以类似于ASP.NET
ViewState的方式使用无会话状态。为保证这种机制的安全,必须对通过客户传送的数据加以适当保护。这通常要求建立一个包含所有状态信息的二进制巨对象,并使用一种公认的算法对这些数据进行加密或签名。还必须在数据中包含足够的上下文,以防止攻击者将在应用程序某个位置收集到的状态对象提交到另一个位置,造成某种意外行为。应用程序还必须在对象的数据中包含一个终止时间,执行与会话超时相同的功能。我们已在第5章详细介绍过通过客户传送数据的各种安全机制。
渗透测试步骤
如果应用程序使用HTTP验证,它可能并不执行会话管理机制。使用前面描述的方法分析任何可能是令牌的数据的作用。
如果应用程序使用无会话状态机制,通过客户传送所有必要数据进行状态维护,有时我们可能很难检测出这种机制,但如果发现下列迹象,即可确定应用程序使用这种机制。
向客户发布的可能令牌的数据相当长(如100B或超过100B)。
应用程序对每个请求做出响应,发布一个新的数据。
数据似乎被加密(因此无法辨别其结构)或包含签名(由有意义的结构和几个字节的无意义二进制数据组成)。
应用程序拒绝通过几个请求提交相同数据的做法。
如果相关证据明确表明应用程序并未使用会话令牌管理状态,那么本章描述的任何攻击都不可能达到其目的。因此,最好着手去寻找其他严重的漏洞,如访问控制不完善或代码注入。