在 JVM 级别阻止类的实例?

Posted

技术标签:

【中文标题】在 JVM 级别阻止类的实例?【英文标题】:Block instances of a class at the JVM level? 【发布时间】:2020-10-27 13:28:44 【问题描述】:

有没有办法配置 JVM 来阻止正在创建的类的实例?

我想这样做是为了确保 JVM 中运行的任何服务都不允许创建在 CVE 中被识别为安全风险的类的实例,让我们调用该类 BadClass

注意:我正在寻找一个通用的解决方案,因此以下内容纯粹是附加信息。我通常会通过切换库或将其升级到没有漏洞利用的版本来解决这个问题,但它是一个更大的库的一部分,在一段时间内不会解决这个问题。所以我什至没有在任何地方使用BadClass,而是想完全阻止它。

【问题讨论】:

我猜想使用自定义安全管理器,尽管我绝对没有关于如何阻止加载类的参考。它是一种内置机制,用于在相关时将小程序沙箱化。 与安全管理器角度相关(可能重复):***.com/questions/991703 【参考方案1】:

我不知道 JVM 参数,但这里有一些替代方案可能会让您处于满足您要求的位置:

    您可以编写一个自定义类加载器,让您可以很好地控制要做什么。正常用例是插件加载等。在您的情况下,这是在 devops 级别上的更多安全治理。

    如果您有一个带有集成测试的 CICD 管道,您还可以使用 -verbose:class 参数启动 JVM,并查看在运行测试时加载了哪些类。看起来有点hacky,但可能适合您的用例。只需将所有内容都投入到游戏中,由您来判断最合适的人选。

    根据您的构建系统(Maven?),您可以限制仅在您的私有缓存库上构建应用程序。所以你应该完全控制它,并在两者之间放置一个库 - 审查层。这也将在开发人员和存储库管理员之间分担责任。

【讨论】:

这里棘手的部分:许多更大的现实世界安装(使用“更大库”的东西)可能已经带有自己的类加载器。你真的想进入那个游戏吗?然后,正如我在回答中所写:当然,您可以了解该类何时被使用,但是您如何实际上阻止它的使用......对JVM进行分段错误? 我并不是说它是最好和最通用的选择。事实上,我只是列出了 3 个选项,它们可能 适合一种或另一种公司情况。我个人认为这比声明一个全球性的 NOGO 更好。请不要误会我的意思——我明白了你的论点,这些论点本身是有道理的。但最后我们都远离“真正的”问题(我相信这来自需求)。我了解到,有时稍微不同的方法可能会奏效。 是的,这是来自我们公司安全部门的要求——除非解决了这些问题,否则我们的服务无法投入生产,在这种情况下,这个类被包含在 spring boot 中, 但这是一个会不断出现的一般概念 - 在更大的库中没有解决的问题,我们甚至没有使用。 问题是这是否需要主动(maven 解决方案)、禁止(构建失败)或追溯(让应用程序崩溃或拆除)。如果最后一个选项是 ol,您可以简单地使用 -JVM 选项 verbose:class 并使用日志收集框架(logstash 或类似的)或扫描程序进程来搜索坏类。然后您可以根据警报采取行动。 另一种可能的解决方案是使用 maven 动态删除坏类,并为有问题的坏库创建一个新的工件(发布版本),[如本文所述](akes an现有的 JAR,解压它并删除一个类并制作一个新的工件....gochev.blogspot.com/2014/07/…)【参考方案2】:

一个明显的不回答:不要不要甚至尝试!

如果具有此依赖关系的较大库想要调用该方法怎么办?那应该怎么办?

换句话说,您的屏蔽应该做什么?

抛出一些Error 实例,导致JVM 崩溃? 返回 null,以便(可能很久以后)其他代码运行到 NPE 中?

请记住:该类不存在于虚空中。有 other 代码调用它。那个代码还没准备好让你进来,好吧,再做什么?!

我认为这些问题没有很好的答案。

所以,如果你真的想“操纵”事物:

尝试将该特定类的不同版本潜入到您的类路径中。要么是官方的,没有安全问题,要么是符合所需接口并且危害较小的东西。或者,如果您敢于走这条路,请按照其他答案的建议去做,并进入“我自己的类加载器”业务。

无论如何,您的第一个目标是:在此处明确您的要求。 阻塞是什么意思?!

【讨论】:

感谢您的反馈 - 我对任何类型的阻塞持开放态度,因此抛出错误或返回 null 或不加载类 - 对我来说一切都很好。对我来说,BadClass 永远不应该用在任何我在 JVM 中运行的服务中,这实际上是超过 30 个微服务当然这些都是在多个阶段开发/测试的,通过 dev/test/staging/performance,然后最后是 prod环境,所以我完全可以接受一项服务在所有环境中都可怕地死去,但生产。 不过,当你的代码调用 biglib,而 biglib 调用 BadClass 时,你会怎么做?停止使用 biglib?! 是的,如果出现这种情况,那么我们必须解除阻止 - 但是我们会在开发时知道发生了什么,并且可以尝试找到其他解决方法 - 但我不知道认为我们完全在使用 BadClass - 即 BigLib 有很多很多类,我认为根本没有使用 BadClass【参考方案3】:

您是否考虑过使用Java Agent?

它可以拦截任何类加载器中的类加载,并在类实际加载之前对其内容进行操作。然后,您可以修改类以删除/修复它的错误,或者返回会在静态初始化程序中引发错误的虚拟类。

【讨论】:

以上是关于在 JVM 级别阻止类的实例?的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 2.6:实例/数据库级别的maxTimeMS

JVM的相关概念

JVM原理是啥?

一:从JDK源码级别彻底剖析JVM类加载机制

Java中锁的级别

Java虚拟机工作原理详解 ( 二 )