Java and Security

by Kelly Ann Smith and Omar Akhtar

www.cis.upenn.edu/~kellyann/papers/javapaper.html


Introduction

Java is a language that is changing the face of the Web. For Java code to be used safely in any machine, security precautions need to be implemented. Although there are many levels of security in Java, flaws are still being found and fixed. It remains to be seen if Java will become a completely safe language.

Java Background

"Wow! How'd you get space invaders on your page?" The answer to this question, for lack of a better term, is Java. Java is a programming language developed in 1995 by Sun Microsystems, a computer firm that produces many of the servers attached to the World Wide Web. Java is an object oriented, dynamic, distributed, portable, and secure language. The advent of Java has completely changed the face of the Web. At the very least, it can change a Web page from a static, two dimensional format composed of text and images to an interactive one. Java may also be used to develop and distribute applications and programs over the Web in a new manner.

Many felt that as the number of users on the Web grew, HyperText Markup Language (HTML) was being stretched to its limits. As more and more Web pages were being created, users demanded more and more HTML tags. The idea of a program that could effectively communicate ideas to replace the ever-growing list of HTML tags was developed by Sun. Java application programs (applets) are downloaded from a server and are executed on the client. These applications may include animation or data input from a user. Examples may be seen at Gamelan, a repository of Java applets.

There are many cases where Java and its associated browser (HotJava) have been shown to be security risks. Although many of the security flaws have been caught and patched, some interpret this to mean that "flaws will continue to be found" and some in industry attribute this to the relative newness of the "execution of remotely-loaded code"[1].

Java is Designed to be Secure

A major concern of users of the Web, which has become all the more important with the arrival of Java, is security. Many reasons for this include protecting commerce, private communications, and proprietary systems. Quoting from Lincoln Stein, there are four basic types of overlapping risk on the Web [2]:

1. Private or confidential documents stored in the Web site's document tree
   falling into the hands of unauthorized individuals.
2. Private or confidential information sent by the remote user to the server
   (such as credit card information) being intercepted.
3. Information about the Web server's host machine leaking through, giving
   outsiders access to data that can potentially allow them to break into the host.
4. Bugs that allow outsiders to execute commands on the server's host machine,
   allowing them to modify and/or damage the system.  This includes "denial of
   service" attacks, in which the attackers pummel the machine with so many
   requests that it is rendered effectively useless.
The risk posed by the means in which Java applets are transferred across the Web fall into the fourth category. It is possible that an applet could cause a security breach on the client's machine through access gained through the browser. (Click here to download some hostile applets).

Security exists in many forms on the Web. One form is encryption; file transfers are encrypted and decrypted using public and private keys[3]. Whereas encryption allows the communication to be viewed by everyone, other methods of security, such as firewalls, are designed to allow only a certain number of users access to portions of the network. Java has security at many levels of its runtime environment. Security procedures include a restricted language, a code verifier, a class loader that allows only certain files to be loaded, and restrictions on what actions may be performed by an applet.

Applications of Java

Many in the computer industry see embedded software, development tools, and Internet programming software as a necessity for future growth of the Web. Java fulfills this in many ways. The security features integrated into Java are required for placing Internet-critical devices, such as network managers, on the Web (especially if they need to be remotely controlled). Also, Java applets that are downloaded allow remote applications to be automatically reconfigured, reducing user intervention.

Within the computer industry, the Java programming language is being hailed. For instance, IBM, Silicon Graphics, Netscape, and Microsoft have announced agreements with Sun Microsystems to integrate Java into their own products. In fact, Sun itself is developing computer chips (Java Chips) to run JavaOS, an operating system based on the Java programming language. Smaller companies have also been caught up in Java fever. Marimba and Lotus are currently developing Java applications. Some firms are using Java to help investors in securities markets, while others are developing intelligent agents to comb through the millions of bits of information on the Web for pertinent data. Many of these firms exist solely to develop customer-specific solutions with Java.


Java Security Features

There are four levels of security designed into Java. The language and compiler are the first level; the programming language was designed to have no memory hazards. The compiler transforms a Java program into byte codes which may be sent over the Internet. The second level of security is the byte code verifier, which is run from the client machine and checks that the byte codes are valid and pose no security risks. The third level of security is the class loader, which prevents any class from overriding a more secure class of the same name. The fourth level of security, found in the HotJava browser and Java Developer's Kit (JDK), prevents applets from performing potentially dangerous actions. In the future, additional security levels may be implemented, such as applet certification.

The Java Programming Language and Compiler

Java is an object-oriented programming language often compared to C++. Java was based on C++, keeping those features that are absolutely necessary, and deleting many of its features that cause core dumps, memory leakage and insecurities. This also makes Java a relatively simple and small language. In fact, Java was designed to be able to run on small computers [4].

Java is Organized into Classes

As with any object-oriented language, Java code is organized into classes. A class is a group of methods (variables, functions, etc.) defined by one name. Each method is assigned a level of protection (public, private, protected, or default), which determines if other classes may see and/or use these methods. All Java code must be in a class, even constant declarations (e.g. this_year = 1996 in the example below) and the main() function; there are no global variables. In C++, this requirement does not exist; any class member may be defined or used outside of a class (e.g. Person::get_ss() is defined outside of any class, and main() is not in a class).

Each class inherits from exactly one other class (multiple inheritance is possible only in C++). A form of multiple inheritance exists in Java, without many of the problems of true inheritance, using interfaces. In C++, an inherited class (subclass) has access to all methods of its superclasses. No class in Java, not even a subclass, has access to methods declared 'private'. This is an important security feature.

Programming in Java is similar to programming in C++ using classes. A simple program written in both Java and C++ is included here to demonstrate some of the differences in the languages [5].

----------------- C++ -----------------    ----------------- Java -----------------

#include <iostream.h>
const this_year = 1996;                    class Year {static int this_year = 1996;}

class Person{                              class Person{
  private:                                   private int ss_num;
    int ss_num;                              public String name;
  public:                                    public int birth_year;
    char name[55];
    int birth_year;                          public int get_ss(){
    int get_ss();                              return(ss_num);}

    Person (int s, char * n, int b){         public Person (int s, String n, int b){
      ss_num = s;                              ss_num = s;
      strcpy(name, n);                         name = n;
      birth_year = b;}                         birth_year = b;}
                                                                     
    int age(){                               public int age(){
      return(this_year - birth_year);}         return(Year.this_year - birth_year);}
};                                         }
                         
int Person::get_ss(){                      public class main{
  return ss_num;};                           public static void main(String argv[]){
                                               Person p = new Person(987654321,
int main(){                                                     "Adam Doe", 1955);
  Person p(987654321, "Adam Doe", 1955);       System.out.println("Person name:  " 
  cout << "Person name:  " << p.name             + p.name + "  SSN: " + p.get_ss());   
    << "  SSN: " << p.get_ss() << "\n";      }
}                                          }

Memory Access

Java was designed to avoid memory problems. If one occurs, an exception is thrown and dealt with. A Java program will never cause a segmentation fault or core dump. Java has a garbage collector so that the programmer is not required to (and cannot) deallocate memory; this eliminates memory leaks in C++ programs that result from not knowing when it is safe to deallocate memory.

There are no pointers in Java (at least none that the programmer has access to). Two major security flaws in most programming languages are based on using pointers: no object is protected from outside modification, duplication, or spoofing [6]; and memory may be altered directly. By eliminating pointers, these gaps in security are also eliminated.

Array bounds are checked. If a program tried to access the 4th element of a 3-element array in C++, this would be a valid command (although the result might be garbage). In Java, memory past the end of the array may not be accessed; the length of an array is defined and is an upper bound on the index. This is another security measure which prevents memory from being illegally accessed or modified.

Other Characteristics of the Java Language

Methods have flexibility in Java. A method may be defined in one class and redefined in another class using late binding. Here, the method to be used depends on the code that is executed. Abstract classes are also possible in Java. A method (and its class) may be defined as abstract (undefined); when it is determined how these methods should be defined, they are overwritten with the proper functions.

Java does not require header files at the beginning of the program as C++ does, with its numerous #include< > statements. The standard library includes many predefined methods, including threads, standard math and I/O functions, data types (Int, String, Hash Table), sockets, exception handling, a boolean class, and a GUI system called AWT [7, 8]. Java is extensible; it is possible to interface Java programs to existing software libraries written in other languages, such as C and C++.

