BUY IT!
Securing Java

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

Section 2 -- Annoying Applets

Next Page
Next Page

The simplest kind of malicious applet is only annoying. Malicious applets of this type do things just beyond acceptable. Because Java has powerful multimedia packages, annoying applets can do a large variety of things, ranging from playing sound files continuously to displaying obscene pictures.

Java has attracted its share of bad programmers and, depending on your point of view, bad Java code can be annoying. To be counted as a hostile applet, some malicious intent on the part of the author is usually required; therefore, unintentionally lousy Java code may not count. Just for the record, a poorly written Java applet may aid a real cracker in breaking your Java security system. Avoid running crummy code, and if you're developing code, use sound software engineering practices and follow the guidelines provided in Chapter 7.

One particularly humorous annoying applet opens a dialog box with the message "April Fools" and an OK button. Users naturally think the applet is supposed to exit when you click OK as it says on the screen. But the dialog box zips around the screen, avoiding the mouse as the user tries to click OK. This quirk renders the applet difficult to stop through normal means. The easiest way to get rid of it is to exit the browser.

Listing 4.1 provides the code for another annoying applet based on an idea from Mark LaDue.1 This applet appears to be well-behaved, at first. All it does is display a nice little picture of one of the author's dogs (and baby Jack). It also plays some appropriate background sound (the dog barking). Not all that exciting for an applet. The code is shown in Listing 4.1.

Listing 4.1 NoisyApplet sustains a thread past the time its creating class is unloaded.

/* NoisyApplet.java                 */
/* Adapted from the NoisyBear applet of Mark LaDue.  */
/* You will need a sound file and a picture to make  */
/* this work.                   */
/* This applet is provided solely as an example and  */
/* is not guaranteed to do anything.         */
/* Use it at your own risk.             */

import java.applet.AudioClip;
import java.awt.*;

public class NoisyApplet extends java.applet.Applet implements Runnable { 
  Font msgFont = new Font("TimesRoman", Font.PLAIN, 36);
  Thread noisethread = null; // thread to run sound in
  Image jackImage;       
  Image offscreenImage;
  Graphics offscreenGraphics;
  AudioClip bark;      // sound file variable

  // the init() runs to set things up
  public void init() {
    // first, set up the picture
    jackImage = getImage(getCodeBase(), "jack+waldog.jpg");
    offscreenImage = createImage(this.size().width,
            this.size().height);
    offscreenGraphics = offscreenImage.getGraphics();
    // then load the audio file
    bark = getAudioClip(getCodeBase(), "bark.au");  
   }

  // the start() method runs whenever you enter the 
  // applet's page. it also runs after init()
  public void start() {
    // start a thread to run the audio clip in
    if (noisethread == null) {
      noisethread = new Thread(this);
      noisethread.start();
    }
  }	

  // the stop() method runs when you exit
  // the applet's page
  public void stop() {
    if (noisethread != null) {
     // uncommenting the following 2 lines will stop 
     // the sound
     // if (bark != null) 
     //  bark.stop();
     noisethread.stop();
     noisethread = null;
    }
  }

  // this starts the ball rolling by telling the sound
  // to "go"
  public void run() {
    if (bark != null) bark.loop();
  }

  // the paint() method draws the graphics
  public void paint(Graphics g) {
    int jack_width = jackImage.getWidth(this);
    int jack_height = jackImage.getHeight(this);

    offscreenGraphics.drawImage(jackImage, 0, 0, 
     jack_width, jack_height, this);
    
    offscreenGraphics.setColor(Color.red);
    offscreenGraphics.setFont(msgFont);
    offscreenGraphics.drawString(
     "Walnut says HI HI HI ...", 150, 225);
    // actually draw the image
    g.drawImage(offscreenImage, 0, 0, this);
  }
}

This applet has been tested and proven to be annoying on a large number of platform/browser combinations.

What makes the NoisyApplet annoying is that the sound never stops, even if the user surfs to another Web page. How could this happen? Simple; the applet starts a thread that never stops!

