事件驱动系统的安全风险

事件驱动系统

事件驱动系统的目的是高效地管理同时执行并相互交互的多个对象和环境。一个事件驱动系统是一个由对象组成的系统,它们使用消息传递机制相互交互。这个机制由一个独立的组件控制,通常称为事件调度程序,它充当对象之间的中介。

  • 被传递的数据称为事件,它们可以以未经处理的形式(原始事件)来自输入设备,也可以是对象之间通信的结果。
    • 对象以事件消息的形式接收事件,通常由固定长度的事件类型标识符和事件参数组成。
  • 每个对象都有一个指定的编程过程,称为事件过程,它为每种类型的事件消息调用个别的事件处理程序。
  • 自定义事件消息被定义为可能将其字段设置为任何值的事件消息。受害者可以是已经运行的应用程序,也可以是由攻击者发起并通过发送适当的事件消息进行控制的应用程序。

例子:假设在一个用户界面中,用户点击绘图应用程序窗口的客户区域的左键。这会生成一个包含鼠标位置和那一刻按下的鼠标按钮的原始事件。事件调度程序接收原始事件,并添加诸如目标应用程序的信息,创建一个事件消息,并将其放入队列中,以供接收应用程序获取。接收应用程序检查新消息并找到它。随后,执行事件过程,并选择适当的事件处理程序来处理特定的鼠标事件消息。

事件驱动系统攻击者的能力

不同的事件驱动系统在事件处理方面具有不同的特点,因此攻击者在攻击过程中可能具有以下几个能力中一个或者多个。

  1. 枚举:要求对象必须能够枚举(遍历)事件驱动系统的对象并检索可帮助进行攻击的描述性信息。枚举对象是一种常见的功能,通常没有对可以枚举的对象施加任何限制。例如,EnumWindows命令可以设置回调函数,并将其传递给系统以便为每个可用窗口执行迭代。这个函数可以使用第二个参数将窗口的识别信息返回给主程序。
  2. 发送:要求对象必须能够向其他对象发送事件消息,包括可能是自定义事件消息的非特权对象向至少一种更高特权对象发送事件。在事件驱动系统中,无需任何访问控制即可将事件发送给任何接收方的能力是常见的。具体来说,要向另一个对象发送事件,应用程序调用事件调度程序的导出过程,将事件放入系统的事件队列中。事件调度程序检查其队列中的未调度消息,并将它们分发给各个对象队列。当攻击者具有发送能力,这相当于,将消息放置在事件调度程序的消息队列中的方法不会检查消息的来源。例如,PostMessage命令向受害者进程发送一个事件消息,可以强制其终止。
  3. 拦截:要求对象必须能够拦截来自其他对象的事件消息,包括非特权对象拦截高特权对象的事件。拦截功能通常用于调试目的和帮助自动化软件测试。例如,SetWindowsHookEx命令设置一个钩子,一个能够在实际接收者之前接收所有与键盘相关的消息的过程。

潜在的风险

事件驱动模型的拒绝服务攻击

在一个绘图应用程序中,用户可以通过按住鼠标按钮、拖动鼠标然后释放鼠标按钮来画一条线。在这个三步骤的过程中,绘图应用程序从鼠标设备接收到以下消息:

“WM_LBUTTONDOWN -> WM_MOUSEMOVE -> WM_MOUSEMOVE -> WM_MOUSEMOVE -> WM_LBUTTONUP”。

攻击者可以在鼠标按钮实际释放之前发送第二个WM_LBUTTONDOWN,程序员可能不会检查源代码的有效性。如果使用计数器(而不是标志)来跟踪鼠标按钮的按下或松开状态,那么应用程序可能会混淆,并且认为鼠标按钮一直按下。

运行应用程序的修改

如果应用程序希望将文本框的状态从启用更改为禁用,以显示它不再使用,它会向特定组件发送一个禁用消息。在安装应用程序时,通常会向用户显示一个最终用户许可协议(EULA),用户必须遵守该协议才能继续安装。这个协议显示在一个通常是只读的文本框中,以防止被修改。为了继续安装,用户别无选择,只能选择接受单选按钮,隐式接受显示的许可协议。然而,攻击者可以轻易地向EULA文本框发送一个精心构造的事件消息,将其转换为可修改的状态。然后,在选择接受并继续之前,可以任意编辑。这种修改过程的存在并不使许可协议无效,因为攻击者故意修改了许可内容。