Other C++ features that did not carry over into Java include Goto statements, structures, typedefs, defines, unions, multidimensional arrays and templates [4]. Also, although any method may be cast as type Object (the root class), implicit type conversion is not possible (Java has strong typing).

The Compiler

The source code is public, so flaws are likely to be found quickly. A statement from Sun reads: "The complete source code for both the Java interpreter and the Java compiler are available for inspection. We do not expect users to take our word for it that Java language is secure." [9]

The compiler is responsible for enforcing the language's security rules, including those mentioned above. The code is compiled into a .class file which contains byte codes, which may then be sent over the Internet. This is generic machine code; it is not specific to a particular machine, so that Java may be executed on many different machines and platforms. The goal is for Java to run correctly on every machine. Since there are differences in such basic things as how to represent an integer from machine to machine, the language is not completely portable yet [7].

Bytecode Verification

After a Java program is compiled into byte code, it is verified. The verification is done by the client machine (the machine running the Java program). Although someone could rewrite the compiler to get around the language specifications to produce malicious code, the code would not be executed, since the verification is done after the compilation and it is the client's machine that does the verification.

The client machine runs the Java byte code using a virtual (simulated) Java machine. The virtual machine is able to verify that the downloaded code contains no illegal memory references, viruses, or other errors. A verified program will not break any of the language or other constraints and may be safely executed. Many tests are done, at every level of complexity, from simple format checks to running a theorem prover [6]. Extra type information is included in the byte codes so that the verifier can check that objects and data aren't illegally manipulated. When the tests are finished, the code is guaranteed not to do any of the following:

The verified bytes may then be executed by the interpreter. Each verified byte causes the interpreter to execute instructions. The code does not execute; instead, it causes certain actions to be performed by the interpreter, from a limited set of safe instructions that the interpreter has.

The verifier is the gatekeeper that lets byte codes perform actions only if they are safe. The verifier must be correct for safety to be ensured. Only Sun and Netscape are currently producing Java runtime environments; it won't be long before others join in. Sun will implement validation suites for runtimes, compilers, etc. to be sure that they're safe; in the meantime, this is another potential security hazard.

Sun is working on a just-in-time compiler to convert verified byte code into native machine code as it loads [7]. The compiler would generate binary code which the client machine which would run directly, replacing the interpreter. This would increase the speed at which a Java program is ready to run.

The Class Loader

There are three possible places from which a class may be loaded. In order of least to most protected, they are: the Internet, the firewall-guarded network on which your computer is located, and your computer. (Actually, you may implement even more realms than this, but these are standard.) You may implement any one of the following four security systems [10]:

This protection is implemented in the java.lang.ClassLoader class. The class loader never allows a class from a less-protected realm to replace a class from a more-protected realm. The local classes are defined in a separate namespace from the loaded classes, so the loaded classes may never supercede the local classes. In fact, classes in one realm may not use or even see the methods of classes in other realms unless they have been explicitly defined as public. Applets are also protected from one another. They cannot access another applet's methods without cooperation.

Application-Specific Security for Applets

The final level of security is addressed in the HotJava browser and the JDK. These restrictions are the responsibility of the java.lang.SecurityManager class. This prevents applets from doing destructive things, such as the following [11, 12]:

Applet Certification

In the future, applets may be certified with a digital signature and security information. This security information would most likely be obtained using public key encryption technology, and would both authenticate an applet and verify that it was not modified in transmission [11]. This would allow applets to be loaded over an untrusted network as long as the source of the applet was trusted.


Java Security Flaws

There are two types of security problems: those that involve access or modification of data on the client's machine (security breaches), and those that are merely nuisances.

A nuisance attack does not involve a breach of security, although it may be very frustrating: your computer may crash and you would be forced to restart it. A denial of service attack is an example of a nuisance attack. This occurs when an applet tries to consume all the resources on your computer, such as opening a million windows. In the Sun's Response to the HotJava Security Flaws, it is stated that "The JDK applet API doesn't claim to prevent denial of service attacks." [12]

A security breach could involve your private files being read, modified, or deleted, or a virus may infect your machine. For example, a nasty applet could create a familiar window and spoof the user into typing private password information (this particular problem has been fixed).

