Reputation: 7450
Is it possible for a class to impersonate its identity? For example, Class A
attempts to access Class B
methods. Class B
methods uses getClass().getName()
to attempt to check Class A
to ensure it is who it is. Can impersonation take place ? e.g. Class C
impersonates Class A
to get pass the getclass().getName()
Class B
uses for checks?
If Class B
wants to implement getClass().getName()
for checks effective on the sample method below, how do I implement it properly in the sample code below ?
public byte[] getStoragePrivateKey(String application) {
if (application.getClass().getName().equals("correctClass") {
// Allow access to Private Key.
} else {
// Access denied
}
}
The above example is a simulation of a plugin applet in the system trying to access an internal key server database in the system.
Upvotes: 1
Views: 335
Reputation: 533660
You can do this with multiple classloaders. Each class laoder can have a class with the same name which is different.
However, I suggest you just use reflections if you can to by-pass this "security"
A simpler way to write the validation is
if (application.getClass() == CorrectClass.class) {
An improved way to implement the validation is to use
StackTraceElement[] stes = Thread.currentThread().getStackTrace();
if (stes[0].getClassName().equals("correctClass") {
This ensures the caller is from the correct class name. It can still be spoofed with class loaders.
The sun.misc.Unsafe class uses something like the latter to protect the getUnsafe() method. The standard work around is to do.
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unafe = theUnsafe.get(null);
If you are wondering why Unsafe is protected and why you might want to get access have a look at the method list. ;)
EDIT: Unsafe.getUnsafe() used to be protected but doesn't appear to be any more in the latest source. Possibly because the check could be easily bypassed. ??
Upvotes: 2
Reputation: 13488
This won't work:
In your example application.getClass().getName()
will always return "java.lang.String"
, as you are getting the type of the "application" parameter.
Moreover, in Java, the invoked method can not find out the type from where it's being invoked, so perhaps, you should check your design, implementing some other kind of access control.
EDIT: let me add an example, based on your code, on how you could try to check the type of the invoker, and how it would not avoid invocations from other sources:
//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
}
}
From the referencing type A, the invoking could be:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
Calling it from a C "impersonator" class, would fail, as this is a C.class instance:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
But, avoiding the validation it's as easy as:
B b=new B();
A a=new A();
byte[] key=b.getStoragePrivateKey(a);
Upvotes: 2