基于类的冒充

时间:2010-12-14 15:19:37

标签: java class impersonation

一个班级是否有可能冒充其身份?例如,类A尝试访问类B方法。类B方法使用getClass().getName()来尝试检查类A以确保它是谁。可以冒充身份吗?例如课程C冒充课A以通过getclass().getName()班级B用于支票?

如果类B想要对下面的示例方法有效的检查实现getClass().getName(),我该如何在下面的示例代码中正确实现它?

public byte[] getStoragePrivateKey(String application) {
    if (application.getClass().getName().equals("correctClass") {
        // Allow access to Private Key.
    } else {
        // Access denied
    }
}

以上示例是系统中试图访问系统内部密钥服务器数据库的插件小程序的模拟。

2 个答案:

答案 0 :(得分:2)

您可以使用多个类加载器执行此操作。每个类别的laoder可以有一个具有相同名称的类,这是不同的。

但是,如果你能绕过这个“安全”,我建议你只使用反思

编写验证的更简单方法是

if (application.getClass() == CorrectClass.class) {

实施验证的改进方法是使用

StackTraceElement[] stes = Thread.currentThread().getStackTrace();
if (stes[0].getClassName().equals("correctClass") {

这可确保调用者来自正确的类名。它仍然可以通过类加载器进行欺骗。

sun.misc.Unsafe类使用类似后者的东西来保护getUnsafe()方法。标准的工作是做。

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unafe = theUnsafe.get(null);

如果您想知道为什么Unsafe受到保护以及您可能想要访问的原因请查看方法列表。 ;)

编辑:Unsafe.getUnsafe()过去受到保护,但在最新的源代码中似乎不再存在。可能是因为检查很容易被绕过。 ??

答案 1 :(得分:2)

这不起作用: 在您的示例中,application.getClass().getName()将始终返回"java.lang.String",因为您将获得“application”参数的类型。

此外,在Java中,被调用的方法无法找到调用它的类型,因此,您应该检查您的设计,实现其他类型的访问控制。

编辑:让我根据您的代码添加一个示例,说明如何尝试检查调用者的类型,以及如何避免从其他来源调用:

//Change the String for an Object, to allow the invoker pass a 
//reference to itself
public byte[] getStoragePrivateKey(Object application) {
    if (application.getClass().getName().equals("correctClass") {
        // Allow access to Private Key.
    } else {
        // Access denied
    }
}

从引用类型A,调用可以是:

  B b=new B();
  byte[] key=b.getStoragePrivateKey(this);

从C“模仿者”类调用它会失败,因为这是一个C.class实例:

  B b=new B();
  byte[] key=b.getStoragePrivateKey(this);

但是,避免验证它就像:

  B b=new B();
  A a=new A();
  byte[] key=b.getStoragePrivateKey(a);