1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. An ninh - Bảo mật >

Chapter 3. The New Java Security Model

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.59 MB, 702 trang )


1. Class loader

The class loader (see 2.1.2.1, “The Class Loader” on page 46 and 2.1.2.2,

“Where Class Loaders Come From” on page 47) determines how and

when Java programs can load codes, and ensures that system-level

components within the run-time environment are not replaced.

2. Class file verifier

The class file verifier (see 2.1.2.3, “The Class File Verifier” on page 47)

ensures proper formatting of downloaded code. It verifies that the

bytecode does not violate the type safety restrictions of the Java Virtual

Machine (JVM), that internal stacks cannot over/underflow, and that the

bytecode instructions will have correctly typed parameters.

3. Security manager

The security manager (see 2.1.2.4, “The Security Manager” on page 49)

performs run-time access controls on attempts to perform file I/O, network

I/O, create a new class loader, manipulate threads and thread groups,

start processes on the underlying operating system, terminate the JVM,

load non-Java libraries (native code) into the JVM, perform certain types

of windowing system operations and load certain types of classes into the

JVM. For example, the Java applet sandbox, which severely constrains

downloaded, untrusted applets to a limited set of functions that are

considered to be relatively safe, is a function of the security manager.

Java security functionalities, even if built and designed in the language itself,

have been changing their features over time, and their evolution has been

dependent on the major Java language releases that have been developed

until now: JDK 1.0, JDK 1.1 and Java 2 SDK, Standard Edition, V1.2.



3.2 Evolution of the Java Security Model

The Java programming language is one of the fastest-growing technologies in

use on the Internet today. The principal reason why Java has scored over

other languages is the promise that an application written once in Java can be

run from any machine that has a JVM. From the early stages of Java

development, it was realized that this feature poses the greatest challenge to

Java security because code distribution is risky.



3.2.1 The JDK 1.0 Sandbox Security Model

The entire focus of the initial security model provided by Version 1.0 of the

Java platform (known as the sandbox model) was to treat code downloaded

from a remote location as untrusworthy and provide a restricted environment



70



Java 2 Network Security



(the sandbox) to limit the resources that could be accessed by the alien code.

At the same time local code was considered trustworthy and was allowed full

access to all the system resources, as illustrated in the figure below:



Remote Code



Local Code



JVM



Sandbox



Resources



Figure 30. JDK 1.0 Sandbox Security Model



This was achieved by using the three components discussed in 3.1, “The

Need for Java Security” on page 69, namely the class loader, the class file

verifier and the security manager. However with the actions of the remote

code constrained to a bare minimum, the Write Once, Run Anywhere benefit

of Java could not be fully exploited.

Remote applets, though a powerful concept, were shackled by having to run

inside a sandbox, and by not being able to perform several operations. They

could not read local files and could not write to the disk. They had absolutely

no access to the system resources. Moreover they could establish a network

connection only with their servicing Web server. This heavily restricted the

use of remote applets for all but cosmetic functions to decorate a Web page.



The New Java Security Model



71



3.2.2 The Concept of Trusted Code in JDK 1.1

The next phase of evolution of Java security was based on an effort to

increase the breathing space for remote code at the client location without

compromising the safety of the client. The security architecture in JDK 1.1

introduced the concept of signed remote code. Remote codes, signed by a

trusted entity, were permitted access to several of the system resources that

were off limits for those remote programs without a trusted signature on them,

as shown in the following figure:



Local Code



Remote Code



Signed and

trusted by

the client



Unsigned/Signed

and not trusted

by the client



Sandbox

JVM



Resources



Figure 31. Trusted and Untrusted Code in JDK 1.1



A remote code (a remote applet or servlet, for example) with an appropriate

digital signature was treated with the same respect as local code, and so it

could be considered trusted. An appropriate digital signature was one that

was recognized as trusted by the client.

On the other hand, unsigned remote code or remote code signed with a

digital signature not recognized as trusted by the client, was still confined to

the sandbox.



72



Java 2 Network Security



Though this opened up interesting possibilities, the system was still rather

crude, with all local Java applications enjoying full access to the system

resources and all remotely loaded code running inside a sandbox, unless

signed by a trusted entity.

3.2.2.1 The jar and javakey Tools

Starting with JDK 1.1, the Java platform has offered the jar command line

tool to pack and deliver remote codes together with their signatures, if any, in

the Java Archive (JAR) format. The JAR file format (which we introduced in

1.4.1.3, “Packing the Applet Class in a JAR File” on page 18) is based on the

ZIP file format and is used for aggregating and compressing many files into

one. Although the jar utility can be used as a general archiving tool, the

primary motivation for its development was so that Java applets and their

