You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 18 Next »

A non-final class or method, which is not meant to be inherited, can be overridden by an attacker, if it is not declared as final [3].

In case inheritance is to be limited to trusted implementations for a public, non-final class, then the class type should be confirmed before creating the instance at each place where an instance of the non-final class can be created. A SecurityManager check should be enforced on detecting a subclass (Chapter 6 of [2]).

A non-final class can be subverted simply by declaring a malicious class that inherits from the non-final class which implies that there is no need for reflection. However, reflection is necessary if the non-final class is private or otherwise inaccessible to the attacker.

Non Compliant code example:

In this code, an attacker can easily create an instance and override methods of BankOperation.

class BankOperation{


	//the account balance has already been retrieved from the database and stored in the foll variable
    private Integer balance = 5000;


    public BankOperation() {

    	//invoke java.lang.Object.getClass to get class instance
    	Class clazz = getClass();
    	//shows the class of the instantiated object
    	System.out.println(clazz);
    }

    public void getBalance() {
        System.out.println("The current balance is: $" + balance);
    }

}

//this class has been written by the attacker
public class SubClass extends BankOperation {

	public void getBalance() {

		//The attacker can change his account balance to any value he wants.
		Integer modifiedBalance = 0;
		//to read the new balance from the attacker
		InputStreamReader input = new InputStreamReader(System.in);
		Field balance=null;
        BufferedReader reader = new BufferedReader(input);
		System.out.print("Enter balance: ");
		try {
			modifiedBalance = Integer.parseInt(reader.readLine());

			//this gets the private field from the superclass
			balance = this.getClass().getSuperclass().getDeclaredField("balance");

			//this changes the accessibility so that field can now be accessed
			if (!Modifier.isPublic(balance.getModifiers())){
				balance.setAccessible(true);
			}
			//retrieve the original balance
			System.out.println("Original Balance: $"+balance.get(this));
			//change the balance
			balance.set(this, modifiedBalance);
			//display the new changed balance
			System.out.println("New Balance: $"+balance.get(this));

		} catch (Exception e) {
			e.printStackTrace();
		}
    }

	public static void main(String[] args) {
        SubClass subclass = new SubClass();
        subclass.getBalance();
    }
}

Compliant Solution:

This compliant solution can be achieved by using the keyword final, thus ensuring that the sensitive class cannot be extended.

final class BankOperation{
//normal coding...
}

In case the class needs to be extended, then permissions should be checked in case a sub class is detected during construction so that malicious implementations are blocked.

Risk Assessment:

Allowing a non-final class or method to be inherited without checking the class instances, allows an attacker to exploit it.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ33-J

high

probable

high

P3

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website

Reference:

SCG 07 Secure Coding Guidelines for the Java Programming Language


OBJ32-J. Do not allow partially initialized objects to be accessed      06. Objects Orientation (OBJ)      OBJ34-J. Compare classes and not class names

  • No labels