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.
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.
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.
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".
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.
Good security practices include a number of important attributes. The following sections discuss these key attributes in detail.
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".
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 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.
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.
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.
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.
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.
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.
The Price of Security
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.
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.
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.
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.
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.
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.
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.
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.
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.
Binary Security Process Flow.
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.)
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 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.
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.
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.
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.
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|
|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.
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.
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.
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.
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.
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.
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|
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
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.|
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.
Another way to keep current on security issues is to visit Sun's Java Security Frequently Asked Questions (FAQ) page. You can find it: here. The FAQs contain timely information concerning the details of potential and actual breaches. Additional information on general security issues can be found: here.
Appendix B: Security Holes
Types of Breaches
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.
|System Modification||Most severe||Strong|
|Invasion of Privacy||Severe||Strong|
|Denial of Service||Moderate||Weak|
Classes of Attacks.
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.
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.
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.
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.
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.