April 18, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Java Performance & Security: Dynamically Loaded Classes, Page 2

  • January 5, 2007
  • By Matt Weisfeld, Matt Weisfeld
  • Send Email »
  • More Articles »

Application Integrity

Although dynamically loading classes provides significant performance advantages, there are also some concerns that have to be addressed.

Unintended design inconsistencies

For example, add to the application that you created in the previous section (refer to Listing 2). The output from this application is what you saw in Figure 3. In this updated example (see Listing 3), a getter method is added, getAccountBalance(), so you can properly inspect the account balance.

Listing 3: Sample Application

class AccountList {

   public static void main(String args[]) {

      System.out.println("In AccountList");
      CheckingAccount myList = new CheckingAccount();

      myList.getAccountBalance();

   }
}

class CheckingAccount {

   protected String accountNumber;
   protected double accountBalance = 1000000.00;

   public void getAccountBalance() {
      System.out.println("Account Balance = " + accountBalance);
   }

}

When this code is executed, the output in Figure 4 is produced.

Figure 4: Class CheckingAccount with getter.

Now, assume that there is a change to the CheckingAccount class and it is edited and compiled without updating the AccountList class, either intentionally or accidentally (I will discuss the intentionally possibility a bit more later).

In this case, you decide to change the name of the getter method from getAccountBalance() to getBalance(), as seen in Listing 4.

Listing 4: Altered CheckingAccount class

class AccountList {

   public static void main(String args[]) {

      System.out.println("In AccountList");
      CheckingAccount myList = new CheckingAccount();

      myList.getAccountBalance();

   }
}

class CheckingAccount {

   protected String accountNumber;
   protected double accountBalance = 1000000.00;

   public void getBalance() {
      System.out.println("Account Balance = " + accountBalance);
   }

}

Note the line in bold within the CheckingAccount class:

public void getBalance() {

The name of the getter now is obviously not the same as the original name (getAccountBalance) that still is expected in the AccountList class, that will still class the object's method, as seen below.

myList.getAccountBalance();

The issue now is that the classes are now out of sync—and it was relatively easy for this to happen. This problem can, and will, cause the application to abort—which is always interesting to test, but you never, ever, want this to happen when the application is live. Figure 5 shows the error that is generated when this application is run with the out-of-sync classes.

Figure 5: AccountList can't find method.

When the AccountList class invokes the getAccountBalance() method of the CheckingAccount class, it just isn't there—so the application fails. This is a serious configuration management issue and can cause nightmares when updating clients who already have a working system.

Malicious intent

Although most development inconsistencies are unintentional, unfortunately, there are situations when someone may try to intentionally sabotage an application. Of course, there are many examples that can demonstrate potential risks with code; you will present a situation that lies at the heart of a major security risk with dynamically loaded classes.

Continue with the previous example. Revisit the code in Listing 3, which produces the output in Figure 4. There are only two class files in this application.

AccountList.class
CheckingAccount.class

The CheckingAccount class actually contains the value of the account balance.

protected double accountBalance = 1000000.00;
Note: Remember the code in this example is used for demonstration purposes and that you would not hardcode a value in practice.

What would happen if someone who knew the design of the application decided to subversively increase the value of accountBalance? In this case, this person could in fact create another copy of the CheckingAccount.class and substitute the rogue class for the correct one.

To accomplish this in a very basic strategy, the rogue class simply can be substituted (copied) into the application directory. However, let me do this in a couple of steps to help illustrate the process.

As stated earlier, there are two classes in the application directory:

AccountList.class
CheckingAccount.class

If you delete the CheckingAccount.class from the directory, you obviously have only a single class left:

AccountList.class

You have seen what happens when this class is removed. When the AccountList.class is loaded and the Virtual Machine attempts to load the CheckingAccount.class, an application error is generated, as you saw in Figure 2.

Now, create the rogue CheckingAccount.class, as seen in Listing 5.

Listing 5: Rogue CheckingAccount class

class CheckingAccount {

   protected String accountNumber;
   protected double accountBalance = 2000000.00;

   public void getAccountBalance() {
      System.out.println("Account Balance = " + accountBalance);
   }

}

You may have noticed that the value for the accountBalance attribute has miraculously grown. For this example, I actually created a separate directory and created an entirely new application to develop and test the rogue CheckingAccount class; I will discuss other code substitution possibilities shortly.





Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel