A Different Kind of Security Problem

19.5.4 Disabling Dynamic Classloading Entirely

There are a number of situations when you may not want any form of dynamic classloading to be enabled. For example, while it makes perfect sense to download classes to client applications, its much dicier when clients upload classes to servers. Generally, thats a security risk a typical enterprise application might want to avoid. There are two ways to do this. The first is to not install a security manager. Well talk more about security managers in Chapt er 20 , but the basic point is that RMI wont dynamically load classes unless a security manager is installed. On the other hand, security managers are useful objects, and you probably want to use one. The second way to disable dynamic classloading is to set a specific system property. If the java.rmi.server.useCodebaseOnly system property is set to true , then RMI will only load classes from the local filesystem, regardless of whether the class has a codebase annotation.

Chapter 20. Security Policies

Making a distributed system secure is a mindnumbingly difficult task. As a system acquires more users, it will naturally acquire more security holes. In this chapter, well discuss a general-purpose Java mechanism for safeguarding against a new type of security problem. By the end of this chapter, you will understand the security policy mechanism in Java 2, and know how to use it to safeguard some aspects of your RMI application. RMI has been part of the Java platform for a long time. The first versions of RMI were interim releases that worked with JDK 1.2. With JDK 1.1, RMI became part of the Java specification. However, when Java 2 was released, something surprising happened. Working RMI applications suddenly failed. They compiled perfectly, they linked correctly, and they appeared to launch correctly. Yet whenever an application attempted to connect to an external process e.g., the launch code tried to connect to the registry, a socket exception was thrown. The reason for this: Java 2 contains a whole new security model. The net effect of the new security model is that a piece of code, unless explicitly granted permission, is not allowed to access anything that is not entirely contained within the JVM. This means that, for example, a legacy RMI application that doesnt have the appropriate permissions will no longer be able to open socket connections. Because all of RMIs messages travel across socket connections, the new security model quite effectively breaks legacy applications. Technically speaking, this isnt quite true. Permissions are enforced by the security manager. Applications that dont have a security manager installed still behave as they used to behave. However, any program that installs a security manager as RMI programs usually do now requires a security policy. Well discuss how SecurityManagers work in more detail later in this chapter.

20.1 A Different Kind of Security Problem

In Chapt er 2 , we discussed the three classical security problems that can arise in a distributed application. Data confidentiality How do we prevent third parties from seeing confidential information? Data integrity How do we make sure that the data received is identical to the data that was sent? Authorization and validation How can we guarantee that a user or program is who or what it claims to be and, given this, how can we ensure that they are allowed to perform the operations they are attempting? Theres an interesting point about these three security problems: they all assume that the functional code will behave correctly, and that security problems arise as a result of failing to safeguard against devious or careless users. However, as veteran Java programmers know, applets introduced a whole new twist to security issues within an application. You can have a fully functioning encryption layer, and fully authenticated users, and still have a tremendous security problem: the code itself may not be trustworthy. The archetypal applet scenario is a variation on the following: 1. The end user uses a web browser to view a web page. 2. The web page contains an applet. As part of displaying the page, the browser starts the applet running. 3. The applet begins to systematically remove files from the end users hard drive after, of course, first harvesting personal information from them and uploading it to a server. The solution adopted inside of web browsers begins with a simple observation: if the applet cant access the hard drive, then the applet cant harvest information or delete files. This is a generalization of the following rule of thumb: If an applet can communicate only with the server that sent it, and cannot access any information outside of the web page in which it was downloaded, then the applet is a minimal security risk. In such a scenario, the applet has access to only two types of information: • Information that originally came from the server the web page and anything the server sends the applet directly. Letting the applet access this information isnt a security risk. Since the applet came from the server and is part of a web-based client-server application, this really boils down to, An application is allowed to have state, which can be passed around. • Information that the user has explicitly given to the applet. While its possible that this information is a security risk, the plain truth is that the user is in a much better position than our software to decide this. This approach to security inside a web browser has become known as putting the applet in a sandbox or, more succinctly, using a sandbox. The designers of Java 2 made an important observation: applets are simply mobile code. Conceptually, and from a security viewpoint, applets arent all that different from our mobile-code scenarios outlined in Chapt er 19 . In fact, dynamic classloading can lead to massive security violations on a scale beyond the reach of applets. Suppose, for example, a malicious programmer somehow gains access to an applications source code and the RMI registry. She then does the following two things: 1. She creates new stubs that export the same interface as the old stub. These new stubs actually wrap an instance of the original stub and forward method calls to the old stub. However, they also do one other thing: they forward all information sent over the wire to a listening application located somewhere on the Internet. 2. She systematically replaces the stubs in your registry with her new stubs. Now, suppose a user launches a client application and attempts to access a server: 1. The user gets an instance of a malicious stub from the registry. As part of doing so, the user automatically dynamically downloads the malicious stub class. 2. Because the malicious stub actually aggregates the real stub, and sends the messages to the server application, the client application appears to work perfectly. 3. The malicious hacker gets a copy of all the information sent over the wire. This is actually a fairly plausible scenario, which well refer to as client-side contamination. The reason for referring to it as a contamination is, of course, that there is also the possibility of server-side contamination. Suppose, for instance, that a malicious hacker creates a new subclass of Money called SpyMoney , which tries to listen in on all the traffic on the server and forwards anything that sounds interesting. If a client application passes an instance of SpyMoney into a server operation, and the client has set the java.rmi.server.codebase property, then the server could wind up dynamically loading the SpyMoney class and then creating and using instances of SpyMoney . In the age of Internet appliances, it continues to get worse. Were rapidly heading into an age when your washing machine will download software patches from the Internet automatically. Lots of small, special-purpose programs will be flowing over the wires, and most of the traffic will occur without direct human supervision.

20.2 Permissions