HostedDB - Dedicated UNIX Servers

-->
Internet Security Professional Reference:Java Security
Previous Table of Contents Next


Java Opcodes and Operands

Imagine you are a computer executing a piece of code. For you, code consists of two types:

  Opcode—a specific and recognizable command
  Operand—the data needed to complete the opcode

All these opcodes and operands exist as a stream that you, the computer, execute sequentially. You might, for example, take a number from memory and place it on the stack, a kind of local pigeonhole for keeping data you will use immediately. You might then take another number, place it on the stack, and add the two numbers together, placing the result back into memory. In the JVM Instruction Set, it would look as it does in table 13.1. The specifics of the opcodes are not important unless you are planning to write your own compiler, but it is interesting to see how it all works.

Table 13.1
Adding Together Two Long Integers

Opcode Numerical Representation

lload address 22 xxxx
lload address 22 xxxx
ladd 97
lstore address 55 xxxx

Each command (lload, lstore) is an 8-bit number that tells the machine which instruction to execute. The address variable is a number telling the machine where to look in memory for the variable. Each address reference is a 32-bit number. Therefore, the preceding code occupies 16 bytes or 128 bits. Imagine that this little piece of code is a member method of a class. It would be embedded in all the other methods for the class when the compiler produced the code. How would the compiler find this piece of code when the program called the function? Because the compiler knows the exact length of all the code and has laid them out in memory, it can simply tell the machine to jump to the exact address at the start of a method needed for it to execute. To call a method, you could use the following command, which jumps (jsr) to the 16-bit address (xx):

jsr address      168 xx

Memory Layout in Java

If you know the memory layout of the program from the compiler and the memory layout of the system the program will be running on, what can stop you from placing the wrong address in your code for the placement of this method? Nothing.

The Java compiler does not allow this kind of memory addressing because it does not reduce references to numeric values that are based upon the memory layout of the code. Instead, the compiler leaves the symbolic reference to the method in the code, and when it is run, the interpreter, after creating the memory layout at runtime, looks up where it placed the specific method. The new way to call a class method is as follows:

invokevirtual index bytes     182 xx

This command references an index of method signatures that exist in the program. If it is the first time the reference is used, the interpreter determines where the method signature will be placed by checking the method table where it placed it in memory when loading the class at runtime. This lookup only occurs the first time a reference is encountered. Thereafter, the method signature will include the proper address, and the call will not need to use the lookup table. This method retains the protection afforded runtime memory layout, without the steep overhead of lookup table calls every time a method is invoked.

The reason for going to all this effort is twofold. First, as mentioned before, is the fragile superclass problem. If classes are laid out in memory at compile time and updating changes this memory layout, a programmer who inherits one of these classes and tries to call a method after the superclass has been updated as had been done before, its placement in the memory layout may have changed, and the program could be jumping anywhere in the code. By allowing the interpreter to set the memory scheme at runtime, the new subclass can call methods from the superclass symbolically and be assured of invoking the right code. The second reason is security. If a programmer cannot directly control the memory pointer for addressing of memory, he or she cannot intentionally send a program into the operating system to wreak havoc. This ensures that the code you receive is free of errant memory calls and can use imported classes, even if they are loaded from across the Internet from sources that might have updated them since to the original compile.

This feature does not protect against classes that are impersonating well-behaving programs. Most of the security issues dealt with in this chapter focus on two kinds of attacks: those that destroy data already on your system, and those that take data off your system. There is a third situation in which a program can impersonate an important piece of code, substituting errant data. For example, you can have a Java applet that updates your stock portfolio by obtaining current market data and performing an analysis on the data. In this case, imagine if the class that performs the analysis is dynamically loaded across the Net, and someone places an identical copy, except with the formulas that are used changed to provide incorrect data. If the impostor class was in every other way identical to the old class, it would be loaded up and run without complaint from the interpreter.

The applet that you run loads its classes from a particular URL—in essence a specific file on a specific machine. For the impostor to be loaded, it would have to replace the actual true class file on the remote machine.

The class file exists on a known machine. The machine would either be your own computer where the occurrence of a forced update of the class file would constitute a major security breach; or, the machine the file resides on would be the original location of the class file used by the calling applet, where you must decide how secure you think the site is.


Warning:  It is never wise to use critical software without extensive testing. Dynamically downloading class files that perform important calculations should never be carried out unless you are positively sure that the machine the class files reside on is secure and trustworthy. Otherwise, make sure that the class files reside on your own machine, and that you are sure they do exactly what they advertise.


Previous Table of Contents Next