requisite components (class files, images, sounds, etc.) could be downloaded

to a browser in a single HTTP transaction, rather than opening a new

connection for each piece. This greatly improves the speed with which an

applet can be loaded onto a Web page and begin functioning. The JAR

format, like a ZIP format, also supports compression, which reduces the size

of the file and improves download time still further. Additionally, a JAR file

may be digitally signed by the applet authors to authenticate the origin of the

code.

The JAR format is cross-platform, handles audio and image files as well as

class files and is backward-compatible with existing applet code. JAR

consists of a ZIP archive, as defined by PKWARE, containing a manifest file

and potentially signature files (see http://www.pkware.com). The jar tool is

basically a Java application that combines multiple files into a single JAR file.

JDK 1.1 offered the javakey tool to sign JAR files.

3.2.2.2 JDK 1.1 Security API

The Java security API was built around the java.security package and its

subpackages java.security.acl and java.security.interfaces. The first release

for Java security, available in JDK 1.1, included primarily cryptography

functions, which could be incorporated into Java-based applications. The

cryptography framework in the Java security API was designed so that a new

algorithm could be added later on without much difficulty and could be used in

the same fashion as existing algorithms. For example, even if Digital

Signature Algorithm (DSA) was the only built-in algorithm in this release, it

was possible to use software from providers to help generate RSA signatures

and key pairs for encryption.



The New Java Security Model



73



The first release of Java security in JDK 1.1 included APIs for digital

signatures, message digests, key management and access control lists

(ACLs). APIs for data encryption and other functionalities, together with their

implementations, were released separately in the Java Cryptography

Extension (JCE) 1.1 as an add-on package to JDK, in accordance with United

States export control regulations (see 2.2.3, “United States Export Rules for

Encryption” on page 57). The JCE APIs included block and stream cipher,

symmetric and asymmetric encryption and support for multiple modes of

operation and multiple encryption.



3.2.3 The Fine-Grained Access Control of Java 2

An obvious handicap with the JDK 1.1 security architecture was no easy way

of achieving fine-grained access control, with all local code enjoying

unrestricted access to all the system resources and all remote code

subjected to sandbox constraints unless signed in a way recognizable to the

client as trusted. By fine-grained access control, we mean the ability to grant

specific permissions to a particular piece of code about accessing specific

resources of the client (say read and write permission on file x, but only read

permissions on file y and no permissions on file z) depending on the signers

of the code and/or the URL location from which the code was loaded. Thus,

existence of a fine-grained access control would allow a user to specify

access permissions on a case-by-case basis rather than a rigid classification

of local code being fully trusted and remote code being untrusted and

restricted to a sandbox, unless signed in a way recognizable to the client as

fully trusted.

The new security architecture developed in Java 2 allows easy fine tuning of

the access controls. The concept of signed code can now be extended to

local code as well. With the new security model, all code, whether remotely

downloaded or local, signed or unsigned, will have access to system

resources based on what is defined in a policy file. This allows the client to

explicitly specify the permissions to be granted to different signatories of code

and different sources. This way the end user can download, install and run

applications from the Web by granting them permissions for only those

actions that are necessary. This will eliminate codes that have a hidden

agenda, such as letting you play a nice game while sending your credit card

information or your password file to a particular server at the same time.

Consider for example the following scenario, based on the JDK 1.1 security

model. You download a little tic-tac-toe program from the Web. It is signed by

an entity you trust, and you are sure that it will not crash your system. For this

reason, you accept to run it. Nonetheless, this code reads your address book,

and sends all the e-mail addresses you have to the database of the nearest



74



Java 2 Network Security



junk mailer. Though not very malicious, this is something we all would like to

avoid. This is a very likely situation, since more and more software is just

being brought off the net, and this trend is likely to continue for a long time.

This might lead to fly-by-night software vendors, some of whom might come

up with very innovative software, but some of whom you cannot really trust.

With JDK 1.1, you do not have an option to restrict access to code to do only

certain things. You either install the software, or you make do without it.

However, if you are running Java 2-enabled software, you can instruct the

JVM, through modifications in a policy file, that code loaded from a particular

URL (local or remote) and/or signed by a particular entity is restricted to

specific local resources. For example, you may specify in the policy file that

the code in question may read files in one particular directory and can do

nothing else – cannot open sockets, cannot write or delete any files, etc. This

is the fine-grained control mechanism offered by Java 2. For more on this, see

1.4, “Understanding Java 2 Security” on page 12.

In versions of Java prior to Java 2, the JVM resource access was enforced by

the sandbox security model, which was a function of the security manager.

Extensions were usually limited to features implemented by the platform

providers such as Web browsers and Web servers. When using Java 2, you

can have full control over what each of your programs and applications is

permitted to do – this was never possible until now. Similarly, you can now

define the exact things an applet coming from a particular URL can do, or

what any programs (applets, applications, servlets) signed by one or more

particular entities can do. Further, in multi-user systems, the system

administrator can define a default system policy, and each of the users of the

system can have their own policy, which is combined with the system default.

Java programs now have the ability to define access restrictions on sensitive

resources without having to write a new security manager or modify the

underlying platform. For example, applets downloaded into a Java 2-enabled

Web browser and servlets downloaded into a Java 2-enabled Web server can

add resource access controls to a JVM without having to modify the

underlying browser or server implementation. These new concepts of

permission and policy enable the Java 2 platform to offer fine-grained, highly

configurable, flexible, and extensible access control.

The Java 2 security model has been depicted in Figure 32 on page 76. As

seen in the figure, a predetermined security policy of the client decides the

security domains within which a specific piece of local or remote code can

reside:



The New Java Security Model



75



Local or remote code

(signed or unsigned)



Security

Policy



Domain A



Domain B



Sandbox



Domain C



JVM



Resources



Figure 32. Fine-Grained Access Control Mechanism in Java 2 SDK



3.2.3.1 Lexical Scoping of Privilege Modifications

A new security feature implemented for the first time in Java 2 is the lexical

scoping of privilege modification, which is a technique enforcing the least

privileged mode. Using this technique, it is possible to enable only the

execution of the piece of code that needs the privilege. All the sensitive code

could therefore be added at one place and defined as privileged, by calling

the doPrivileged() method, belonging to the java.security.AccessController

class. The doPrivileged() method is discussed in 3.5.1, “Run-Time Access

Controls” on page 91. But to get an idea in advance, basically, through the

use of this method, Java 2 provides a facility to mark Java code as being

privileged and temporarily grant it some permissions that it normally would



76



Java 2 Network Security



not enjoy by itself by virtue of its location of origin and the identity of its

signers.

3.2.3.2 Java 2 Security Tools

Java 2 provides four powerful security tools for ensuring confidentiality,

integrity, authenticity of data and adequate control on access to various

system and non-system resources. These are jar, keytool, jarsigner and

Policy Tool.

The jar function is similar in Java 2 to what it was in JDK 1.1 (see 3.2.2.1,

“The jar and javakey Tools” on page 73). JAR files acquire specific

significance, since the old javakey, and its newer version jarsigner, can sign

only JAR files.

The keytool command line utility creates key pairs – pairs of public and

private keys – imports and exports X.509 V1, V2 and V3 certificates (see

Appendix C, “X.509 Certificates” on page 649), generates self-signed X.509

V1 certificates and manages keystores. A keystore is a protected database

that holds private keys as well as public keys and certificates. In the default

implementation, a keystore is protected using a password and each private

key stored in the keystore is protected with a possibly different password. The

private keys are used to digitally sign applications and applets whereas public

keys are used to verify signed data, and certificates are used to verify

whether a public key indeed belongs to the person it is supposed to belong.

The jarsigner command line tool signs JAR files and verifies the signature(s)

of signed JAR files. It accesses the keystore when it needs to find:

• A private key when signing a JAR file

• A public key when verifying a signature

• A certificate when verifying a public key

In the Java 2 platform, the keytool and jarsigner command line utilities

replace the JDK 1.1 tool javakey. The javakey tool had several shortcomings,

the most significant of them being the fact that both the public and private

keys were stored in the same, unprotected location (often called an identity

database). This allowed anyone with access to the identity database to

determine all keys that were stored in the file. In contrast, private keys are

now password protected in the keystore.

The Policy Tool utility, which is launched through the policytool command,

creates and modifies the external policy configuration files that define the

client’s security policy.



The New Java Security Model



77



All of these tools are discussed in detail later in this book (see Chapter 9,

“Java 2 SDK Security Tools” on page 259).

3.2.3.3 Java 2 Security API

In Java 2 two new subpackages have been added to the java.security

package, and they are java.security.cert and java.security.spec. These

packages offer more features to deal with X.509 certificates and to create

certificate revocation lists (CRLs) and certificate signing requests (CSRs). In

particular, java.security.Certificate, that in JDK 1.1 was an interface of

abstract methods for managing an identity certificate, is completely

deprecated in Java 2, which offers the entire package java.security.cert to

handle certificates. Moreover, the package java.security.cert adds X.509 V3

support to certificates.

Java 2 also provides an additional certificate interface: the X509Extension

interface in the java.security.cert package. This is an interface for X.509

extensions. The extensions defined for X.509 V3 certificates and V2 CRLs

provide methods for associating additional attributes with users or public

keys, for managing the certification hierarchy, and for managing CRL

distribution.



3.2.4 A Comparison of the Three Java Security Models

Table 1 on page 79 shows a comparison of the three Java security models

based on seven parameters, which are:

• Resource access to local unsigned code

This refers to the options provided by the security architecture to a client

to determine access to local resources for local unsigned code.

• Resource access to local signed code

This refers to the options provided by the security architecture to a client

to determine access to local resources for local signed code.

• Resource access to remote unsigned code

This refers to the options provided by the security architecture to a client

to determine access to local resources for remote unsigned code.

• Resource access to remote signed code

This refers to the options provided by the security architecture to a client

to determine access to local resources for remote signed code.

• Lexical scoping of privilege modification

This refers to the availability of the option in the security architecture to

temporarily grant more privileges to a specific piece of code in an



78



Java 2 Network Security



execution thread, which are additional to the privileges the code would

have enjoyed by itself. This facility is available only with Java 2 and

achieved with the help of the doPrivileged() method introduced in 3.2.3.1,

“Lexical Scoping of Privilege Modifications” on page 76. This method

actually internally modifies the way the run-time stack (for an execution

thread) is checked for permissions.

• Cryptographic services for data confidentiality/integrity

This refers to the availability of cryptographic services for data

confidentiality and integrity. Such services became available only with JDK

1.1.

• Digital signature services for code signing

This refers to the facility of digital signature services for signing code.

Such services became available only with JDK 1.1.

Table 1. Evolution of the Java Security Model



JDK 1.0



JDK 1.1



Java 2 SDK



Local unsigned code

resource access



Unconstrained



Unconstrained



Policy based



Local signed code

resource access



Not available



Unconstrained if trusted



Policy based



Remote unsigned code

resource access



Constrained by the Java

sandbox



Constrained by the Java

sandbox



Policy based



Remote signed code

resource access



Not available



Unconstrained if trusted



Policy based



Lexical scoping of

privilege modification



Not available



Not available



Stack annotation based

with doPrivileged()



Cryptographic

services for data

confidentiality/integrity



Not available



Java Cryptography

Extension 1.1



Java Cryptography

Extension 1.2



Digital signature

services for code

signing



Not available



Java Cryptography

Architecture DSA

signature



Java Cryptography

Architecture DSA

signature



Constrained by the Java

sandbox if untrusted



Constrained by the Java

sandbox if untrusted



This comparison shows the increasing flexibility and functionality provided by

the evolving Java security model in determining a security policy.



The New Java Security Model



79



3.3 Java 2 Protection Domain and Permissions Model

This section explains the concepts of protection domain, code source and

security policy file which are the foundations of the new security model.

A protection domain can be scoped by a set of objects that are currently

directly accessible by a principal, where a principal is an entity in the

computer system to which permissions are granted. A principal can access

objects in the protection domain by virtue of the permissions it enjoys over

the objects in the protection domain. These permissions are specified

explicitly in a security policy file, which is a text file that can be edited

manually or through the Policy Tool. The Java 2 security architecture allows

the combination of a system security policy, defined by the system

administrator, with one or more user-defined security policies. A default

system policy file comes with the installation of the Java 2 SDK (see 3.6, “The

Policy File” on page 93).

Notice that, even if an arbitrary number of policy files can be specified, there

is only one policy (meaning, one set of protection domains) in effect for the

JVM at any given time. That policy might be the result of processing the

information from many policy files. The default policy implementation, via the

java.security.Policy class, has a public refresh() method that can be used to

re-init the policy, eventually re-reading the policy file(s). However, there is no

automatic policy change: refresh() must be called explicitly.

Using this security model, it is possible to grant specific access permissions

to specific code whether local or remote. Local or remote code is now

identified by its code source. The code source for a code is a combination of

the URL location from which the code is loaded and the entity or entities that

signed the code originating from that location. The code source is

represented by the java.security.CodeSource class. The location from which

the code is loaded is passed as an argument to the constructor of the

CodeSource class in the form of a java.net.URL object. The identity of the

signer(s) is passed as the second argument to the constructor of the

CodeSource object in the form of a set of java.security.cert.Certificate

objects. These certificates are for the public keys corresponding to the private

keys that signed the code. The constructor of the CodeSource class therefore

looks like the following line:

public CodeSource(URL url, Certificate[] certs)



The location from which the code is loaded is referred to as the code base in

the policy file, as we have seen in the examples of 1.4, “Understanding Java 2

Security” on page 12. In the Java 2 security model, a policy file serves as a



80



Java 2 Network Security



Xem Thêm
Tải bản đầy đủ (.pdf) (702 trang)

×