Java Security Model

A Java program runs within a JVM, and the JVM itself runs as a normal process on the host machine. As a user process, the JVM enjoys all the rights and privileges associated with the user on resources such as files, devices, ports, memory, CPU, disk space, keyboard, and so on as per the rules of the underlying OS (Operating System). The Java security model works within the confines of this boundary drawn by the OS.

You may wonder—what is the need for an additional security model? Why isn't the OS security model adequate for Java programs? Let us ponder over these facts:

  1. Most Operating Systems provide a user process virtually unlimited power over the resources accessible to the user and considerable flexibility in terms of what instructions it can execute. This makes sense when the program is trusted by the user to do things that he or she intends it to do. This is the case when you run a standalone Java program. However, one of the intended uses of Java is to support execution of mobile code downloaded from the Internet and run within the context of a user's Web browser. Applets are well known examples of mobile code that get downloaded from websites as part of displaying HTML documents. Not all applets can be given unrestricted access to a user's resources. Also, applets from one site cannot be allowed to access objects of applets from another site, within the same Web browser.

  2. Even in situations without any mobile code, it is sometimes possible to exploit program vulnerabilities and trick a user process to execute code that it never intended by supplying it cleverly crafted input data over the network. This happens mostly due to failure of the program to validate the content or size of the input data and let it overwrite program stack or memory locations earmarked for different purposes. Recall from Chapter 1, A Security Primer that these are nothing but stack smashing and buffer overflow attacks and are the number one cause of top security vulnerabilities. Some of these are preventable at the programming language and execution environment level.

  3. The OS security model does not extend to the networks and doesn't apply to security of communication between two parties over an untrusted network like the Internet. Think of it this way—by assigning appropriate access rights to a file on a multi-user machine, you can limit which users can read or modify it, but how do you ensure that the same content is not read or modified when being transmitted over a network?

  4. A number of complex applications are used by multiple users and must authenticate the users and perform authorization of their actions. These users are not necessarily Operating System-level users. Think of any e-commerce site. It allows registration of new users and authentication of existing users through their browsers. In fact, most Web applications provide this functionality.

  5. The fact that the same Java program must be able to run on multiple Operating Systems requires that they cannot rely on the security model and associated APIs of any one Operating System. Java addresses this issue by defining APIs with pluggable providers. For example, MS-Windows has its own way of managing users, assigning access rights and making this service available to Windows programs. Correspondingly, Java platform defines JAAS (Java Authentication and Authorization Service) to let a Java program avail itself of similar functionality. A Java program running on MS-Windows can tap the Windows user management implementation as the provider for JAAS functionality. The same program running on a UNIX platform would make use of a UNIX user management sub-system.

Hopefully, these points make a strong case for a Java platform security model, separate from and on top of the Operating System security.

Java Language Security

As we noted earlier, Java is often claimed as a safe programming language. What does it mean? In simple terms, it means that the language has features that makes it much more difficult to write vulnerable code and it is much harder to subvert the language-defined security rules, either intentionally or unintentionally. This is accomplished by enforcing a number of rules:

A code fragment can access code and data only as per the rules of the Java language. This includes enforcement of a number of rules: (a) A program can access only visible objects through valid references; (b) strict adherence to the access modifiers such as private, protected, public and so on; and (c) proper range checks on accessing array elements. Recall that attacks involving stack smashing and buffer overflow rely on passing control to code segments in violation of such rules in languages that do not enforce such rules.

A variable must be initialized before use. Uninitialized variables are a source of many hard to detect bugs. They could also allow a program to access data stored by another program using the same memory locations. Java ensures that all memory objects are properly initialized and object references are checked for null values at runtime.

The value of a final entity cannot be changed. Change of value for a final variable could alter the behavior of the program relying on this value and can introduce vulnerabilities.

Type safety rules must be adhered to. Free casting of an object reference to another object reference would violate access rules of the language and could allow access of forbidden portions of the memory. Java runtime environment checks for such illegal casts at runtime and prevents them.

This list is not exhaustive but gives an idea of the security offered by the Java language. The actual enforcements of the rules happen not only at compile time but also at class loading and execution time. Compile-time checks performed by the Java compiler flags any violation of access modifier rules, unsafe type castings, use of uninitialized variables and updates of final entities. However, compile-time checks cannot be relied upon to guarantee integrity of mobile code. An attacker could use a “doctored” compiler to generate unsafe code or can modify the generated code using a hex editor or other tool. Java byte-code verifier, an engine that verifies the byte code while loading the individual classes, makes sure that only a valid sequence of byte code gets loaded. Yet another set of checks, such as certain type castings and array bounds checks are performed by the JVM at runtime.

