弱引用的安全风险是什么?
链接的文章用非常笼统的术语说话,因为它谈论的是垃圾收集器中弱引用的通用实现。他们正在说明潜在的机密性问题,因为在他们正在研究的抽象级别上,可能出现的特定类型的侧信道攻击完全取决于个人实现。
首先,了解弱引用的作用很重要。
在垃圾回收系统中,GC 的任务是清除程序不再使用的对象。检测对象是否在使用中通常是通过引用计数来实现的,其中程序将引用元数据存储在对象旁边以帮助 GC,当使用对象和作用域进入和超过其生命周期时,递增和递减引用计数器。传统的引用类型通常称为强引用。
强引用的一个缺点是您无法在不阻止 GC 处理对象的情况下观察对象。例如,您可能希望提供内部调试命令来显示有关集合中已分配对象的信息,而无需创建导致对象永久位于堆上直到程序退出的强引用。这就是弱引用有用的地方——它们向 GC 表明程序仍然对对象感兴趣,但对象保留并不是绝对必要的。更重要的是,它们实现了一个过程,应用程序可以通过该过程检查(或通知)GC 是否已删除对象,并且很可能一些确保 GC 在执行代码时无法删除对象的锁定机制直接对对象进行操作.
弱引用的具体实现取决于语言的通用内存架构和类型范式,而 GC 本身通常被认为是一个黑盒。在记录的具体行为之外,依赖 GC 的特定行为对于用户代码来说是不好的做法。但是,作为特定场景中的攻击者,您的好处是能够研究正在使用的特定实现的内部结构并将它们用于您的优势。
作为一个理论示例,假设有一个 GC,其对弱引用对象的处理过程如下:
- 有内存压力吗?
- 您是否处理了所有具有零引用(弱引用或其他引用)的对象?
- 是否还有内存压力?
- 优先考虑长时间未访问的对象。
- 优先考虑弱引用较少的对象。
- 优先考虑尺寸较大的对象。
现在,如果攻击者可以检测到某个特定对象已被释放(某些 GC 允许用户定义的终结代码,这可能会以某种方式将事件泄漏到外部),那么他们就会知道存在内存压力,其他对象很可能有也被从堆中清除,他们知道被释放的对象可能有一段时间没有被访问,它可能只有一两个弱引用,并且它可能比堆上的其他对象大。
这对于一系列侧信道攻击,甚至对于协调其他攻击类型(例如定时攻击)来说可能是非常有用的信息。当在特定应用程序的上下文中理解时,它也可能很有用,例如,如果弱引用对象仅在用户出现在系统时被持续访问,则其处置可能很好地表明用户不在他们的站点。
这里要记住的重要一点是漏洞是理论上的,本文只是试图让 GC 实现者在设计弱引用功能时牢记这些问题。
这是一个延伸,但请考虑是否仅当代码沿某个路径向下流动时才分配某个对象。
if (secret_bit_is_set(hidden_flags))
{ Object = new TellTale(); }
这是边信道攻击的一个子集,通常与定时攻击密切相关。
或者,如果我试图弄清楚何时可以安全地攻击资源,则旨在监视某些资源的对象的生命周期可能会很有用。