java - 限制类及其成员的可访问性是否是更安全代码的有效做法?
问题描述
根据Oracle 安全编码指南指南 4-1/EXTEND-1 和指南 4-5/EXTEND-5,您应该限制类及其成员的可访问性,作为防止攻击者恶意覆盖的安全控制。
设计继承的类和方法或将它们声明为 final。如果不是最终的,一个类或方法可能会被攻击者恶意覆盖。不允许子类化的类更容易实现和验证它是安全的。
在现实世界的场景中,攻击者如何真正利用以下不安全的类?即使该类已经加载到正在运行的 JVM 中,他/她能否做到这一点?
public class PasswordVerifier {
private String regex;
public PasswordVerifier(String regex) {
this.regex = regex;
}
public boolean isPasswordValid(String password) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(password);
return matcher.find();
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
}
如果我们谈论的是可以访问源代码的恶意内部人员,他难道不能一开始就删除 final 修饰符(如果已经存在的话)或以任何方式改变类本身吗?
解决方案
无论是否有final
关键字,该代码都不安全。它还很大程度上取决于它运行的环境。
如果 JVM 已经在运行:
困难得多。我确实注意到通过 C++ 进行注入的一些事情,这可能会在类加载时为使用ASM生成/修改运行时类提供可能性。这需要将 ASM 作为依赖项包含在内,而大多数项目都没有。使用这种方法,该类是否是最终的都没有关系。从那里,攻击者可以修改该isPasswordValid()
方法以始终返回 true。
如果该类已经加载,我认为这是不可能的。在这里查看更多:
这也提供了一个有趣的阅读:
如果代码被用作库:
容易得多。攻击者可以final
像你说的那样删除修饰符,或者使用 ASM 之类的东西生成一个新类,该类首先没有final
修饰符。也可以只使用sun.misc.Unsafe
,如这里 repo所示。这将允许他们生成一个扩展不再是最终类的新类。
另一种方法是只使用 ASM 在加载类时对其进行修改,这样会更容易。
可能有更多的方法可以做到这一点,我自己还没有实际测试过这些方法,但我认为这两种情况都有可能,具体取决于环境。
编辑:我忘了提到这些东西中的一些可能不适用于更高版本的 Java,其中类操作和依赖访问受到更多限制。我将所有这些都建立在您使用 Java 8 的基础上,大多数人仍然在使用 Java 8。
编辑2: 我刚刚在这里找到了这篇文章,它提供了一种通过调试模式执行任意代码的方法,也可以用来操作类。关联
推荐阅读
- c++ - 如何在 Ubuntu 中将内容从一个文件传输到另一个文件。?
- excel - How to insert a point in a txt file?
- python - Flask-sqlalchmey 行更新反映在 sqlite DB 中
- scala - SCALA 和弹性搜索:将符号添加到类路径(Databricks)
- cleartool - rmstream 的 CCRC 命令
- python-3.x - 如何获取键的索引?
- angular - How to make observable wait for the previous observable to complete
- python - 有没有一种简单的方法可以在 python 的列表中输出一个列表?像这样 [[0,1], [2,3]]
- javascript - 如何根据数组遍历数据?
- sql - 为什么在尝试插入数据时出现此错误 ORA-00904 "PBIRTHDATE"