未经授权访问对象

当满足条件枚举和发送时,任何对象都可以向任何其他对象发送事件。因此,一个非特权对象可以通过发送事件来操作一个特权对象。

在Windows操作系统中,如果管理员已登录,非特权的木马程序可以发送适当的事件序列来添加一个新的管理员账户。否则,木马程序可以暂时禁用个人防火墙以便与互联网通信。另外,攻击者可以在管理员尝试向服务进行身份验证时截取管理员的密码。身份验证过程通常涉及在两个文本框中输入用户名和密码。密码文本框具有一个属性,它会在密码键入的每个字符位置显示星号。另一个属性是,在此文本框上无法执行复制和粘贴操作。无法执行复制和粘贴操作是由于第一个属性隐藏了用户输入。攻击者可以通过发送消息暂时禁用密码隐藏属性来绕过这种保护,以执行复制和粘贴操作,然后再次使用消息启用它,这个操作发生得足够快,以至于受害者没有观察到视觉上的变化。

执行恶意代码。

事件消息是一个固定和有限长度的结构,人们期望它不允许传递恶意代码给受害者。

攻击者可以使用间接方法,例如让受害者对象去读取文件,来将恶意代码放入受害者的地址空间中。因此,可以构建自定义的事件序列执行此代码。另一种情况是与缓冲区溢出的结合。攻击者发送自定义的事件消息序列,以实现缓冲区溢出。在Windows 2000中,应用程序可以执行驻留在其地址空间中的代码。因此,攻击者可以找到受害者应用程序中已有的函数并执行它。

事件拦截。

能拦截发送给对象的事件使得攻击者能够突破对象与系统之间通信的机密性。在用户界面环境中,拦截键盘事件可以轻松地揭示使用键盘输入的身份验证详细信息。在另一种情况下,一些公钥算法中密钥对生成的随机性基于用户在屏幕上随机移动鼠标。拦截鼠标移动可能导致私钥的计算泄露。

成因

风险出现的原因有两个方面。

  • 首先,对于事件驱动系统的对象枚举、事件发送和事件拦截,通常没有访问控制机制。这主要是因为添加访问控制会导致性能下降,并增加了访问控制规则的处理复杂性。
  • 其次,很难有效控制发送给对象的错误事件的影响。对象通过与环境的交互来改变状态。如果其安全性受到损害,则是由于其内部逻辑无法有效地过滤输入。

对策

任何对策都应该集中在事件驱动系统的两点上。确定事件的起源和确保对象在接收到各种组合的事件时能正确运行的。

  1. 恶意对象攻击事件驱动系统,通常由于恶意对象能够枚举可用的事件对象,然后向系统发送事件。系统中应该有机制限制对象的枚举和发送事件,只允许特定请求的对象进行。

  2. 此外,应该对可用的事件类型进行安全审查,并标记那些潜在危险的事件,例如传递内存引用的事件。然后,在源代码的安全检查中,应该检查这些事件类型是否存在被利用的可能性。

  3. 此外,事件调度程序应该能够识别来自可信对象发送的事件与来自其他源(例如输入设备或系统本身)发送的事件的区别。对象用于发送消息的系统过程可以将它们标记为不安全,并将其转发给防火墙组件。或者,应用程序本身可以注意到特殊标志并相应地处理这些事件。

  4. 此外,在计算设备(如自动取款机)的安全评估中,应该进行注入恶意事件的威胁测试。

  5. 最后,可以通过过滤恶意事件消息提供一定程度的安全性。尽管这会降低性能。

术语关联

事件驱动:消息队列、事件触发
安全风险:攻击、漏洞、恶意事件

参考文献

[1] Xenitellis, Simeon. “Security vulnerabilities in event-driven systems.” Security in the Information Society: Visions and Perspectives (2002): 147-160.

你可能感兴趣的:(安全,消息队列,攻击,事件驱动)