![]() ![]() |
||||
|
||||
[Design Application] Java Security Guards Embedded Networks By Conquering Its Early Security Issues, This Language Has Emerged As A Highly Secure Environment For Embedded Applications. Prithvi Rao November/December 2003
From the beginning, the Java programming language was designed with security in mind. Yet developers remained suspicious about its secure nature. They were blinded by the novelty of a portable language that could transfer applications from system to system on an as-needed basis. During its initial shakedown period, Java did encounter some relatively minor security problems. At that point, many developers decidedwith little real examination of the issues involvedthat Java was insecure. It was deemed unsuitable for applications like electronic commerce. In the PC environment, Java has successfully overcome these early suspicions. This statement is especially true for Web applications. In this arena, developers recognize the language's usefulness. They also understand its built-in security features. In the embedded community, however, the story is quite different. Generally, developers of networked embedded systems are unaware that Java provides multiple security checks. Such measures make it extremely difficult for downloaded rogue software to attack a system. It's unfortunate that developers continue to hold this attitude. After all, networking is becoming pervasive in embedded systems ranging from set-top boxes to handheld multimedia devices. Meanwhile, the increasingly high performance that's offered by digital signal processors (DSPs) is steadily enabling new forms of communication to these systems. Multiprocessor architectures provide a solid hardware and software foundation for building mobile systems. Such systems can run a variety of multimedia programs, including Java applications. Texas Instruments' OMAP platform is an example of this type of architecture. It is based on a DSP and enhanced ARM microcontroller. Until embedded-systems developers understand and make use of the security that's inherent in Java, however, the full potential of these platforms won't be realized. This article defines Java's security mechanisms. To help developers implement their security policies, it also discusses how to employ those mechanisms in software development. The sample code that is shown will assist developers in evaluating Java protections and creating a mechanism for security implementation. Readers can immediately duplicate this code on their workstations, as it is designed to run as an applet within the web browser. Once they have this information in hand, developers will understand the security that's offered by Java. They'll also be better prepared to build secure Java Virtual Machines (JVMs) for their finished products. Java offers security at the application level. There, it complements other, more fundamental types of protection. For instance, platforms like OMAP provide security in hardware to prevent boot-code tampering. The Mobile Information Device Profile (MIDP) specificationwhich is built on top of the Connected Limited Device Configuration (CLDC)provides a secure run-time environment for Java in mobile information devices. These devices include cellular phones and PDAs. For protection in data transmission, all of the predefined Java applications or classes that are loaded must be properly signed. The signing is done using an X.509 Public Key Infrastructure (PKI) security standard. These protectionsespecially MIDPdemonstrate the great importance that embedded-systems developers attach to security. MIDP is the result of a collaborative effort of over 50 companies. Among those companies are mobile-device manufacturers, wireless carriers, and mobile software vendors. Their collaboration resulted in a specification that guarantees end-to-end security for networked applications. At the same time, it leverages capabilities like Secure Socket Layer (SSL) and HTTP using SSL (HTTPS). The Java programming environment provides mechanisms that ensure security for the execution of Java programs. Security exists both outside and inside of the JVM, which is the target of the Java compiler. All byte code is interpreted inside the JVM as well. Outside of the JVM, language support assists in making Java a more secure programming environment. This security takes place on three fronts. First of all, there are no pointers in Java-only references. Arithmetic functions can be performed with pointers but not with references. As a result, it's not possible to scan memory. Secondly, changing the cast of an object invokes a check at either compile or run time. Access to methods and fields are checked at run time. If an application tries to access a method of a class that's declared private, a run-time exception (IllegalAccessException) is generated. A final security feature is that the Java compiler produces an architecture-neutral .class file. This file makes it almost impossible to discover how a program is laid out in memory. As a result, it's very difficult to take advantage of any information about memory maps to devise attacks. JAVA IN THE SANDBOX Inside the JVM, security concerns itself with the execution of byte codethe object code that's created by the compiler. The term "sandbox" refers to the JVM mechanisms that are used in creating a secure environment. In that environment, Java applications can run. Normally, sandbox security is illustrated as shown in Figure 1. The diagram indicates that the code that's loaded from remote sources cannot make direct use of the local resources within the target system. To be technically accurate, the Kilobyte Virtual Machine (KVM) is used in embedded systems. It is a smaller variant of the JVM. The KVM still supports the sandbox, which is the source of security in any JVM. The KVM received its name because its memory footprint is measured in kilobytes rather than the megabytes required by the Java Virtual Machine. The default sandbox is comprised of three interrelated parts: the verifier, the class loader, and the security manager. The verifier is the part of the JVM that performs checks on the incoming byte code. This process is transparent to the user. It's not under direct control by the user either. The security manager enforces the security policies for executable content. In other words, it controls the actions that a particular Java class can perform based on some policy. The class loader forges the connection between the JVM and the outside world. In the early days of Javaaround 1996people often referred to the Java security model as a "three-layer defense." Though such a label is still sometimes encountered in Java-security literature, it's misleading. It implies that if an application penetrates the first layer, two layers are left to set things straight. Actually, the parts are more like links in a chain. If any of the three parts breaks, the entire security system fails. The following sections discuss the verifier, class loader, and security manager in greater detail. They also make development recommendations based on the interests of greater system security. The work that's presented is taken in part from the research of Dr. Ravindra Rao, co-founder of KiwiLabs. Because the example code is applied to the running of an applet within a web browser, readers can duplicate this work on their workstations. It also can be used in a more general framework of embedded systems in which applets cannot be run. BYTE-CODE VERIFIER The verifier is built into the virtual machine. It cannot be accessed by Java programmers or users. In most implementations, the verifier automatically examines the Java code when it arrives at the VM and is formed into a class by the class loader (FIG. 2). The verifier checks byte code at a number of different levels. The simplest test makes sure that the format of a code fragment is correct. On a less basic level, a built-in theorem prover is applied to each code fragment. This theorem prover helps to make sure that byte code doesn't forge pointers, violate access restrictions, or access objects using incorrect type information. If the verifier discovers a problem with a class file, it throws an exception. Loading then ceases and the class file never executes. The verification processtogether with the security features that are built into the language and checked at run timehelps to establish a base set of security guarantees. The verifier also ensures that the class files that refer to each other preserve binary compatibility. Because of Java's ability to dynamically load classes, it's possible that a class file being dynamically linked may not be compatible with a referring class. Binary incompatibility problems could occur when a library of Java classes is updated. Problems also may arise if a class from a large Java program isn't recompiled during development. The rules of compatibility govern the ability to change the use of classes and methods without breaking binary compatibility. For instance, it's acceptable to add a method to a class that's used by other classes. But it's not acceptable to delete methods from a class that's used by other classes. The verifier enforces the compatibility rules. Binary incompatibility also has security implications. Picture a scenario in which a malicious programmer can get the virtual machine to accept a set of mutually incompatible classes. The hostile code will probably be able to break out of the sandbox. Before a Java program can run, it must be loaded into the VM. The loading process begins by reading a file that contains the byte code (i.e., has a .class name). The file is then stored in a buffer. The verifier acts on the information in this buffer. It takes advantage of the fact that Java byte code conforms to a well-known format (8-bit bytes). Plus, each Java .class file contains information about one Java class. A .class file is a stream of 8-b bytes along with larger quantities that are represented in terms of 8-b bytes. This information is stored in big-endian format. In other words, the most significant bits are leftmost. The first 4 bytes act as an identifier. The other information that's contained refers to the major and minor number of the compiler that produced the .class file. The VM supports classes that originated from a compiler with a fixed major number as well as a minor number that has a predefined upper limit. The constant pool is an array of structures that represent the names of classes, interfaces, fields, and methods. Debugging information also is available. |
|||||||||||||||
|
|
|||||||||||||||
|
[Reader Comments] Java Security Guards Embedded Networks |
|
|
|
Electronic Design Europe Electronic Design China EEPN Microwaves & RF Schematics ![]() Electronic Design Military Electronics Featured Vendors EE Events Free Design Resources |
|
|
Planet EE Network Home |
Contact Us |
Editorial Calendar |
Media Kit |
Headlines |
Site Feedback & Bugs Copyright © 2010 Penton Media, Inc. Legal | Privacy Statement Terms of Use |