|
February 2001 Issue |
|
Headlines:
Java
Technical Insight of the Month
Java
2 Platform Security Exposed
Visit
The Java News
Brief Archive for past issues of the JNB.
OCI
Educational Services
Java Technical Insight of the Month
Java 2 Platform
Security Exposed
by Dean Wette, Senior Software
Engineer, Object Computing, Inc. (OCI)
Introduction
to Java Security
Security is perhaps
one the most visible, yet least understood, aspects of Java. Starting with
the first version, every logical and physical component of the Java platform has
been designed and implemented with security a chief concern.
This includes the Java language itself, which prevents dangerous operations such
as array overruns and direct memory access via pointers; the compiler, which
checks that source code is specification conformant; and the runtime
environment, which insures that compiled code is well-behaved and safe to
execute according to rules of the Java platform.
Java 2 includes many significant changes and improvements over its previous
versions. The security model represents a significant evolution in Java
both in terms of architecture and API support in the core libraries and optional
packages.
Surprisingly, the new security model in Java 2 is also one of the least
discussed enhancements. Indeed, while the press has been very prolific
with new literature on the Java 2 platform, only a handful of new books cover
Java security in enough detail to be meaningful, and books devoted to Java 2
security aren't anywhere as numerous as those on other Java topics.
The
Java 2 Security Model
Generally speaking, Java security is class-based, where trust is given to executable code (bytecodes found in class files), according to:
A mapping of code to
signers is represented by the java.security.CodeSource
class, which encapsulates a URL pointing to the code's location and a list of
zero or more digital certificates used to verify signed code originating from
that location.
In versions prior to Java 2, trust is all-or-nothing; that is, either code has complete trust to execute freely and perform any operation supported by the Java platform, or the code is untrusted and runs in a 'sandbox' where it is restricted from performing operations that access sensitive local and network resources. In all versions of Java, Applets and other code loaded from the network run in this sandbox and are prevented from accessing file systems, devices, sockets, and information about the environment and user. In effect, they can only utilize local memory, the CPU, and the web server from which they are loaded. On the other hand, Java applications and other code loaded from the local file system are trusted unconditionally to perform sensitive operations. Java 1.1 features packaging of class files into Java Archive (jar) files that can be digitally signed, allowing Applets to run trusted with full resource access. However, this course grained approach to security is too limiting or too free for many situations.
Java 2 alleviates
the 'all-or-nothing' scenario with a new security model and supporting APIs
that provide a fine-grained, policy-based access control mechanism with the
following characteristics:
In effect, trust and
access control can be fine-tuned for all Java programs using policy files
configured independently of security implementation and enforcement. By
default Java Applets and applications run as they always have in terms of trust
and security, but now options exist for specifying security policies that
selectively relax Applet sandbox restrictions or subject local code to more
restrictive access control. Policy
Configuration Sun's standard
distribution of the Java 2 platform utilizes text files for policy
configuration, with a system-wide policy file deployed automatically with the
Java Runtime Environment (JRE), and optional user policy files located in user
home directories. Other policy configurations are possible with the use of
additional policy files, or with alternate methods of policy statement
persistence (e.g. database or network-based policy storage). Policy configuration
consists of an optional 'keystore' entry that specifies the location and
type of digital certificates used to sign code, plus zero or more 'grant'
entries specifying permissions given to code sources (i.e. code URL plus digital
signers). A grant entry might look something like this:
This entry grants
the code in util.jar, found at the joe.org web site, permission to
read and write files in dwette's home directory, if and only if the
code is also signed by the signer identified by the alias honestjoe.
Omitting the signedBy clause grants permission to unsigned code as well. When the Java
runtime loads the code specified in the grant entry, it associates loaded
classes with protection domains that map the code source to granted
permissions. If code is also loaded from some other location, it becomes
associated with a different protection domain, with its own permission mappings,
making it impossible to spoof the policy or fool enforcement of access
control. The runtime representation of protection domain mapping utilizes CodeSource objects associated with collections of immutable objects derived from
the java.security.Permission class (such as the FilePermission
given in the example). These permission objects are used at runtime for
the actual access control checks. The core Java 2 APIs include eleven Permission
classes representing access permissions to resources such as file systems,
network sockets, environment & user information. These built-in
permissions suffice for many applications, but facilities exist for creating new
Permission
classes unique to application requirements, which are in turn supported
automatically in policy grant statements. Permission checks
are only performed if a security manager is installed. Applets always run
with a security manager, installed automatically by the host browser.
Applications, however, only execute with a security manager if one is specified
explicitly, either in the application code, or through an option provided to the
java command. The security manager
class (java.security.SecurityManager)
represents the runtime focal point of access control in Java 2, and is called by
operations whenever a decision needs to be made for granting or denying resource
access. It does this by determining the type of permission needed and
delegating the actual check to the access controller (java.security.AccessController),
which determines if permissions granted to the code requesting access imply the Permission
needed to grant the specific request for access. If the access controller
denies access it throws a runtime security exception; otherwise, it returns
silently. If no security manager is present, access checks are not carried out
at all. The access
controller makes security determinations using the 'principle of least
privilege' which means a request for access to a protected resource is granted
if and only if every protection domain in the current execution context (call
stack) has access permissions to the requested resource. In other words,
every method call in the current execution stack - starting with the current
caller and moving through all ancestral callers - is examined to make sure the
calling code has been granted permissions necessary for requested access.
If at any point code is encountered that lacks the permission, a security
exception is raised without further ado. This implies that untrusted code
cannot use trusted code to gain permission for access it doesn't have
otherwise. However, it also means that trusted code cannot perform secured
operations on behalf of other code, which can be too restrictive under certain
circumstances. In fact, the core Java APIs need to perform various
operations regardless of calling context. To solve this
problem, a block of code may be marked 'privileged,' in the sense that it
assumes responsibility for exercising its own permissions and informs the access
controller to ignore previous callers. However, privileged code cannot
gain access permissions as a result and the principle of least privilege still
applies, but only from the point of the caller requesting access to that of the
privileged block. Callers to the privileged block are ignored. A code
block is marked privileged by wrapping it in a java.security.PrivilegedAction
object that is passed to the AccessController's doPrivileged method. For security reasons the privileged
action objects passed to doPrivileged() are usually implemented with anonymous inner
classes. Privileged blocks
stand as one of the most interesting facets of the Java 2 security model.
Further details and examples can be found by consulting the standard Java
API documentation for java.security.AccessController. Class loaders, which locate and fetch class files for linking into the Java
runtime, form an important relationship with the Java security model.
Their responsibilities include establishing protection domains for loaded
classes, ensuring that newly loaded classes don't preempt more trusted classes
(such as the core API classes in the java.* packages), and ensuring that bytecodes found in class
files are safely verified before being allowed to run. The security
enhancements in Java 2 include significant improvements to the class loading
mechanism and supporting classes. Support for digital signature and cryptographic services comprises another
important component of security in Java 2.
The Java Cryptography Architecture (JCA) design features provider-based,
algorithm-independent cryptographic services that allow multiple interoperable
implementations and associated standards to be used without requiring
modification to existing APIs. Thus, as improved cryptographic services
become available, they can be plugged-in to existing applications easily. Some
of the current implementations are strong enough to warrant U.S. export controls
(these controls have been relaxed recently). For that reason the
export-restricted parts, along with some supporting APIs, are available
separately as an optional package, the Java Cryptography Extension (JCE). The JCA also includes the java.security.SignedObject
and javax.crypto.SealedObject classes,
which provide facilities to ensure validity and confidentiality of serializable
Java objects. This feature allows protecting runtime information outside
of the Java environment or during transport between Java Virtual Machines. Moving Forward This technology brief barely scratches the surface of Java 2 Security.
The core APIs provide much more than represented here, and security support for
enterprise Java systems is mentioned here only briefly. While the Java
security model is simple to use - once its fundamental concepts are understood
- it is also sophisticated and powerful.
However, Sun is not resting on this accomplishment. In the future more
improvements and enhancements can be expected, not only in the core APIs, but
with enterprise Java technologies as well. Already on the horizon are new
security support for mobile devices, improved security mechanisms in the Java
RMI (Remote Method Invocation) APIs, and interoperability with OS based security
services. Foreseeable future enhancements and improvements might include
dynamic permission revocation, improved and more flexible access control
algorithms with fine-grained tuning of privileged block permissions, XML-based
policy configuration, and XML encryption & digital signatures. Select Java 2 Security Bibliography Note: Li Gong is the Chief Java Security Architect at Sun Microsystems, Inc.
OCI Educational Services
OCI has one of the most
comprehensive OO training curricula in the country. Clients contract group
training that is either taught at the client site or at the OCI Education Center
in St. Louis, MO. We encourage you to check our Object-Oriented
Technology Curriculum show below: (click
on course titles for online descriptions) For more information or to register, email training.
Object Computing, Inc.
is a Sun Authorized Java Center in St. Louis and a Member of the Object
Management Group, OMG. OCI specializes in distributed computing using
object-oriented and web-enabled technologies and provides Consulting,
Education,
and Product
Development services to clients nation-wide.
For more information contact us at 314-579-0066 (St. Louis), 480-752-0042
(Tempe) or email info@ociweb.com. Click here for OCI CAREER OPPORTUNITIES.
grant signedBy "honestjoe", codeBase "http://joe.org/util.jar" {
permission java.io.FilePermission "/usr/home/dwette/*", "read,write";
};
The Security Manager and Access Controller
The Access Controller and Privileged Blocks
Some
Other Features of Java 2 Security (In A Nutshell)
The Java 2 platform
also includes several supporting security tools:
Sun offers additional optional packages for implementing security in the
enterprise with the Java Secure Sockets Extension (JSSE), for building secure
network applications, and the Java Authentication and Authorization Services
(JAAS), for adding user-centric access control to applications.
§ Li Gong. Inside Java 2 Platform Security. Addison-Wesley, 1999.
§ Li Gong. Java
Security Architecture 1.0, Sun Microsystems, 1998.
§ Jamie Jaworski and Paul J Perrone. Java Security Handbook. SAMS, 2000
§ Jonathan Knudsen. Java Cryptography. O'Reilly, 1998.
§ Scott Oaks. Java Security. O'Reilly, 1998
§ Marco Pistoia, et al. Java 2 Network Security. Prentice Hall, 1999.
Not reflected in the OO curriculum diagram shown below are three new Java classes recently developed. These classes are:
The Java News Brief is a monthly newsletter. The
purpose and intent of this publication is to advance Java, provide technical
value, and to announce available OCI Java services. If you would prefer to
not receive this newsletter or would like to subscribe please click
here.
Copyright © 2001. Object Computing, Inc. All rights reserved.
Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
Object Computing, Inc. is independent of Sun Microsystems, Inc.