Secure Computing with Java: Now and the
Future
Print-friendly Version
Executive Summary
Overview
The Internet is changing the landscape of modern computing. In addition to opening new
avenues of access for users, it is fundamentally altering the architecture of today's computing
systems. Software developers are no longer constrained by the monolithic, mainframe approach
to computing. Rather, they are free to take advantage of a new development paradigm:
distributed processing. This new architecture allows designers to segment applications into
components-each of which may exist and execute on different processors and in separate
locations.
The tremendous new potential offered by distributed computing also carries with it the necessity
to exercise certain security safeguards. As distributed, mobile components move among
machines, the opportunity for security breaches increases dramatically. Examples are not
difficult to find:
Viruses can invade and destroy information
on a user's disk, sometimes permanently
Unauthorized agents can steal credit card
numbers
Confidential business files can be copied or
distributed in a way that directly affects
revenues
Computer users and administrators should not be lulled into thinking that security is someone
else's problem. Anyone who uses a browser can unwittingly download a "Trojan Horse" directly
onto their system. The resultant problems can range in severity from mildly mischievous to
highly malicious.
Leading the charge into this new era of computing is Java-a development platform born of the
net. Java technology is well known for simplifying many operations for both users and
developers. Through its unique design and streamlined implementation, Java has made
distributed computing, especially on the Internet, a practical reality. As we shall examine here,
Java also provides a full complement of powerful and highly flexible security features that make
it uniquely capable in the area of the Internet and distributed computing systems.
What is Security?
Security is the practice by which individuals and organizations protect their physical and
intellectual property from all forms of attack and pillage. Although security concerns are not
new, there is revived interest in the entire area of security in computing systems. Why? Because
today's information systems have become the repositories for both personal and corporate assets.
Computers of all sizes and network configurations are providing new levels of access-and
consequently new opportunities for unauthorized interaction and possible abuse.
With respect to computing systems, there are a number of important attributes that are associated
with good security practices. These include authentication, authorization, confidentiality,
containment, auditing, and non-repudiation. Due to its inherent security architecture, the Java
development platform is particularly well-suited to implement all of these features.
Java Security
In order to combat potential security threats, users need programs they can rely on. Moreover,
developers look to a development platform that has been designed with security capabilities built
in-not added as an afterthought. This is where the Java platform comes in. Java is designed from
the ground up for network-based computing. Security measures are an integral part of Java's
design. Other distributed solutions cannot make this claim. From their inception, other
distributed solutions utilize a traditional execution model. As applications created by other
solutions migrate toward the net, developers must add security features as appliqués-without the
many benefits of the Java security model.
The business end of the Java security model is conveniently described by using the metaphor of
the Sandbox. The sandbox comprises a number of cooperating system components, ranging from
security managers that execute as part of the application, to security measures designed into the
Java Virtual Machine (JVM) and the language itself. The sandbox ensures that an untrusted-and
possibly malicious-application cannot gain access to system resources.
To implement sandboxes, the Java platform relies on three major components: the class loader,
the byte-code verifier, and the security manager. Each component plays a key role in maintaining
the integrity of the system. Broadly speaking, these components serve the following purposes:
Only the correct classes are loaded
The classes are in the correct format
Untrusted classes will not execute dangerous
instructions
Untrusted classes are not allowed to access
protected system resources
Also fundamental to the Java security model is the concept of a Java Protected Domain. Their
unique characteristics can serve to extend the Java sandbox into the file system thereby offering
a powerful and independently flexible facility. Java Protected Domains enable the use of
"permissions" by the user or can use a pre-configured default setting. This type of capability
serves to extend Java's existing fine-grained control by allowing multiple and unique permissions
for individual applications. Collectively, these and other integral features provide a highly secure
and flexible security model for the Java platform.
Summary
Effective security is not a discreet or static endeavor. It is an on-going process that requires
diligence, the use of appropriate techniques, and a watchful eye on the context in which
computing systems operate. Security measures can fail if not constantly reinforced by training
and revision to address new types of attacks.
The Java Security Model provides developers with an extremely flexible and powerful security
framework that is built-in to the Java platform. This means that developers can create fine
grained security policies and articulate independent permissions for individual applets- all while
appearing transparent to the end user. The Java Security Roadmap has laid the groundwork for
the continued delivery of refinements and new capabilities and in so doing, offers users a high
level of confidence for the future. The Java platform is more secure than any other Internet
access platform, including those that download native (binary) code, while continuing to deliver
excellent usability.
The New World of Computing
The Advent of the Internet
The world of application development is changing at a rapid pace. As the age of the monolithic,
mainframe-based application wanes, a new era of distributed computing is rapidly taking hold.
Distributed development architectures allow applications to be divided into pieces (called
components), each of which can exist in different locations. In fact, this new development
paradigm allows programs to "download" code from remote machines onto a user's local host.
Leading the charge into this brave new world is Java-a execution platform born of the net. It has
made distributed computing a practical reality, while simplifying computing and empowering
users.
One of the strongest catalysts for the Java technology evolution has been the Internet. The
Internet has changed the landscape of modern computing, and perhaps more to the point, is
changing the way we live. Because its full potential is still being realized, even the most ardent
cynic ought to agree that as we move into the 21st century, the world will be at our fingertips-
literally.
The power and potential of the Internet have not been lost on the business community. The
ability to reach consumers and conduct business via the Internet has precipitated countless new
opportunities for electronic commerce. Software organizations have also been quick to recognize
the power of the Internet. For example, customer service organizations have discovered that
using the Internet can reduce the costs associated with product support. In addition, system
designers have discovered that the Internet can provide their users with convenient and cost-
effective access to both personal productivity and mission critical applications. However, the
Internet's tremendous potential does bring with it some tradeoffs. As we'll discuss here, the price
of openness on the Internet might be peace of mind.
Distributed Computing
The continually changing landscape of today's computing systems alters our understanding of
systems architecture and application development. That is, new technologies must be harnessed
to create applications that are more efficiently developed and maintained. A few examples
follow:
Enhanced Transaction Processing - With
distributed applications, single transactions
may span multiple hosts and multiple
processes. However, applications must still
guarantee the atomic integrity of transactions
(i.e., a unit of work.)
Portable Clients and Servers - In distributed
environments, both users and their
applications can move. On the Internet, users
can access applications from just about
anywhere. Similarly, system administrators
enjoy the luxury of moving
applications/components among various
machines based on such factors as load,
hardware failure, performance, and so on.
Enhanced Data Sets - Applications no
longer deal with only simple data types.
Current technologies allow system designers
to incorporate enhanced objects such as
video, audio and multimedia into even the
most basic applications.
With the move toward distributed processing, applications must continue to appear seamless to
users. This can be very difficult because of changes to the underlying architecture. Furthermore,
distributed architectures increase this burden because they provide users easy access to a myriad
of applications.
Distributed computing is also has its attendant compromises for developers: ease of access
increases security concerns. As a result, system designers that are developing for distributed
environments benefit greatly when security is integral. Effective security cannot be added on as a
"patch".
Why Now?
Although many of the ideas expressed here are not new, the seeds of distributed computing are
only now coming to fruition. Why is distributed computing becoming a reality now? In the
recent past, system designers were unable to exploit the advantages of distributed computing
because some basic requirements were missing. Today that has changed, due to a number of
important technological advances. These include:
Better development platforms that are
specifically designed to support distributed
execution environments. Java's Write Once,
Run Anywhere capabilities address one of the
key challenges faced in distributed computing
environments.
Rapid expansion of low-cost, high bandwidth
networks.
General availability of high-performance,
low-cost CPU cycles.
Broader feature sets provided by operating
platforms.
Better development methodologies and tools.
Note that many of these features have a resonant and cascading effect. For example, reducing the
cost of CPU cycles allows systems developers to imbue operating systems with expanded feature
sets; that in turn allows other developers to implement more powerful tools that support and
enhance the efforts of application designers.
Security
Good security practices include a number of important attributes. The following sections discuss
these key attributes in detail.
Authentication
The first task of any security system is to authenticate remote users, systems, and applets.
Specifically, a system should be able to assure it users, to some reasonable extent, that who or
whatever is on the other side of the connection is who or what the user expected to be there. That
is, users should be assured that:
The host that they have connected to is the
host they "called out to" (i.e., the host is not
an "impostor").
The module they have downloaded is really
the one they expected to run. (i.e., the module
has not been replaced with a "substitute").
This is of particular concern in downloaded environments where there is a constant threat of a
"Trojan Horse".
Authorization
Given authentication, the next feature security systems should provide is authorization. Users
and/or administrators should have the ability to decide what level of access to bestow upon an
authenticated principal. Note that for this feature, granularity is an important attribute: highly
trusted resources should be granted more access than those of more dubious origin.
Confidentiality
Confidentiality is a feature that comes in many forms. For example, users should be assured that
any data they are exchanging with a remote host remains private. However, users may also want
to keep confidential the fact that they have simply connected to a particular host. If known, this
fact alone could reveal customer and/or supplier information to a competitor. In short, a secure
system should ensure that all attributes of a connection-time, frequency, data, queries, etc.-
remain confidential.
Containment
Given authentication and authorization, a security system can provide an appropriate level of
containment. That is, once the execution environment establishes an applet's bona fides, it should
ensure its continued compliance by constraining its activities-in effect, it should the applet in a
"box". The system can determine the size, shape, and boundaries of the box by the level of
authorization. As mentioned earlier, Java implements a model based on a Sandbox.
Auditing
A good security system should provide an auditing capability. Thus, if an anomaly or a breach
should occur, the audit trail should assist developers and administrators in their efforts to isolate
and remedy the problem. In a more practical sense, it also helps the business people access the
extent of the damage and decide on an appropriate course of action. Note that while auditing
cannot prevent attacks, it can alert appropriate personnel, record the extent of the breach, and
assist in the eventual repair.
Non-repudiation
Assured authentication provides another important benefit: non-repudiation. That is, parties can
no longer disavow knowledge of a transaction: the security system can "prove" they took part.
As a result, cooperating parties can now execute electronic agreements because each side can
authenticate and prove the other's participation. Thus, both sides can execute an agreement with
the assurance that other side cannot repudiate it..
Security in Practice
Given the previously mentioned attributes, and the fact that no usable system is impenetrable, the
objective of a solid security strategy is to strike a balance among the following goals:
To minimize the potential costs of a breach
To minimize the impact on users
To maximize the difficulty of potential
attacks
Note that the importance of each factor will vary with each system; thus, one would expect the
level and type of security measures employed to vary as well.
Security must therefore be viewed as a trade-off between cost and benefit. However, regardless
of the amount of money spent and effort expended, no system-no level of security-is
impenetrable. The sections that follow will discuss what system security can-and should-
reasonably achieve in practice.
Personnel
Every organization is responsible for vetting its constituents. The tools and techniques discussed
here can do little to protect an organization from the untrustworthy actions of individuals. An
organization must involve every one of its members in security practices-at all levels. These
practices must be established by edict, and reinforced through training. Whether through attack
or apathy, the cost of a security breach is just as great. This is not a new concern, and most
organizations have established vetting practices commensurate with the risk.
System Security
Let's begin by stating the obvious: The only truly secure system is the one that contains no
external access capabilities and remains locked and guarded in a sealed vault. Such a system
would be of extremely limited value to its potential users. Thus, security boils down to a risk
analysis, weighing the benefits of external access versus the costs of a breach.
What Price Security?
Deciding how much to spend on security is a major concern. For example, the security
requirements for a company publishing an on-line catalogue would be much less stringent than
those of a multi-billion dollar bank engaging in nightly fund transfers; and the security needs of
both of these organizations would be less than a governmental agency involved in national
security. In short, the cost of security should remain commensurate with the need. Figure 1,
below, depicts this relationship.
Figure 1
The Price of Security
Usability
As alluded to previously, one typical characteristic of computing systems is that security
corresponds inversely to usability. To the extent possible and practical, security should not
impede users. Systems must remain accessible to those people with authorization to use them.
Indeed, overly restrictive measures can greatly reduce personnel productivity. In extreme cases,
users will often deliberately circumvent security measures when under pressure to "get the job
done at any cost".
Accordingly, different security models afford different levels usability. Because the Java security
model incorporates security features as part of its foundation, it can continue to deliver excellent
usability while enabling security options. By comparison, binary security models must sacrifice
significant usability in order to implement even modest levels of security.
Figure 2
Security vs. Usability
It can be difficult to strike an appropriate balance between security and usability. However,
because of its flexible security model, Java provides many features that allow for "transparent
security". That is, Java environments can provide a high-degree of security without unduly
encumbering the user. While at once, offering the system manager the ability to articulate finely
grained security policies.
False Expectations
In most organizations, a manager's job includes the management of as one of their primary
responsibilities. Surprisingly, many professionals have an elevated expectation involving
computer system security. To understand the risks properly, managers must understand what
security can and cannot provide.
No Risk at All (or, If you can't see it, it doesn't exist)
This is likely the greatest misconception of all. There is no such thing as an impenetrable or
invulnerable system. In fact, this status is unattainable. However, that is not to say that one
should not strive for perfection-only that one should not reasonably expect to achieve it. Security
issues are only one facet of the business jewel: Every dollar spent on security is a dollar not spent
on marketing, research and development, employee training, customer support, etc. Because
security contributes to business overhead, it should be regarded as an important cost of doing
business, just as with other "business overhead" items such as rent, utilities and insurance.
Organizations must weigh the cost of security measures in context with the other needs of the
business.
Narrow Focus
Modern computing networks and architectures can be very complex. Often, security breaches
result from a compartmentalized view of the world, particularly in organizations that divide
security responsibilities among multiple departments. Security breaches occur all too frequently
at the seams between components and systems. Therefore, security policies should encompass a
broader vision that spans department, system, and network boundaries.
One Size Fits All
When a security breach does occur, organizations quickly assemble their "damage control" teams
to quell the attack. This is especially true when deploying new technology: all hands are on alert
and quick to pounce at the slightest indication of a problem. Despite such preparedness, many
organizations lack consistency and follow-through. Security breaches usually occur when you
least expect them. When a break is discovered and repaired in one area, there may be no follow-
up investigation to determine whether a similar problem exists in other areas. Each breach should
be treated as a puzzle: once discovered, the security team should reconstruct the reasons for its
occurrence and eradicate all traces of its signature.
Diligence
Just because the security door is locked today, does not mean that a new attack will not be
fashioned tomorrow. Hackers are an inventive lot with time their side: they have to succeed only
once. Security administrators have to be prepared for intrusions around the clock, and only one
failure might not be considered an acceptable condition.
The Importance of Security
Unfortunately, the convenient, cost-effective network access described previously is also a
troubling concern. This is one of the great ironies the new age of technology: in order to use the
Internet securely-a technology whose raison d'être is to open new vistas-users have to continually
find new ways to implement safeguards. Consequently, everyone who surfs the net must remain
cautious.
Downloading Code
Adding to the welter of concern is the age of remote access. Millions of individuals are
downloading unseen programs, from unknown Web sites, allowing them unquestioned access to
their systems. The power of this architecture is undeniable, but so are the attendant security
concerns. Here are two examples:
A hacker managed to make a downloaded
module appear as if it was a local piece of
code. Once running, the module had access to
the user's disk drive. It was then comparative
child's play for the module to open a socket to
a private host and transfer proprietary data.
In another example, another hacker managed
to get a "Trojan Horse" loaded onto an
unsuspecting user's machine. Once executed,
the module attacked the user's banking
software to transfer funds into the hacker
account.
The precise details of each attack have been omitted (for obvious reasons). The sophistication of
the attacks is of primary concern, and there are plenty of hackers who would like nothing better
to do than to breach a system and get into some malicious mischief.
The Problem with Binary Security
Security problems can be exacerbated in environments that download binary code. That is, the
downloaded code is in the native computing mode of the local host. The reason this is such a
concern is simple: binary code is not as easy to inspect, review, and restrict as is an interpreted
language like Java. Moreover, once executing, the host system can exercise only limited control
on binary modules. This can lead to serious security breaches. (The examples cited above
occurred in binary environments.) To drive home the point, experts in the anti-virus industry
predict that the next major virus barrage will be delivered through ActiveX Controls.
Nonetheless, given that downloading has become commonplace in Internet life, the important
questions one should ask are:
What constitutes good security?
How much can one rely on the execution
environments themselves?
What is the cost of adequate security?
These issues will be explored in more detail throughout the remainder of this paper.
Java Security
The sections that follow address the integral security features of the Java development platform.
However, before we can describe these features in detail, we need to describe some important
features of Java.
The Java Platform
In order to realize the benefits of distributed computing, developers require both design and
implementation tools. Java contains features that enhance the ability of developers to create
sophisticated, distributed applications. Indeed, Java's meteoric success is readily apparent by the
use of an important new term in the computer science lexicon: applet.
Write Once, Run Anywhere
As a rule, applications are tied to their development platforms and cannot easily "port" to other
execution environments. Porting applications across multiple platforms increases the costs of
software development and maintenance. With Java, developers gain the advantage of its Write
Once, Run Anywhere application. Developers can implement the application on their platform of
choice, and users can execute it on theirs.
The Java Virtual Machine
Java achieves Write Once, Run Anywhere capability through Java's architecture. As depicted in
Figure 3, all Java applications run atop the Java Virtual Machine (JVM). The JVM resides on the
host operating system and buffers Java programs and applets from system variances. In effect, it
creates a virtual machine that remains constant across systems. Initially accessible only in
browsers, the JVM is now widely available across a host of systems.
Figure 3
Java's Execution Environment
So, What's an Applet?
Though revolutionary in their own right, static Web pages (such as those written in HTML) can
be quite limited in what they can offer in terms of graphics and interactivity. One of the most
powerful features of Java are applets. An applet is a small executable program embedded in
(Java-aware) Web pages that are downloaded and executed locally by the browser. Thus, Web
publishers can provide sophisticated, dynamic, interactive applications as part of their pages. For
example, instead of displaying static information about a stock, a brokerage house can simulate a
"live ticker" as part of its display.
Other Important Java Features
Architecture Neutrality: Java is designed to
support applications deployed across a wide-
range of platforms.
Network Support: Java provides integral
support for most networking requirements.
Additional Libraries: Java has numerous
ancillary libraries that support the many needs
of distributed applications.
Performance: Java is efficient (especially for
an interpreted language)
Extensibility: Java can interoperate with
many other programming environments.
Multi-threading: Java browsers can generate
more interesting Web pages by allowing
multi-threaded processing.
Based on its initial acceptance, Java will likely become the lingua franca of the Internet. Many
industry observers think it already has.
The Java Security Model
Java's security model differs greatly from traditional approaches. First, most operating systems
permit applications broad access to system resources. Administrators must rely on the users to
ensure that resources are adequately protected (e.g., permissions are set correctly). Second, it is
usually incumbent upon users to verify a program's veracity before executing it (e.g., performing
a virus scan). This approach has two obvious drawbacks: it relies on the user to perform the
verification, and it relies on the accuracy of the verification software itself. As we will see, Java
takes a much more pro-active approach.
The Java Sandbox
Java allows users to download and execute untrusted applications without undue risk by
restricting such code to its own sandbox. Applets may wreak havoc in their own sandbox, but
they cannot disrupt or affect any other sandboxes. Furthermore, restrictions may be placed on
what the application can do within their own sandboxes. Thus, the jvm can allow untrusted
applications to execute in a trusted environment, without fear of corruption or subterfuge.
The Java sandbox comprises a number of cooperating system components, ranging from security
managers that execute as part of the application, to security measures designed into the JVM and
the language itself. The sections that follow describe in detail how Java's security model
constructs the sandbox. In addition, they examine the ways in which Java allows users to extend
the model.
The Class Loader
As mentioned previously, applets are executed (transparently) as part of a Web page. To load the
applet, the browser invokes the Java Applet Class Loader. This forms the first line of defense in
the Java security model: the class loader determines how (and when) applets can load classes
(code). The following briefly describes its major functions:
It fetches the applet's code from the remote
machine.
It creates and enforces a namespace (see
below) hierarchy. One of its more important
functions is to ensure that running applets do
not replace system-level components within
the runtime environment. In particular, it
prevents applets from creating their own class
loader.
It prevents applets from invoking methods
that are part of the system's class loader.
An executing Java environment (i.e., a running JVM), permits multiple Class Loaders-each with
its own namespace-to be active simultaneously. As depicted in Figure 4, namespaces allow the
JVM to group classes based on where they originated (e.g., local or remote). This delineates and
controls what other portions of the runtime environment the applet can access and modify. In
addition, by placing restrictions on the namespace, the class loader prevents untrusted applets
from accessing other machine resources (e.g., local files). In effect, namespaces serve as the
outer wall of the sandbox.
Figure 4
Java Namespaces.
By design, class loaders load all applets and their corresponding classes. When an applet is
executed, the browser invokes the Applet Class Loader, which fetches the applet and instantiates
it as a class. Normally, applets may not install new class loaders; thus, the applet class loader
remains in control of the environment.
The applet class loader creates a new namespace for each applet. Therefore, applets can access
only its own classes, and classes belonging to the standard Java library API. However, they do
not have access to any classes belonging to any other applets. This provide two important
advantages:
Distinct namespaces make it very difficult for
applets to pool their resources in an effort to
form a concerted attack.
Applet developers need not be overly
concerned about collisions: names need only
be unique within a namespace.
There are two important caveats that should be noted:
In browser environments, the class loader is
typically supplied by the system vendor.
Although it is usually based on templates
supplied by Sun, consumers must nonetheless
rely on the vendor's expertise. However, if the
system vendor relies on Sun's templates, users
should not experience any problems.
Java applications are free to create their own
class loaders. In fact, the Java Developer Kit
(JDK) provides a template for a class loader
to facilitate customization. As already noted,
a breach in this area could allow an untrusted
applet to define its own namespace and
breach security. Thus, when designing
custom class loaders, developers should take
care to follow all of the guidelines put forth in
the JDK documentation. If they do, they
should experience minimal difficulties.
Security Feature Summary
Security is an integral feature of the Java platform. The Java security model offers a variety of
ways to inspect, review, and restrict the execution of applications. In contrast, the binary security
model offers only a small fraction of Java's capabilities, and in some instances, offers no security
at all. To illustrate this point, Figures 5 and 6 depict the process flow of code in both binary and
Java models from a security perspective. Note that in the Java model, both untrusted and local
code must pass through the byte-code verifier.
Figure 5
Binary Security Process Flow.
Figure 6
Java Security Process Flow.
The Byte-Code Verifier
Recall that Java source code is compiled into platform-independent byte-codes. Before a class
loader may permit a given applet to execute, its code must be verified by the Byte-code Verifier.
The verifier ensures that the applet's code-which may not have been generated by a Java
compiler-adheres to all of the rules of the language. In fact, the verifier assumes that all code is
meant to crash or penetrate the system's security measures.
The verifier performs several types of validations. At a base level, it ensures that the code
conforms to language specifications. On a more complex level, the verifier applies a built-in
theorem prover against the code. This ensures that the applet does not (among other things) forge
pointers, circumvent access restrictions, or access objects through an illegal cast. The byte-code
verifier, in conjunction with security features built directly into the language (see below), ensures
that:
Compiled code is formatted correctly.
Internal stacks will not overflow or
underflow. (When either of these events
occurs, systems are unstable and hackers can
"play in the confusion.") Historically, this
type of attack has led the way to some of the
most infamous security breaches.
No "illegal" data conversions will occur (i.e.,
the verifier will not allow integers to serve as
pointers). This ensures that variables will not
be granted access to restricted memory areas.
Byte-code instructions will have
appropriately-typed parameters (for the same
reason as described in the previous bullet).
All class member accesses are "legal". That
is, an object's private data remains just that:
private.
Using a byte-code verifier means that Java validates all untrusted code before it permits it to
execute within a namespace. Thus, namespaces ensure that one applet cannot affect the rest of
the runtime environment; code verification ensures that an applet cannot violate its namespace.
Ultimately, the JVM will only execute code that has passed muster with the verifier.
The Security Manager
The third and most important component of Java's security model is the Security Manager. Its
task is to perform run-time verification of all so-called "dangerous methods"-that is, methods that
request file I/O, network access, or those that want to define a new Class Loader. In all such
cases, the Security Manager may exercise veto power over any request. For example, if applet
invokes a "read" method, the JVM consults the security manager. If the applet is trusted (among
myriad other considerations), the request will be permitted; if it is not, the request will be denied.
(Obviously, built-in classes are granted more license than downloaded, untrusted applets.) In
effect, the job of the Security Manager is to police the boundaries between the sandboxes.
Some of the Security Manager's duties include:
Managing all socket operations.
Guarding access to protected resources
including files, personal data, etc.
Controlling the creation of, and all access to,
operating system programs and processes.
Preventing the installation of new Class
Loaders.
Maintaining thread integrity. (There are some
security concerns in this area; this topic is
explored in detail later in the paper.)
Controlling access to Java packages (i.e.,
groups of classes).
To ensure compliance, all methods that are part of the basic Java libraries (i.e., those supplied by
Sun) consult the Security Manager prior to executing any dangerous operations.
Another point to note is that the Security Manager is customizable. This is different that most
binary models: if binary code is trusted, it can do anything; with Java, users can customize the
level of security for each module. For example, the JDK program, appletviewer, reads a
configuration file to set some tunable security options. (Future releases of the JDK will simplify
Security Manager customization even further.)
Type Safety
The Java language itself is designed to enforce security in the form of type safety. This means
the compiler ensures that methods and programs do not access memory in ways that are
inappropriate (i.e., dangerous). In effect, this is the most essential part of the Java security model
in that it fundamentally protects the integrity of the memory map.
To understand how type safety plays a fundamental role, consider the following example.
Imagine a banal class called MyClass, that has a member function called doIt(). Now assume that
doIt() did nothing more that set a Boolean variable to True-but that variable happened to reside at
byte offset 64 in the object. At this point, it all seems rather mundane. Now, let's make it more
interesting and assume there is also a JDK-supplied class call SecurityManager, and at byte
offset 64 resides a flag that, when set to True, allows applets to access the local hard drive. It
does not take a deceitful mind to realize that if you can get a pointer of type MyClass to point to
an object of type SecurityManager, you can invoke the doIt() method and have your untrusted
applet gain access to the local file system.
This type of attack is a major concern in binary models. If a malicious piece of code can gain
access to a protected part of memory, the results could be disastrous.
The JavaSecurity API
One of the core APIs that ships with the JDK is called JavaSecurity. Built as part of the
java.security package, this API will provide for digital signatures, message digests, key
management, and access control lists. A portion of this API contains the Digital Signature
classes. This component will provide tangible classes called Certificate, Key, Signature as well
as extensible classes such as Provider and Algorithm. The latter two represent a specific
JavaSecurity vendor and a specific algorithm, respectively. The JDK ships replete with a default
provider called SunSecurity (located in sun.security). This package also includes an
implementation of the NIST DSA algorithm, the MD5 and SHA message digest algorithms, and
support for X.509 certificates. The access control list package (sun.security.acl) allows users to
define read/write permissions based on users and groups.
Sun defines a vendor that supplies a complete implementation of the JavaSecurity API as a
Security Package Provider (ssp). The important point is that users can rely on the default
package, or purchase and/or create one of their own. Thus, an organization can select a security
level commensurate with their risk tolerance. If you plan to develop an SSP of your own, you
must ensure that your algorithm is secure and that it is bug-free. One error in design or
implementation could render you signatures forgeable or your encryption algorithm breachable.
Digital Signatures and JAR files
There is a type of attack to which all network-based systems might be vulnerable. Called the
man-in-the-middle or middleman, this type of breach is particularly insidious. It proceeds as
follows: a client application requests some service from a legitimate server. Unknown to both
client and server, an attacker application observes this request and waits for the server to
respond. When it does, the attacker intercepts the server's response and replaces it with one of its
own-one that the client may assume came from the original server. To appreciate how
treacherous this type of attack can be, consider that the client might expect to treat this response
as an applet.
The way to thwart this type of attack is to ship code contained within a digital shrink-wrap.
When purchasing software that is delivered on physical media, consumers tend to trust the
product if its from a known supplier and the external packing does not show any signs of
tampering. Java environments can achieve similar results using "signed applets". To do this, a
supplier bundles Java code (and any related files) into a JAR (a Java Archive). The supplier then
"signs" the applet using a digital signature. The client can verify the authenticity of the supplier
by verifying the signature.
Key Management
Key encryption is based on two equally important components: an algorithm and a key. Both the
key and the function are crucial to the encryption -- the same key used in two different
encryption functions will produce two different results, and two keys used with the same
function also produce two different results. The Security API provides support for integrated key
management in Java programs and applets.
Message Digests
Using public-key encryption algorithms to encrypt messages can be quite slow. As a result,
cryptographers have developed a way to generate a short, unique representation of your message-
called a message digest-that can be encrypted and then used as your digital signature.
Access Control Lists
The Security API also provides support for Access Control Lists, which are used to restrict
access to systems and services. The Java Security API provides code that simplifies the effort
required for programs to maintain and access these lists.
JAR files also provide another benefit: increased performance. Current web technology transmits
files serially. Using JAR files, a Web page can download everything it needs in a single request.
Additional Security Considerations
Java Application Security
Java programs come in two main flavors: applications and applets. Java applications are
developed, purchased, and installed just like other types of commercial software. Because such
applications reside locally, they are usually not subject to the stringent security measures applied
to applets. In effect, they execute as "trusted" applications-security is achieved by maintaining
physical control of the local environment.
One caveat: Users should scan all application files for viruses before invoking any newly
acquired programs. This is particularly true for applications delivered via the net. To encourage
this practice, organizations should maintain, and invite the use of, isolated virus scanning
stations. In addition, users and administrators should be encouraged to scan their systems for
viruses regularly.
Java Applet Security
In what is now considered traditional networking infrastructure, organizations safeguard their
environments by restricting access to data, software, and networks. It is true that by merely
accessing Web pages, users may download code onto their local machines that might be obtained
from untrusted party. More importantly, unless otherwise restricted, this code can execute in an
unrestricted manner on the local machine. Thus, code that is downloaded from a remote source
has the potential of becoming the software equivalent of a "Trojan Horse".
Java reduces the likelihood of such an attack by placing rigid, enforceable processing restrictions
on applets.
Untrusted applets cannot read or write
from/to local disk drives-this severely limits
the disruption that an applet can create.
All stand-alone windows created by applets
are labeled as such. Thus, users are
forewarned when entering data into such
screens.
Untrusted applets cannot establish network
connections to other hosts on the network.
This prevents malicious behavior behind the
firewall.
However, this level of applet security is the "default". Consider that the security features
described in previous sections allow users to "trust" applets downloaded from the net. Thus, if
desired, this type of trusted applet can enjoy the same level of security as purchased or "home
grown" applications. That is, if permitted by the user, the JVM can let users '"extend the
sandbox" and establish fine-grained security policies to address almost every need. For example,
a user could establish the policy that applets from site A may read files, whereas applets from
site B may read and write files. The level of granularity can be applied to any system resource:
files, devices, ports, communication channels, etc.
Browser Security
Currently, both major browser products-Netscape's Navigator (versions 2.02 and later), and
Microsoft's Internet Explorer (versions 3.0 and later)-are Java enabled. Moreover, as of this
writing, both browsers' security policies are identical-and rather strict at that. The following
summarizes the applet security conventions adopted by both vendors:
Applets may not read or write files
Applets may only establish network
connections to their original hosts
Applets have access to a limited number
(nine) of system properties
If a local applet is loaded, and its class file
does not reside in a directory specified in the
classpath, it is loaded using the Applet Class
Loader (i.e., it is considered untrusted).
Java Security: The Future
Java Protected Domains
A fundamental element to the evolving Java security model is the Java Protected Domain. This is
a Java security component that has its scope defined by a set of objects that are accessible by a
principal. A principal is any entity in the computer system that has accountability-that is, any
entity to which authorizations may be granted or revoked. The Java Sandbox is an example of a
Java Protected Domain.
By default, Java Protected Domains must remain distinct from each other. Interaction among
domains will be permitted only through trusted system code, or when explicitly permitted by
both interacting domains. This unique characteristic of Java Protected Domains can serve to
extend the Java sandbox into the file system-a powerful yet flexible facility. For example, two
different applets might be allowed to write to a specific part of the file system while each one
was protected from the other. These conditions could be set up as permissions by the user or
enabled through a pre-configured default setting. This type of facility serves to extend Java's
existing fine-grained control by allowing multiple and unique permissions for individual
applications.
Broadly speaking, protection domains fall into two distinct classes: system and application. By
design, all system resources (e.g., files, network connections, screen, keyboard, etc.) are
accessible only through system domains. This architecture is depicted in Figure 7.
Figure 7
Java Protected Domains.
Conceptually, each jvm needs only one system domain. However, for increased security, the jvm
can instantiate multiple system domains, each responsible for a single class of resource. This
greatly reduces the risks and consequences arising from coding errors or security flaws. The
result is that errors and breaches are more likely to be confined within a domain. All Java
Protected Domains (system and application) may also impose additional restrictions on their
internal resources. Thus, developers can extend integral security services to provide support for
custom resources. For example, a brokerage application can define a domain that will protect
such objects as customers, bonds, equities, etc.
Note that a given thread of execution (which may span multiple threads) is not limited to a single
protected domain; indeed, it may span several. For example, a program that wishes to print the
contents of a file will need to interact with the domains responsible for the file system and the
printer. Obviously, the jvm must ensure that the application does not acquire less-restrictive
permissions when it invokes services within one of the system domains. The converse is also
true. If code within a system domain invokes a method within an application domain-such as
when the awt library invokes an application's paint() method-the effective permissions must be
only those enabled in the application domain. There is one important exception to this rule:
surrogate code, or trusted code that executes on behalf of an application. For example,
applications may not access password files directly. However, a trusted utility can change a
password on behalf of a user.
Architectural Directions
The Java Security Roadmap has been carefully constructed to meet the demands of rapidly
expanding distributed systems. The following guidelines will help to shape and update the
roadmap:
easy use for both users and developers
fine-grained control
unique policies for different sources
the ability to manage all system resources
flexibility to support emerging technologies
portable across all platforms
The following section describes some of the new security features for Java that are already in the
pipeline.
Table-based Configuration
Currently, the flexible and fine-grained security policies previously mentioned are available only
at the programming level. Therefore, in order to take advantage of these policies, an organization
must purchase or develop custom code (e.g., extending the security classes). Future versions of
Java will be designed to allow users an enriched ability to establish such policies using a simple,
table-based interface.
Secure Communication
As illustrated by the middleman attack, a conversation is only as secure as the medium itself.
Sun's Simple Key Management Internet Protocol (SKIP) technology allows conversing parties to
agree on an encryption scheme that ensures private communications. The Java Encryption
Extension is a plug-in module that provides an easy way for developers and system
administrators to apply advanced encryption technologies to Java programs. The plug-in is
algorithm and implementation independent thereby offering developers complete flexibility in
choosing from a variety of third party encryption schemes. DES and triple-DES encryption
methods are slated for inclusion in the Java Security model.
Auditing
An important aspect of any security system is auditing-the ability for the system to provide a
journal of events. If security administrators observe or suspect a breach, auditing would offer a
history of the events that will help them determine what happened.
Currently, Java does not define a set of auditing standards. Efforts are now underway to define a
set of standard auditing features that vendors must provide as a standard part of the deliverable.
Domain IDs
One of the problems users might face when using protection domains is cross-machine
authentication. That is, how can code running in a domain on a remote machine gain access to
resources on a local machine-assuming it was "entitled" to them. The local machine would likely
view the remote code as "untrusted", and therefore deny it access to its local resources. To
overcome this limitation, protection domains can be assigned "IDs" that would allow the local
host in this example to authenticate the remote host and allow its code to execute in a local
domain.
Certificate Support
Currently, the use of certificates requires a considerable amount of custom development. To
simplify the use of certificates, Java will supply apis to allow uniform access to third-party
certificate code including X.509v3 and provide a on-line Certificate Authority (ca) server.
Summary
With the rapid expansion of the Internet and the proliferation of distributed computing, new
interest is now focused on the security aspects of both personal and enterprise computing
systems, and with good reason. Millions of computer users are downloading files and
applications of unknown origin every day-directly onto their PCs and workstations. Due largely
to its Write Once, Run Anywhere capabilities, Java has become the de facto development
platform distributed applications, while at once offering the most powerful and flexible security
model available for web-centric environments.
The table below, summarizes the important security attributes discussed in this paper and the
Java platform features that implement them.
Security Attribute Java Platform Feature
Authentication Digital Signatures, Certificates
Authorization Security Manager, Java Protected Domains
Confidentiality Encryption, SKIP Technology
Containment Class Loader, Sandbox, Java Protected Domains, Byte Code Verifier
Auditing Limited, Security Manager, Future enhancements pending
Non-repudiation Digital Signatures, Message Digest
Table 1
Java Security Features
The Java Security Model includes several facilities that are inherent to the Java architecture and
helps to promote a secure operating environment while offering selective permissions to users
and machines. Unlike some binary security models that patch on security features as an
afterthought, the Java Security Model has security built into its foundation. The end result of
Java's security architecture is that it can offer intelligent and selective access to system resources
and information. When compared to "all or nothing" binary methods, the Java development
platform offers superior protection and flexibility.
Appendix A: Security Guidelines
Overview
The few problems experienced by Java users to date can be classified as implementation defects,
rather than inherent flaws in the security model itself. Nonetheless, users and system
administrators should adhere to the following guidelines to enhance their Internet experience:
Use the most current version of all
networking software-particularly browser
programs. Newer versions include fixes for
known security problems of the past.
Employ draconian measures as appropriate-
don't even consider connecting enterprise
systems directly to the Internet. Use firewalls
as appropriate.
Remain vigilant and investigate even the
smallest anomalies. A "missing file" might
really be the result of "a hack".
Be cautious of the web sites you visit-you
never know what you might be downloading.
CERT
Users and administrators should become familiar with CERT (http://www.cert.org). This
organization-funded by DARPA-provides assistance to individuals and organizations that are
experiencing security attacks. In addition to providing assistance to those besieged by attacks,
the organization also issues "alerts" that announce potential and actual security breaches.
Sun's FAQ's
Another way to keep current on security issues is to visit Sun's Java Security Frequently Asked
Questions (FAQ) page. You can find it at: http://java.sun.com/sfaq. The FAQs contain timely
information concerning the details of potential and actual breaches. Additional information on
general security issues can be found at: http://java.sun.com/security.
Appendix B: Security Holes
Types of Breaches
Overview
In theory, there are several types of attacks to which systems using applets might be vulnerable.
They are listed in order of their severity:
Attacks that modify or alter a system or its
resources
Attacks that deny legitimate use of machine
resources
Attacks on an individual's privacy
Attack aimed at merely annoying users
Table 2 below summarizes the types of attacks and Java's ability to defend against them; each is
then discussed in more detail in subsequent sections.
Class Severity Defense
System Modification Most severe Strong
Invasion of Privacy Severe Strong
Denial of Service Moderate Weak
Antagonistic Irksome Weak
Table 2
Classes of Attacks.
System Modification
This is the most serious type of attack-its consequences most severe. By definition, such a breach
implies loss of service, proprietary data, or damage to system resources. This type of attack is
especially important to defend against due to Java's ability to run on many different platforms.
However, although such attacks are theoretically possible, it is extremely difficult to achieve in a
practical sense in most Java environments.
Invasion of Privacy
Examples of this type of attack include the reading of email, modifying messages, and displaying
intrusive (and often rude) messages. Although not as severe as the former, it can have drastic
consequences. Again, Java environments are not easily subject to such attacks.
Denial of Service
This class of attack renders system services unusable. Applets can accomplish this "feat" in any
number of ways:
Exhausting a file system
Allocating all available file pointers
Allocating all available memory
Creating thousands of windows
Consuming CPU cycles
Denial-of-service attacks are, by far, the most prevalent security concern. This is because Java
engineers cannot adequately protect users from such attacks-programs have to run to do anything
useful. Though a real concern, there is usually no material loss (as compared with the prior
classes of breaches) and recovery is usually as simple as re-booting the systems. Nonetheless,
repeated attacks of this type can affect business operations and individual productivity.
Antagonistic Attacks
Less odious, though just as troublesome, antagonistic attacks are meant to annoy users. Examples
include playing unwanted sound files and displaying obscene images on the screen. As with the
prior class of breaches, Java environments can have a difficult time defending against such
attacks. However, losses are usually negligible and recovery is simple.
Security Flaws
The following sections describe some serious security flaws that have been discovered within
Java execution environments. They have all been rectified.
Jumping the Firewall
Most organizations protect their internal networks by using a firewall. A firewall protects the
local environment by acting as a gate: all access to/from the Internet must pass through, and be
approved by, the firewall. When using firewalls, many organizations feel they can relax their
internal security levels. Thus, if hackers can breach the firewall, they might achieve unrestricted
access to the rest of the local network.
In one instance, a hacker managed to use Java to jump a firewall. To accomplish this breach, the
hacker exploited a weakness in Java's DNS translation processing. That is, the hacker managed
to "fool" the runtime environment into believing that his system was a "trusted host". Once that
was accomplished, the JVM allowed a network connection that breached the victim's firewall.
The solution for this breach was to change the criteria used by the Security Manager when
deciding whether a network connection is permissible. This fix has already beenincorporated into
the latest browser releases.
A Question of Locality
In another attack, a hacker managed to make an applet appear as if it was a local, and therefore
trusted, piece of code. This breach required two "slights of hand". First, taking advantage of a
common browser feature called file caching, the hacker managed to store a malicious applet in a
file on the user's local disk. He then "fooled" the browser into loading the applet as a local,
trusted piece of code. The fix for this problem is simple, and has been incorporated into the
current versions of all the popular browsers.
Type Confusion
In a type confusion attack, a malicious applet coerces two pointers of different types to reference
the same object. Thus, the applet can use one pointer to access (read) private information from
the object, and use the other to modify (write into) the object. The result is an applet that can
undermine, or bypass, security restrictions. This problem was fixed in release 3.0 of Netscape's
Navigator.
CERT Alerts
At the time of this writing, CERT has issued two alerts for Java: CA
96.05.java_applet_security_manager and CA-96.07.java_bytecode_verifier. The first deals with
the firewall breach discussed previously; the second concerns a breach in the class loader. Both
have been rectified with updates made by the major browser vendors.
Portions of the White Paper were derived from Java Security: Hostile Applets, Holes, and Antidotes, by Gary
McGraw and Edward W. Felten. Copyright © 1997 by Gary McGraw and Edward Felten. Published by
John Wiley & Sons, Inc., New York, NY. Used herein by permission.
Top Related