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.
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].
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.
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.
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.
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].
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"; } } }
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.
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 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].
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.
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.
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]:
java.io, java.awt,
etc.)
user.name, user.home, user.dir,
java.home, java.class.path
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.
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).
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].
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.