Java technology has been an evolving success story since its inception, and it has revolutionized the computing industry by delivering to us the most capable platform for building and running a wide range of applications and services. With the release of the Java 2 Platform, Sun Microsystems categorized the Java technologies under three key major editions in order to simplify software development and deployment.
The Java Standard Edition (also referred to as J2SE or Java SE) provides the runtime environment and API technologies for developing and executing basic Java applications, and it serves as the secure foundation for running Java enterprise applications. The Java Enterprise Edition (also referred to as J2EE or Java EE Platform) is a set of standards and API technologies for developing and deploying multitier business applications. To support Java on microdevices and embedded systems, Java Micro Edition (also referred to as J2ME or Java MW) provides the runtime environment and API technologies for addressing the needs of consumer electronics and devices. With its widespread adoption, today Java technology is enabled and executed from smart cards to microdevices, handhelds to desktops, workstations to enterprise servers, mainframes to supercomputers, and so on.
Security has been an integral part of Java technology from day one. Security is also an evolving design goal of Java community process to build and run secure and robust Java-based network applications.
This two-part article explores the inherent security features of a Java platform environment that contribute to the end-to-end security of Java applications. Part 1 examines security within the Java Runtime Environment, Java security management tools and Java applet security. Part 2 looks at Java WebStart security and the Java Extensible Security Architecture and APIs.
Security within the Java Runtime Environment
The primary reason for Java's success today as a secure execution environment is its intrinsic security architectural foundation provided by the Java Virtual Machine (JVM) and the Java language.
The JVM provides the runtime execution environment for the Java programming language and has the primary responsibility for executing the compiled code by interpreting it in a machine-independent and cross-platform fashion. To prevent known security breaches and threats, the JVM facilitates a built-in Java security architecture model, configurable security policies, access-control mechanisms, and security extensions.
Within the Java runtime security architecture, all code -- regardless of whether it is run locally or downloaded remotely -- can be subjected to a security policy configured by a JVM user or administrator. All code is configured to use protection domains (equivalent to a sandbox) and a security policy that dictates whether the code can be run on a particular domain or not. During Java runtime execution, all local Java applications run unrestricted as trusted applications by default, but they can also be configured with access-control policies similar to what is defined in applets and remote applications.
Because of the built-in JVM safety features, Java programs can run safely and are more securely protected from known vulnerabilities. The key major features of the JVM security are as follows:
- Policy-driven restricted access control to JVM resources
- Rules-based class loading and verification of byte code
- System for signing code and assigning levels of capability
- Policy-driven access to Java applets downloaded by a Web browser
The Java language allows creation of general-purpose programs called Java classes that represent a Java program or an application. It delivers platform-neutral compiled code that can be executed using a JVM and is intended for use in distributed application environments, heterogeneous systems, and diverse network environments.
The Java language is also designed to provide security and integrity of the application and its underlying systems at all levels: from the Java language constructs to the JVM runtime and from the class library to the complete application.
The Java bytecode verifier is an integral part of the JVM that plays the important role of verifying the Java code prior to execution. It ensures that the code was produced consistent with specifications by a trustworthy compiler, confirms the format of the class file and proves that the series of Java byte codes are legal. With bytecode verification, the code is proved to be internally consistent following many of the rules and constraints defined by the Java language compiler.
The bytecode verifier may also detect inconsistencies related to certain cases of array bound-checking and object-casting through runtime enforcement. The Java classloader plays a distinct role in Java security. It is responsible for loading the Java classes into the JVM and then converting the raw data of a class into an internal data structure representing the class. To enforce security, the classloader coordinates with the Java security manager and the access controller of the JVM to determine the security policies associated with the Java application.
Java security management tools
The Java platform provides a set of tools that helps Java developers and security administrators administer security policies, create keys (for testing purposes only), manage keys and certificates, sign JAR files, verify signatures, and support other functions for integrating smartcards and cryptographic devices.
The Java keytool is a key and certificate management tool that allows users and administrators to administer their own private/public key pairs and associated certificates. This tool is intended for use with authentication services and verifying data integrity using digital signatures. The keytool is provided with the J2SE bundle as a command-line utility, which can be used to create JKS (Java keystore) and JCEKS (Java Cryptographic Extensions Keystore) keystores, generate and store keys and their associated X.509v1 certificates, generate Certificate Signing Requests (CSR), import and store trusted certificates, and perform maintenance on keystore entries.
The keytool utility uses the X.509 certificate standard, which is encoded using the Abstract Syntax Notation 1 (ASN.1) standard to describe data and the Definite Encoding Rules (DER) standard to identify how the information is to be stored and transmitted. The X.509 certificate takes the values of subject and issuer fields from the X.500 Distinguished Name (DN) standard.
The Java keystore is a protected database that stores keys and trusted certificate entries for those keys. A keystore stores all the certificate information related to verifying and proving an identity of a person or an application. It contains a private key and a chain of certificates that allows authentication with corresponding public keys. Each entry in the keystore is identified by a unique alias. All stored key entries can also be protected using a password. The Java keystore follows a cryptographic standard known as PKCS#12, which provides a way to securely store multiple keys and certificates in a password-protected file.
With the release of J2SE 5.0, the Java environment introduced the support for Cryptographic Token Interface Standard (referred to as PKCS#11) which defines native programming interfaces to cryptographic tokens, such as hardware cryptographic accelerators and smart cards. Integrating smart card-based keystores is commonly accomplished by configuring the smart card PKCS#11 module as a security provider.
Java applet security
A Java applet downloaded from a Web site runs in an end user's Java-enabled Web browser. From a security standpoint, Java applets downloaded from the Internet or from any remote sources are restricted from reading and writing files and making network connections on client host systems. They are also restricted from starting other programs, loading libraries or making native calls on the client host system. In general, applets downloaded from a network or remote sources are considered untrusted. The Java environment defines constraints for considering an applet to be trusted, based on the following factors:
- Applets installed on a local file system or executed on a local host
- Signed applets provide a way to verify that the applet is downloaded from a reliable source and can be trusted to run with the permissions granted in the policy file
In a Web browser, a Java plug-in provides a common framework and enables secure deployment of applets in the browser using the latest JRE. While downloading an applet, the Java plug-in enables the browser to install all the class files and then render the applet. A security manager (Java SecurityManager implementation) will be automatically installed during startup whenever an applet starts running in a Java-enabled Web browser. No downloaded applets are allowed to access resources in the client host unless they are explicitly granted permission using an entry in a Java security policy file.
The Java platform also provides the notion of signed applets. Signing an applet ensures that an applet's origin and its integrity are guaranteed by a certificate authority (CA) and that it can be trusted to run with the permissions granted in the policy file. The Java platform bundle provides a set of security tools, including the JARsigner utility, which allows the end users and administrators to sign applets and applications, and a policy tool to define local security policy. This is done by attaching a digital signature to the applet that indicates who developed the applet and by specifying a local security policy in a policy file mentioning the required access to local system resources.
The Java platform requires an executable applet class to be packaged into a JAR file before it is signed. The JAR file is signed using the private key of the applet creator. The signature is verified using its public key by the client user of the JAR file. The public key certificate is sent along with the JAR file to any client recipients who will use the applet. The client who receives the certificate uses it to authenticate the signature on the JAR file.
About the author: Ramesh Nagappan, CISSP, is a Java Technology Architect at Sun Microsystems who specializes in Java distributed computing architectures for mission-critical enterprise applications, Identity assurance and Access Management. Ramesh is the co-author of Core Security Patterns and also three other books on topics related to J2EE, EAI and Web Services. He frequently speaks at industry conferences related to Java, XML and Security. His current technology focus is on Web services security, identity assurance and strong authentication technologies using PKI, smart cards and biometrics.