...
| Code Block | ||
|---|---|---|
| ||
public class BankOperations {
public BankOperations() {
if (!performSSNVerification()) {
throw new SecurityException("Invalid SSN!");
}
}
private boolean performSSNVerification() {
return false; //returns true if data entered is valid, else false. Assume that the attacker just enters invalid SSN.
}
public static void greet() {
System.out.println("Welcome user! You may now use all the features.");
}
}
public class UserApp {
public static void main(String[] args) {
BankOperations bo;
try {
bo = new BankOperations();
} catch(SecurityException ex) { bo = null; }
Storage.store(bo);
System.out.println("Proceed with normal logic");
}
}
public class Storage {
private static BankOperations bop;
public static void store(BankOperations bo) {
// only store if it is not initialized
if (bobop !== null) {
bo.greet();
if (bo == null) { else
System.out.println("Sorry, you were denied access to the features.");"Invalid object!");
System.exit(1);
}
bop = bo;
}
}
}
|
To exploit this code, an attacker extends the BankOperations class and overrides the finalizer method. The gist of the attack is the capture of a handle of the partially initialized class. When the constructor throws an exception, the garbage collector waits to grab the object reference. However, by overriding the finalizer, a reference is obtained using the this keyword. Consequently, any method on the base class can be invoked maliciously. Note that, even a security manager check can be bypassed this way.
| Code Block |
|---|
public class Interceptor extends BankOperations {
private static Interceptor stealInstance = null;
public static Interceptor get() {
try {
new Interceptor();
} catch(Exception ex) { } // ignore the exception
try {
synchronized(Interceptor.class) {
while (stealInstance == null) {
System.gc();
Interceptor.class.wait(10);
}
}
} catch(InterruptedException ex) { return null; }
return stealInstance;
}
public void finalize() {
synchronized(Interceptor.class) {
stealInstance = this;
Interceptor.class.notify();
}
System.out.println("Stolen the instance in finalize of " + this);
}
}
public class AttackerApp { //invoke this class and gain access to the restrictive features
public static void main(String[] args) {
Interceptor i = Interceptor.get();
Storage.store(i)
i.greet(); //now invoke any method of BankOperations class
UserApp.main(args); //Invoke the original UserApp
}
}
|
This code is an exception to OBJ02-J. Avoid using finalizers
...
| Code Block | ||
|---|---|---|
| ||
public class BankOperations {
public staticvolatile boolean initialized = false;
public BankOperations() {
if (!performSSNVerification()) {
throw new SecurityException("Invalid SSN!");
}
else
initialized = true;
}
private boolean performSSNVerification() {
return false;
}
public static void greet() {
if(initialized == true) {
System.out.println("Welcome user! You may now use all the features.");
//other authorized code
}
else
System.out.println("You are not permitted!");
}
}
|
...