There are two features of Java that must be used to make applets useful. They are multithreading and the ability to open a network connection to the server from which the applet was loaded. Without these features it will be very difficult to create Applets that have good interactive response, or are able to do useful work.
However the combination of these features can lead to a denial of
service attack on Java capable WWW browsers.
I will show that this attack is not of great concern,
and can actually be used as an effective way of sharing
the computer resources in an organisation.
Keywords: java, security, attacks, denial, service, share, resources
In this paper I will look at a possible denial of service attack that arises out of two features of Java that can not easily be removed. I will show why this attack is not a great cause for concern, and may even lead to a solution to one of the fundamental problems in operating system design.
However, for the purpose of this paper I want to be explicit about what Java is and how it is used. For that purpose, Java is two things:
The question to ask is, 'What is so useful about a program downloaded into a Web page?' This may be inverted to read, 'What features must a program have to make it useful in the context of the WWW?'.
Consider that one of the main selling points of the WWW is that it provides an interactive way to explore the myriad information available on the Internet. The particular appeal of browsers such as Mosaic and Netscape is that they give a graphical user interface to the 'net. Therefore any downloadable programs we expect to run in those browsers should extend this interactivity, and provide better and more responsive user interfaces than ordinary WWW pages.
In addition, if we want these downloadable programs to do anything more than brighten up a Web page with some animation (which these days can be done just with GIF files anyway), then we must provide a way for these programs to have a memory. For example, if a word processing program cannot remember your document from one session to the next, then it is just a typewriter.
But providing this memory is fraught with danger since it can lead to giving access to your system to code that is not trusted. The problems inherent in this are described in 'Mobile Code Security', presented at this conference. (Brown 1996) The response of the Java designers was to require that systems that download and execute applets impose the Java Security Model on those applets.
I would go further to say that multithreading is almost an essential part of creating interactive graphical user interfaces. To see why, examine the following example.
The Bounce application presents the user with two buttons: 'Start' and 'Close'. When the user presses 'Start', a black ball starts bouncing around the screen - it moves 1000 times and stops. The code for Bounce is shown in Appendix I.
The trouble with Bounce.java is that it is single threaded. This means that while the program is bouncing the ball around the screen, it can't think about anything else - like processing mouse clicks. So if you tire of seeing the ball bounce around the window and wish to close the window, that's tough. You must wait until the ball has finished bouncing before the next click on the close button will be recognised.
I have seen this effect in many X Windows programs. As soon as you ask the program to go fetch something from a remote database, the whole GUI freezes up until the remote database responds.
Fortunately, in Java this is easy to fix because multithreading is very easy to implement in a Java program. A multithreaded version of Bounce, BounceThread, is shown in Appendix II, with the differences between Bounce.java and BounceThread.java shown in Appendix III. All we have really done is turn the Ball object in to a subclass of Thread. This means that the Java Virtual Machine will execute Ball's 'run' method in a separate thread, leaving the thread running the Bounce object's 'main' method free to handle interaction with the user.
This has a side effect though. In this version of the program, the 'Start' button can be hit as often as desired. Each time it is hit, a new Ball object is created, allocated a thread, and starts running. Thus, it is possible to have many balls roaming the screen at once:
In summary, it pays to note that almost any object can be allocated a thread by subclassing the object from the Thread class, making sure it has a 'run' method that does something useful, and getting someone to call its 'Start' method.
Appendix IV shows an applet that contacts the host it was downloaded from and asks it what the time is, giving a result similar to this:
You would expect networking to be easy in a language system that is supposed to tie together the Internet. And, in fact, if all you are doing is fetching URLs, the networking code becomes even easier.
Note that applets in particular must be able to access the network if they are to have a memory. This is because of the security restrictions outlined above - remember, an applet cannot touch your local file system.
There are many problems in computing that can be split into an arbitrary number of pieces to take advantage of however many CPUs are available. For example, rendering a scene in computer graphics or cracking a key by brute force in cryptography.
By creating a Java applet that spawns a thread to do work for the server and then sends the results back to the server over a socket connection, the computer running the Web browser can contribute to the calculation the server is performing.
Here is an example of how it would work. Say I wanted to calculate a region of the Mandlebrot set. I could create a thread that would take as arguments the y value for a row, the start x, end x and delta x values for the points to be calculated. The thread would then send back values for pixels until it reached the end of its row, or it was terminated (possibly by the user going to another page).
Meanwhile, the server would keep track of which parts of the image had been drawn and which applets were connected. As new applets were connected, the server would send them an unfinished part of a row to do. The more applets that were connected, the faster the server would generate its image.
Note that time constraints prevented me from constructing this example, but in principle it is not difficult.
However, if you look at the security problems in Java that have received all the hype - CERT 1996a, CERT 1996b, Dean et al. 1996, Home Page Press 1996a, Home Page Press 1996b - you will note that they are caused by bugs in the implementation of the Java Virtual machine, and not by flaws in the Java security model.
My point is that you cannot prevent someone taking advantage of your CPU without turning off one of these very desirable features of Java. As noted above, if you take out multithreading, then performance of applets goes down and you get worse interactive behaviour. If you remove networking, even by blocking communications with a firewall, then you are limited in how useful you can make applets
The worst attack that someone can launch against you is to waste your CPU cycles. But since you were 'surfing' the Web, they probably were not doing anything useful anyway.
Another consideration is that, as an applet programmer, there are two ways I could waste your CPU cycles. I could use these features to get the applet to do useful work for myself, or I might just be a very bad programmer (likely, since I am writing Web content) and write inefficient Java code. As a user of my applet, it would be hard for you to tell the difference.
There are some examples on the Web of hostile applets that purposely burn up CPU and/or memory - a denial of service attack (Javasoft 1996). The Java developers are aware of this and are developing means to restrict an applet's resource usage. However, they face a fundamental problem. As they put it, 'It is hard to automatically tell the difference between a hostile applet and an MPEG viewer'.
Most organisations arrange their computing resources these days on the Workstation Model. Every user has their own computing resource on their desk, connected via a network so that resources such as printers, file servers or computer servers can be shared. A problem with this model that has been the subject of considerable amounts of research is that few people make 100% use of their workstation - they spend many hours away from their desks, and even when at their desks they may not be using the computer (Tanenbaum 1992, ch. 12). How do we make use of these idle workstations?
One approach is taken by operating systems such as Amoeba or Plan 9. Taking the slogan 'the network is the computer' to its logical extreme, these systems treat every computing device on the network as a resource that can be applied to whatever workload is pending.
The trouble with this approach is that it is too socialist: 'From each CPU according to its cycles - to each process according to its code'. The reason the managing director has the biggest computer is that, although it spends 99.97% of its time in the idle loop, when the MD does want it, he gets very fast response. He would not get this response if he was sharing it with others.
Others have tried a user level approach to this, for example, the Pratt & Whitney 'SuperComputer At Night' programme, where every workstation is devoted to complex numerical analysis problems from 5 p.m. to 9 a.m. (Mackay 1996), and the TreadMarks system (Amaza et al. 1996). The problem with these systems is that the user's workstation is taken out from under her, whether she is still using it or not.
Wouldn't it be nice if you could say when others could use the CPU power of your workstation, and even choose which projects could use it?
Well, by using these features of Java, that is exactly what you can do. Create a Java applet that contributes towards some large calculation, then to share your computer - when you want to - simply load the appropriate web page into a browser. When you no longer wish to share your CPU, just close down the browser.
It is difficult to solve this problem and prevent this attack, because the features involved are very useful themselves, and it is difficult to tell a malicious applet from one that just needs a lot of resources.
However, while this can be used as an attack, it could also be used as a way of sharing the computer on your desktop when you are not using it.
/*
* Gary Cornell and Cay S. Horstmann, Core Java (Book/CD-ROM)
* Published By SunSoft Press/Prentice-Hall
* Copyright (C) 1996 Sun Microsystems Inc.
* All Rights Reserved. ISBN 0-13-565755-5
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for NON-COMMERCIAL purposes
* and without fee is hereby granted provided that this
* copyright notice appears in all copies.
*
* THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR
* WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
* AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED
* BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* @version 1.00 07 Feb 1996
* @author Cay Horstmann
*/
import java.awt.*;
public class Bounce extends Frame
{ public Bounce()
{ setTitle("Bounce");
canvas = new Canvas();
add("Center", canvas);
Panel p = new Panel();
p.add(new Button("Start"));
p.add(new Button("Close"));
add("South", p);
}
public boolean handleEvent(Event evt)
{ if (evt.id == Event.WINDOW_DESTROY) System.exit(0);
return super.handleEvent(evt);
}
public boolean action(Event evt, Object arg)
{ if (arg.equals("Start"))
{ Ball b = new Ball(canvas);
b.bounce();
}
else if (arg.equals("Close"))
System.exit(0);
else return super.action(evt, arg);
return true;
}
public static void main(String[] args)
{ Frame f = new Bounce();
f.resize(300, 200);
f.show();
}
private Canvas canvas;
}
class Ball
{ public Ball(Canvas c) { box = c; }
public void draw()
{ Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move()
{ Graphics g = box.getGraphics();
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
y += dy;
Dimension d = box.size();
if (x < 0) { x = 0; dx = -dx; }
if (x + XSIZE >= d.width) { x = d.width - XSIZE; dx = -dx; }
if (y < 0) { y = 0; dy = -dy; }
if (y + YSIZE >= d.height) { y = d.height - YSIZE; dy = -dy; }
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void bounce()
{ draw();
for (int i = 1; i <= 1000; i++)
{ move();
try { Thread.sleep(10); } catch(InterruptedException e) {}
}
}
private Canvas box;
private static final int XSIZE = 10;
private static final int YSIZE = 10;
private int x = 0;
private int y = 0;
private int dx = 2;
private int dy = 2;
}
/*
* Gary Cornell and Cay S. Horstmann, Core Java (Book/CD-ROM)
* Published By SunSoft Press/Prentice-Hall
* Copyright (C) 1996 Sun Microsystems Inc.
* All Rights Reserved. ISBN 0-13-565755-5
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for NON-COMMERCIAL purposes
* and without fee is hereby granted provided that this
* copyright notice appears in all copies.
*
* THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR
* WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHORS
* AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED
* BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*/
/**
* @version 1.00 07 Feb 1996
* @author Cay Horstmann
*/
import java.awt.*;
public class BounceThread extends Frame
{ public BounceThread()
{ setTitle("BounceThread");
canvas = new Canvas();
add("Center", canvas);
Panel p = new Panel();
p.add(new Button("Start"));
p.add(new Button("Close"));
add("South", p);
}
public boolean handleEvent(Event evt)
{ if (evt.id == Event.WINDOW_DESTROY) System.exit(0);
return super.handleEvent(evt);
}
public boolean action(Event evt, Object arg)
{ if (arg.equals("Start"))
{ Ball b = new Ball(canvas);
b.start();
}
else if (arg.equals("Close"))
System.exit(0);
else return super.action(evt, arg);
return true;
}
public static void main(String[] args)
{ Frame f = new BounceThread();
f.resize(300, 200);
f.show();
}
private Canvas canvas;
}
class Ball extends Thread
{ public Ball(Canvas c) { box = c; }
public void draw()
{ Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move()
{ Graphics g = box.getGraphics();
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
y += dy;
Dimension d = box.size();
if (x < 0) { x = 0; dx = -dx; }
if (x + XSIZE >= d.width) { x = d.width - XSIZE; dx = -dx; }
if (y < 0) { y = 0; dy = -dy; }
if (y + YSIZE >= d.height) { y = d.height - YSIZE; dy = -dy; }
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void run()
{ draw();
for (int i = 1; i <= 1000; i++)
{ move();
try { Thread.sleep(5); } catch(InterruptedException e) {}
}
}
private Canvas box;
private static final int XSIZE = 10;
private static final int YSIZE = 10;
private int x = 0;
private int y = 0;
private int dx = 2;
private int dy = 2;
}
*** Bounce.java Sat Aug 17 16:18:22 1996
--- BounceThread.java Sat Aug 17 16:18:46 1996
***************
*** 26,34 ****
import java.awt.*;
! public class Bounce extends Frame
! { public Bounce()
! { setTitle("Bounce");
canvas = new Canvas();
add("Center", canvas);
Panel p = new Panel();
--- 26,34 ----
import java.awt.*;
! public class BounceThread extends Frame
! { public BounceThread()
! { setTitle("BounceThread");
canvas = new Canvas();
add("Center", canvas);
Panel p = new Panel();
***************
*** 45,51 ****
public boolean action(Event evt, Object arg)
{ if (arg.equals("Start"))
{ Ball b = new Ball(canvas);
! b.bounce();
}
else if (arg.equals("Close"))
System.exit(0);
--- 45,51 ----
public boolean action(Event evt, Object arg)
{ if (arg.equals("Start"))
{ Ball b = new Ball(canvas);
! b.start();
}
else if (arg.equals("Close"))
System.exit(0);
***************
*** 54,60 ****
}
public static void main(String[] args)
! { Frame f = new Bounce();
f.resize(300, 200);
f.show();
}
--- 54,60 ----
}
public static void main(String[] args)
! { Frame f = new BounceThread();
f.resize(300, 200);
f.show();
}
***************
*** 62,68 ****
private Canvas canvas;
}
! class Ball
{ public Ball(Canvas c) { box = c; }
public void draw()
--- 62,68 ----
private Canvas canvas;
}
! class Ball extends Thread
{ public Ball(Canvas c) { box = c; }
public void draw()
***************
*** 86,96 ****
g.dispose();
}
! public void bounce()
{ draw();
for (int i = 1; i <= 1000; i++)
{ move();
! try { Thread.sleep(10); } catch(InterruptedException e) {}
}
}
--- 86,96 ----
g.dispose();
}
! public void run()
{ draw();
for (int i = 1; i <= 1000; i++)
{ move();
! try { Thread.sleep(5); } catch(InterruptedException e) {}
}
}
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
/**
*
* A demonstration of Java Applet networking.
*
* @author David Purdue, SunSoft Pacific
* @version 1.0 12 Aug 96
* @see java.net.Socket
*/
public class RemoteDate extends Applet
{
private static final int DAYTIME_PORT = 13;
private String time_there;
public void init()
{
try
{
Socket sock
= new Socket(this.getCodeBase().getHost(), DAYTIME_PORT);
DataInputStream is = new DataInputStream(sock.getInputStream());
time_there = is.readLine();
sock.close();
}
catch (IOException e)
{
this.showStatus("Error: " + e);
}
}
public void paint(Graphics g)
{
g.drawString("The time at my server is " + time_there, 10, 30);
}
}
Return to Conference Proceedings