In the first release of the Sun Java Platform, the Java Development Kit 1.0.x (JDK) introduced the notion of a sandbox-based security model. This primarily supports downloading and running Java applets securely and avoids any potential risks to the user's resources. With the JDK 1.0 sandbox security model, all Java applications (excluding Java applets) executed locally can have full access to the resources available to the JVM. Application code downloaded from remote resources, such as Java applets, will have access ONLY to the restricted resources provided within its sandbox. This sandbox security protects the Java applet user from potential risks because the downloaded applet cannot access or alter the user's resources beyond the sandbox.
The release of JDK 1.1.x introduced the notion of signed applets, which allowed downloading and executing applets as trusted code after verifying the applet signer's information. To facilitate signed applets, JDK 1.1.x added support for cryptographic algorithms that provide digital signature capabilities. With this support, a Java applet class could be signed with digital signatures in the Java archive format (JAR file). The JDK runtime will use the trusted public keys to verify the signers of the downloaded applet and then treat it as a trusted local application, granting access to its resources:
The release of Java 2 SE introduced a number of significant enhancements to JDK 1.1 and added such features as security extensions providing cryptographic services, digital certificate management, PKI management, and related tools. Some of the major changes in the Java 2 security architecture 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.
In the Java 2 SE 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 a particular domain (equivalent to a sandbox) and a security policy that dictates whether the code can be run on a particular domain or not.
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. This is done by configuring a ProtectionDomain, which allows grouping of classes and instances and then associating them with a set of permissions between the resources. Protection domains are generally categorized as two domains: "system domain" and "application domain". All protected external resources, such as the file systems, networks, and so forth, are accessible only via system domains. The resources that are part of the single execution thread are considered an application domain. So in reality, an application that requires access to an external resource may have an application domain as well as a system domain. While executing code, the Java runtime maintains a mapping from code to protection domain and then to its permissions.
Permissions determine whether access to a resource of the JVM is granted or denied. They give specified resources or classes running in that instance of the JVM the ability to permit or deny certain runtime operations. An applet or an application using a security manager can obtain access to a system resource only if it has permission. The Java Security API defines a hierarchy for Permission classes that can be used to configure a security policy. At the root, java.security.Permission is the abstract class, which represents access to a target resource; it can also include a set of operations to construct access on a particular resource. The Permission class contains several subclasses that represent access to different types of resources. The subclasses belong to their own packages that represent the APIs for the particular resource.
Some of the commonly used Permission classes are as follows:
For wildcard permissions: java.security.AllPermission
For named permissions: java.security.BasicPermission
For file system: java.io.FilePermission
For network: java.net.SocketPermission
For properties: java.lang.PropertyPermission
For runtime resources: java.lang.RuntimePermission
For authentication: java.security.NetPermission
For graphical resources: java.awt.AWTPermission
The Java 2 security policy defines the protection domains for all running Java code with access privileges and a set of permissions such as read and write access or making a connection to a host. The policy for a Java application is represented by a Policy object, which provides a way to declare permissions for granting access to its required resources. In general, all JVMs have security mechanisms built in that allow you to define permissions through a Java security policy file. A JVM makes use of a policy-driven access-control mechanism by dynamically mapping a static set of permissions defined in one or more policy configuration files. These entries are often referred to as grant entries. A user or an administrator externally configures the policy file for a J2SE runtime environment using an ASCII text file or a serialized binary file representing a Policy class.
Each Java application can have its own security manager that acts as its primary security guard against malicious attacks. The security manager enforces the required security policy of an application by performing runtime checks and authorizing access, thereby protecting resources from malicious operations. Under the hood, it uses the Java security policy file to decide which set of permissions are granted to the classes. However, when untrusted classes and third-party applications use the JVM, the Java security manager applies the security policy associated with the JVM to identify malicious operations. In many cases, where the threat model does not include malicious code being run in the JVM, the Java security manager is unnecessary.
In cases where the SecurityManager detects a security policy violation, the JVM will throw an AccessControlException or a SecurityException.
If you wish to have your applications use a SecurityManager and security policy, start up the JVM with the -Djava.security.manager option and you can also specify a security policy file using the policies in the -Djava.security.policy option as JVM arguments. If you enable the Java Security Manager in your application but do not specify a security policy file, then the Java Security Manager uses the default security policies defined in the java.policy file in the $JAVA_HOME/jre/lib/security directory.
The access controller mechanism performs a dynamic inspection and decides whether the access to a particular resource can be allowed or denied. From a programmer's standpoint, the Java access controller encapsulates the location, code source, and permissions to perform the particular operation. In a typical process, when a program executes an operation, it calls through the security manager, which delegates the request to the access controller, and then finally it gets access or denial to the resources.
The Java bytecode verifier is an integral part of the JVM that plays the important role of verifying the 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.
Keystore and Keytool
The Java 2 platform provides a password-protected database facility for storing trusted certificate entries and key entries. The keytool allows the users to create, manage, and administer their own public/private key pairs and associated certificates that are intended for use in authentication services and in representing digital signatures.
Java Applet Security
A Java applet downloaded from the Web runs in either a Java-enabled Web browser or a Java appletviewer, which is provided in the J2SE bundle. 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. An applet can be considered trusted, based on the following factors:
Applets installed on a local filesystem or executed on a localhost.
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 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 (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 2 platform introduced 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 J2SE bundle provides a set of security tools that allows the end users and administrators to sign applets and applications, and also 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 2 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. To sign the applet, we need to obtain a certificate that is capable of code signing. For all production purposes, you must always obtain a certificate from a CA such as VeriSign, Thawte, or some other CA.