Securing Java

Previous Page
Previous Page
Malicious Applets: Avoiding a Common Nuisance
CHAPTER SECTIONS: 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 / 9

Section 3 -- Denial of Service

Next Page
Next Page

In a cracker's world, the next-best thing to breaking in to your computer is locking you out of it. After all, if the cracker cannot use your computer, then neither should you! Attacks that prevent someone from using his or her machine are called denial-of-service attacks in the security community. Denial of service comes in many guises. Attacks may involve consuming all available CPU cycles, allocating every last bit of memory, hogging all possible screen space, or causing a system to hang while it waits for something impossible to happen. The one common requirement is that the user being attacked is effectively locked out of his or her machine. An effective denial-of-service attack happens so quickly that it's usually impossible to stop it. Experiencing such an attack is a sobering event.

There are many ways to write applets initiating denial-of-service attacks. We think these attacks are serious enough that code for them is not listed here. Examining some attacks through high-level description and occasional code fragments should be enough to illustrate a point. Realistically, the sorts of malicious applets being described are not too difficult to dream up. People who are interested will be able to either create the code or find it, as they see fit.

Consider the denial-of-service attack presented in Listing 4.4. It recycles an idea from the NoisyApplet making use of nonterminating threads. Quite simple to formulate, it looks something like this:

  1. Create an applet that starts a thread with its priority set to MAX_PRIORITY. This makes the thread run as quickly as possible and gives it a leg up in the ongoing competition between threads for CPU time.
  2. Redefine the stop() method to null for the thread.
  3. Do something silly in the main part of the applet so that it appears to be harmless. Show a picture or display some cute animation.
  4. Have the thread sleep for a while to delay its malicious activities. Such sleight of hand will have the effect of placing the blame somewhere else when the thread wakes back up to perform its dirty work.
  5. When the thread wakes up, have it begin calculating in an infinite loop (or some other CPU-intensive activity that eats cycles). Such a computation will, in effect, bring the browser down by taking away all available computational resources. One particularly worthy function for intense calculation overload is the Ackerman function shown in Listing 4.4.
Listing 4.4 The Ackerman function implemented as a Java application.
Ackerman takes integer n and exponentiates n by itself n times. This means that Ackerman(3) is equivalent to three cubed, cubed. The program can be run by typing the command java Ackerman n, where n is an integer. Computing anything greater than Ackerman(3) takes a long time and many CPU cycles. This code was written to be as inefficient as possible. This version of Ackerman could easily be used in a denial-of-service attack.

import java.lang.System;
import java.lang.Math;

class Ackerman {
public static void main(String[] args) {
  long ackValue = 1;
  long exp = 0;

  if (args.length >= 1) {
    try { exp = Integer.parseInt(args[0]); }
    catch (NumberFormatException e) { exp = 0; }

  if (exp > 1) {
    ackValue = exp;
    int numLoops = (int)exp;
    for (int i = 1; i < numLoops; i++) {
   	  exp = ackValue;
	  for (int j = 1; j < numLoops; j++) {
	    ackValue = ackValue * exp;
	    System.out.println("current value is " + ackValue);
    System.out.println("Ackerman vlue: " + ackValue);

This denial-of-service approach is simple and elegant. There are literally hundreds of things that can be done in Step 5. Other possibilities include endlessly appending to a StringBuffer and using drawString to display its entire contents. This ends up as a double whammy, eating both CPU cycles and memory. Another possibility would be calculating p using the most inefficient algorithm possible. If you have trouble remembering how to code poorly, just teach an introductory programming course to jog your memory.

On a more serious note, this line of attack is both very simple and very successful. Most browsers seize up and die under such an attack.

Applets that implement these strategies exist on the Web now. Skeptical readers are welcome to surf over and kill their browsers personally ( Just surf to a Web page containing hostile applets using a Java-enabled browser, and they will automatically be invoked. Short of creating and enforcing a mobile code policy based on code-signing, nothing can be done to prevent them. Chapter 6 examines some strategies for protection, but they are all still in early development. Just to complicate matters, such a hostile applet can implicate other Web pages by using delay tactics discussed previously.

Is Denial of Service All That Bad?

There is no doubt that denial-of-service attacks are less serious than security breaches of the sort we discuss in Chapter 5. Although a browser might be crashed with such attacks, intruders do not gain entry into a system. This has led some people at JavaSoft to dismiss this class of attacks as unimportant. Before Arthur van Hoff (one of the original designers of Java) left JavaSoft for Marimba, he posted a note to that dismissed such problems as either not very serious or a concern for browser vendors-not JavaSoft. Although the most serious security problems should be addressed first, denial-of-service applets should also be addressed. Using resource allocation limitations-for example, placing upper limits on CPU usage, number of instructions that can run, or number of windows allowed-is one line of defense. Threads should not be able to override the stop() method so easily, either. (The ability to override stop, or not, is now enforced by policy.)

It is ironic that some of the most Java-heavy Web pages almost go as far as denial of service in doing what their programmers intended. Some Java-enhanced sites take quite a while to load (we have heard of some applets that take 10 minutes to start up, even over a very fast T1 connection). The bottleneck likely involves the byte code Verification process and not the network transmission time. Of course, slow loading/verifying really doesn't constitute a true denial-of-service attack.

Even a denial-of-service attack that is no big deal when embedded in an applet becomes a serious problem if it can be launched against a Web server. Sites that use Java-enabled Web servers and configure those servers to allow anyone to upload a servlet are exposing themselves to easy denial-of-service attacks. In short, anyone, anywhere in the world, can bring down such a server whenever he or she feels like it. That's why we recommend that Java-enabled servers only accept servlets from clients that they really trust.

Previous Page
Previous Page

The Web

Next Page
Next Page

Menu Map -- Text links below

Chapter... Preface -- 1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -- 8 -- 9 -- A -- B -- C -- Refs
Front -- Contents -- Help

Copyright ©1999 Gary McGraw and Edward Felten.
All rights reserved.
Published by John Wiley & Sons, Inc.