A brief listing of all known security problems follows [13, 14], along with (the software and version affected) and the fixed version of the software. The software is abbreviated: NN (Netscape Navigator), MIE (Microsoft Internet Explorer), JDK (Java Developer's Kit).

November 1995 - (HotJava Web browser 1.0a3) NN 2.0b, JDK b
Many different bugs were found by researchers at Princeton University [1]. Sun claimed the bugs were already fixed, although the code hadn't been released yet [12].

February 1996 (NN 2.0) NN 2.01, JDK 1.0.1
The Princeton team found that since Java trusted remote DNS servers, applets could make network connections to machines other than from which they were loaded.

March 1996 (NN 2.0) NN 2.01, JDK 1.0.1
David Hopwood at Oxford University discovered a bug in the class loader that allows illegal byte code; specifically, a class referenced by an absolute path name may be loaded.

March 1996 (NN 2.01) NN 2.02, JDK 1.0.2
The Princeton team found a bug in the verifier that allowed an applet to execute any code.

April 1996 (NN 2.01) NN 2.02, JDK 1.0.2
An applet downloaded from a client inside a firewall may connect to a host behind the firewall.

May 1996 (NN 2.02, MIE 3.0b1) NN 3.0b4, MIE 3.0b2, JDK 1.0.2
The Princeton team found a way to create a class loader; a user may define and use classes otherwise barred from execution.

June 1996 (NN 2.02, NN 3.0b4) NN 3.0b6 - for PCs, NN 3.0b5 - for other machines, JDK 1.1
David Hopwood discovered a way to create illegal type casts of objects.

August 1996 (NN 3.0b5, MIE 3.0b2) NN 3.0b6, MIE 3.0
The Princeton team discovered a serious bug, allowing a malicious applet to gain full read/write access to the victim's files.

August 1996 (MIE 3.0) patch for MIE 3.0
The Princeton team discovered a serious flaw that allows an attacker to be able to execute any DOS command on the victim's machine.

As of November 7, 1996, JavaSoft released the following statement: "There are at present no known security-related bugs for which fixes have not been propagated to all Java licensees." [13].


Conclusion

Java was designed to be a safe language. The numerous safety features in all levels of the runtime environment demonstrate this. The language was designed to make it impossible for a programmer to directly access memory. The compiler checks that the code meets the language constraints and produces byte codes. The client verifies that the byte codes are valid and safe before it executes the program. The other important safety features are the class loader, controlling which classes may be loaded into an environment, and the security manager, which disallows applets from performing malicious actions.

With every security system comes ways to get around it. There have been security problems, and it is likely that there are more to come. Although each problem has quickly been fixed, and there have been no reported, confirmed cases of security breaches involving Java, a user is not guaranteed safety. In the future, it may be possible to certify an applet's security. Until then, the safest policy is to use an up-to-date Web browser and to load applets only from trusted sites, and to disable Java altogether when visiting an untrusted site.


References

1.
Dean, Drew; Felten, Edward W.; Wallach, Dan S. "Java Security: From HotJava to Netscape and Beyond". 1996 IEEE Symposium on Security and Privacy. Oakland, CA. May 1996.
2.
Stein, Lincoln. "The World Wide Web Security FAQ".
3.
Ross, Keith W. "Fundamentals of Cryptography".
4.
Van Hoff, Arthur; Shail, Sami; Starbuck, Orca. "What is This Thing Called Java?". Datamation. March 1, 1996. 42(5):45-46.
5.
University of Pennsylvania Course CSE 120/130, Spring 1996 Lecture Notes.
6.
Lemay, Laura; Perkins, Charles. "Yes, Java's Secure. Here's Why." Datamation, March 1, 1996. 42(5):47-49.
7.
Singleton, Andrew. "A Hot Cup of Java". Byte, April 1996. 21(4):129-132.
8.
Mateosian, Richard. "Java". IEEE Micro, June 1996. 16(3):3-5.
9.
Yellin, Frank. "Low Level Security in Java".
10.
Wang, Wei; Yan, Yi; Zang, Lu, " Security----How is it implemented in the Java Language".
11.
Flanagan, David, "Java in a Nutshell". O'Reilly & Associates, Inc. Sebastopol, CA 1996.
12.
Mueller, Marianne. "Sun's Response to the HotJava Security Flaws".
13.
JavaSoft, "Frequently Asked Questions - Applet Security."
14.
Felten, Edward. "Safe Internet Programming: News".