Much of the base security model found in Java's JDK 1.0.2 (and explained in Chapter 2) is not present in Card Java. For example, Card Java has no Security Manager class. This means the whole concept of security for Card Java applets is significantly different from the case of applets running on a standard browser-based VM. Fortunately, some of Card Java's "missing parts" may actually enhance the security situation; unfortunately, some of the changes introduce new security risks.
One of the most difficult problems in Java security is figuring out how to preserve type safety, while at the same time allowing dynamic class loading (see Chapter 2). If you can confuse the VM about the types of objects it is manipulating, you can break the security model. In its current form, Card Java takes care of this problem by removing dynamic class loading, making type safety easier to enforce. Class loading has always been problematic in Java and has introduced a number of serious security holes. Because it has no dynamic class loading, Card Java is less risky than regular Java from this perspective.
Another constraint imposed by Card Java, lack of threading, makes security analysis of applet code much easier than it is normally. Threading is difficult to implement properly and to use properly, plus threading takes a fair amount of overhead in the VM and significantly impacts the VM footprint. Although there can be multiple applets resident on the same smart card, Card Java systems allow only one applet to be selected at a time. (The multiple-resident-applications concept introduces risks of its own, which we address later.)
Lack of threads and the absence of dynamic class loading impact security in a positive way, but the opposite effect can be seen with other Card Java features. In other words, the removal of some features of Java (clearly intended to make possible the migration to Card Java) may introduce new security problems. Risks that are introduced involve:
Garbage collection is a good example of a feature whose absence has a security impact. Without a system for freeing allocated memory, the problem of denial-of-service attacks is exacerbated. The Card Java 2.0 specification does not require implementation of garbage collection on a card (in fact, implementing garbage collection on a card would be no small feat). As a result, even subtle programming errors can wreak havoc on a smart card. Memory leaks are a classic problem in languages such as C++ that do not support automatic garbage collection [Hastings and Joyce, 1992]. (Note that the term memory leak refers to memory becoming full when objects are inefficiently created and destroyed.) Since Card Java does not support garbage collection, logic errors in applet code may over time exhaust free memory, rendering the card useless. This problem is especially acute on cards with limited memory resources. Another closely related issue is the "dangling reference" problem, in which a program frees memory even though it still has a pointer to that memory. The problem is that the freed memory may be recycled for another purpose, and then the old "dangling" pointer may be used, resulting in memory corruption. Unfortunately, garbage collection is expensive in terms of both time and computational resources. Nevertheless, the risk of memory leaks is real. The requirement to ensure that these kinds of errors do not occur raises the need for extensive testing and analysis of Card Java applet code.
Exception propagation is an interesting issue for Card Java as well, since uncaught exceptions could lead to a card being muted (disabled for normal use). The potentially fatal effect of unhandled exceptions implies another significant exposure to unintended denial of service, once again resulting from subtle programming errors. As with memory exhaustion, the requirement to ensure that these kinds of errors do not occur raises the requirements for extensive testing and analysis of the Card Java applet code.
Since Card Java allows multiple applications to be resident on the same smart card, there is a risk of interapplication attacks. This risk is especially relevant in situations where applets may be provided by competing vendors. Card Java defines applet firewalls meant to protect applets from one another, although it is not exactly clear what technology underlies this terminology. It appears that the main protections between applets are related to memory management; in particular, applets are not allowed to access memory arbitrarily on the card. As a default, they can only get access to objects that they own (which are mapped into card memory during applet installation). It is clear that the memory protection mechanisms must be perfectly implemented to allow safe use of multiple applets. Plans are in the works for smart card applications that cooperate with each other. Imagine, for example, a card that works both as a debit card and as a frequent flyer card. Such plans may introduce more security risk than they are worth.
One feature that is in high demand in systems with multiple applications is object sharing. Card Java 2.0 includes an object sharing approach that includes a loophole. The current approach is described as follows:
The JCRE keeps track of the currently selected applet as well as the currently active applet. The currently active applet value is referred to as the applet execution context. When a virtual method is invoked on an object, the applet execution context is changed to correspond to the applet that owns that object. When that method returns, the previous context is restored. Invocations of static methods have no effect on the applet execution context. The applet execution context and sharing status of an object together determine if access to an object is permissible [Sun Microsystems, 1997].To illustrate the implications of this approach, consider an example with three applets named A, B, and C as shown in Figure 8.3. Applet A shares an object it owns, x, with applet B. Applet B shares an object it owns, y, with applet C. A virtual method in the object owned by B, called y.bar, and shared with C invokes a virtual method in the object owned by A, called x.foo. Now if applet C is selected, it has permission to invoke virtual methods of the object owned by applet B, including the one that in turn invokes the virtual method in an object owned by applet A. In other words, C indirectly invokes x.foo.
In short, if virtual methods are used, granting an applet permission to access an object amounts to also granting that applet the ability to export indirect access to that object to any other applet. This has a clear weakening effect on any assurance about the protection of an object. For static methods, such access is prohibited, since static methods do not change the applet context. Restricting virtual methods in the same way that static methods are restricted may add some complexity to sharing schemes. The upshot of this change would be that an applet will be forced to share the object explicitly with all other applets that directly or indirectly need to be granted access permission.
By far the biggest risk presented in the design of Card Java is a potential ability for a vendor to add and use Native methods on the platform. Obviously, this will compromise portability (applets that use Native methods will not be automatically portable to other cards), and it may expose the card to dangerous code that exists outside the applet firewalls. In fact, if Native methods are available, the concept of firewalls deteriorates. Native code is not restricted by the JCRE mediation of access, and misuse is possible.
The very real security concern is that an attack applet will make use of Native code to carry out operations that would otherwise be stopped by the JCRE. When Native code executes, all bets are off for the Java Virtual Machine and its protection mechanisms. Native code in applets completely breaks the idea behind Java security. Attack applets are likely to make use of Native method calls.
The five new risks we have covered were introduced into Java with its transformation to Card Java. Although Card Java certainly presents an intriguing new set of risks in terms of security, it does nothing to address several important fundamental security concerns associated with smart cards, including the problem of physical attacks and the terminal problem (both discussed earlier in the chapter). It is important to keep in mind that the non-Java-related problems have a real impact on card security and that they are not solved by Card Java.
Copyright ©1999 Gary McGraw and Edward Felten.