Why does the sound keep on going? As you can see in the Listing 4.2, the stop() method of the NoisyApplet class has been redefined. The redefinition makes the thread live until the user either figures out how to kill the thread, disable audio on the target machine, or quit the browser.2 None of these options are particularly convenient.

The lines commented out would silence our NoisyApplet by installing a more normal stop() method. By commenting out these lines you can turn our somewhat-typical applet into a malicious annoyance. Clearly, the line between an honest mistake and an antagonistic programming practice is very fine indeed.

There are some interesting implications that our simple annoying applet introduces. Any thread can employ the same strategy of redefining the stop() method in order to run ad infinitum. Depending on the way a Security Manager is written, Java may not require a programmer to stop all threads. Overriding the default stop() method is, as we have shown, a trivial exercise. Threads can run even in the absence of the applet that spawned them, meaning that it is possible to write threads that monitor what the user is doing.


Going beyond stop()

Redefining the stop() method is an easy thing to do, but it is sometimes possible to determine that an applet is doing this by inspecting its byte code. An alternative to redefining the stop() method is wrapping an attack in a try/finally block. This technique is often seen in malicious applets. In fact, today's slickest malicious applets both redefine stop() and use a try/finally strategy. An example is shown in Listing 4.3.

Listing 4.3 Using try/finally to defeat ThreadDeath.

public void run() {
     try { //do somthing interesting here
     }
     catch(ThreadDeath td){System.out.println("Can't touch this!");}
// Return from the dead
     finally{	
           Thread.reborn = new Thread(, "new");
           reborn.start();
     }
}

The idea is to catch any exceptions that might be sent to an applet thread to try to kill it (for example, a ThreadDeath exception, which is what is thrown when Thread.stop() is called). These exceptions are caught in the body of the block. In the finally block, a malicious applet can include code to resurrect itself in case of a problem.

Note that the same sort of thing can be done using an applet's finalize() method, which gets invoked during garbage collection.

This technique counters all attempts to kill a thread and can be used to defeat a majority of commercial Java security packages that claim to be able to kill hostile applets. Stopping an applet that does not want to be stopped is a nontrivial undertaking. One approach might be to hook deeply into the Java runtime and terminate an actual OS thread, but this is problematic since it would sometimes destabilize the entire browser.

Since stopping applets is difficult, making monitoring applets is easy.


The Business Assassin Applet

One such monitoring applet (possibly an armchair exercise) is called the Business Assassin applet [Dean, et al., 1996; LaDue, 1996]. The Business Assassin targets the applets of a particular Web site, such as applets from Gamelan.

If you place this applet on your homepage, it will start up threads on the remote machine of anyone who surfs your site with Java enabled. These threads silently watch for other applets being loaded from Gamelan. If the monitoring threads detect the user surfing the Gamelan Web site, they begin the attack. The malicious threads make useless any applets coming in from Gamelan. They kill the threads of Gamelan applets (something discussed in more detail on page 135). Another feature of the Business Assassin applet (code disabled by default) goes on to launch a denial-of-service attack against anyone who visits Gamelan after running the Assassin.

On the surface, the Business Assassin applet appears to be harmless; that is because it uses threads to do all the dirty work. Threads are not required to stop running when an applet's Web page is exited. This means that threads can keep running in the browser after an applet has appeared to finish. In order to have the blame pinned on some other applet, hostile threads can be programmed to delay their attack until some future time. In the case of the Assassin's threads, an apparent problem in the Security Manager (only addressed recently by Java 2) allows the Assassin threads to attack thread groups that belong to applets other than their own. It waits for the target threads from Gamelan to appear and only then initiates hostile activity.

Applets like the Business Assassin will certainly have a chilling effect on Web-based commerce. Even if applets that use never-ending threads are not used for annoying things like these, they still have the potential to be used for information gathering. If an applet can spawn a monitoring thread, there is no reason that it could not report information it finds interesting back to its server. Such information could include lists of sites a user has visited, files that he or she has downloaded, the names of other competing applets run, or a host of other things. Such monitoring applets should be named BigBrother.

Previous Page
Previous Page


Search Help
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.