The design issues involved in security of language features and byte-code verifier are complex and at times esoteric. Although of great interest to language designers and JVM implementers, these topics have little impact on a programmer, administrator or user. For this reason, we do not dwell upon these any further.

What about the vulnerabilities in the implementation of JVM itself? Wouldn't that leave Java applications vulnerable to attacks? This is a valid concern. A number of vulnerabilities have been reported in different implementations of JVM and have been fixed. But this should not cause any alarm. JVM implementations have undergone extensive scrutiny and we can be reasonably confident that most of the serious defects have already been addressed or will be addressed by vendors on a priority basis.

Access Control

Java platform provides an elaborate mechanism to specify and enforce access control of certain security sensitive operations with help of a security manager. When a Java program is run by invoking a JVM at command line with the "java classname" command, there is no security manager in force and all code has permission to do whatever the underlying operating system allows. However, you can specify a security manager either at command line or programmatically within the program. A JVM associated with a browser, that runs applets downloaded from various sites, is configured to have a security manager by default. With default settings within a browser, the security manager is responsible to make sure that an applet cannot perform a number of privileged actions including (a) inspect or change a file on the local machine; (b) make a network connection to hosts other than the one from where the applet was downloaded; (c) start another program; (d) load native libraries; (e) get access to certain system property values such as java.class.path, user.dir, user.name, and so on.

With a security manager installed, one or more Java classes can be granted permission to perform operations on basis of the following:

  • Code origin. Location, either a local directory or a URL pointing to a remote site, hosting the .class or .jar files.

  • Code signature. Credentials of the signer, if the code is signed. We talk more about code signing later.

  • Validated user. User on whose behalf the code is running. This requires authenticating the user against a user management system.

Specific permissions can be granted to a collection of classes based on zero (meaning the permissions apply to every class irrespective of its origin, signature or the current user) or more of the above.

Java platform defines a wide variety of permission types applicable to different operations. A privilege to carry out any operation is granted by specifying a permission entity within a grant statement of a policy file. A permission entity has three parts: permission type, target name and associated actions. A permission type is defined by a fully qualified Java class name. Target names and associated actions depend on the permission type.

Let us understand this with the help of an example: A permission of type java.io.FilePermission could apply to a set of files and directories, i.e., target names, for specific actions such as "read" and/or "write".

The permissions can be specified statically in one or more policy files or dynamically at runtime by invoking appropriate methods.

Let us look at a policy file fragment that grants read permission to certain files:

grant codebase "file:/home/Pankaj/" {
    permission java.io.FilePermission "/home/pankaj/work/-", "read";
  };

This statement grants read permission on all the file in the directory tree rooted at /home/pankaj/work to the code in .class files (but not the .jar files) residing in the directory /home/pankaj.

This discussion on access control in Java here has been very brief. Hopefully you get an idea of what we are talking about. We return to this important topic in Chapter 5, Access Control.

Cryptographic Security

As we noted in the first chapter, a number of security features depend on cryptographic operations and related standards. Java platform supports these through various Security APIs. These APIs are part of J2SDK v1.4 and include JCA (Java Cryptography Architecture), Certification Path API, JCE (Java Cryptography Extension) and JSSE (Java Secure Socket Extension). Let us briefly touch on each of these.

  • JCA defines a framework for accessing and developing cryptographic functionality for the Java platform and includes classes for certain functions such as digital signature and message digest. These classes reside in the java.security package and its various subpackages. Chapter 3, Cryptography with Java, explains the JCA framework and specific classes in detail.

  • Certification Path API has classes for accessing, building and validating cryptographic material as defined by Internet X.509 Public Key Infrastructure Certificate and CRL (Certificate Revocation List) Profile. This API is discussed in Chapter 4, PKI with Java.

  • JCE provides classes for cryptographic functionality not included in JCA such as encryption, key generation, message authentication code, and so on. These classes follow the framework defined by JCA and are covered in Chapter 3, Cryptography with Java, along with the JCA classes.

  • JSSE is the API for writing networking programs to exchange data securely over insecure network using SSL/TLS protocol. JSSE classes follow the framework defined by JCA. You can find more about it in Chapter 6, Securing the Wire.

Though we devote a significant portion of the book to cryptography APIs, it should be kept in mind that this is not a book on cryptography. We talk about cryptographic concepts, algorithms, APIs, and other aspects only as much as needed for practical security of J2EE-based enterprise applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.145.2