|
|
|||
|
|
|
|
|
|
Chapter 28Accessing Remote Systems Securelyby Mark Wutka
The huge explosion of Internet access is both a blessing and a curse to businesses on the Net. Because Internet data passes over insecure networks, a company must be extremely careful when passing sensitive data over the Internet. In the past, it was difficult for companies to communicate with their employees out in the field, because networking technology was fairly primitive, and laptop computers were not very portable, or too powerful. This was especially a problem for sales force automation. A salesman may be on the road for weeks or months at a time, unable to communicate with the home base. Figure 28.1 illustrates the old design of a sales force automation network. Figure 28.1 : In the past, companies had to create their own sales force automation networks. Now, laptop computers are extremely powerful with a wide range of networking options, and Internet access is available all over the world. Figure 28.2 shows how the Internet has changed the environment for sales force automation. Figure 28.2 : The widespread availability of the Internet eliminates the need for custom networks. It seems like things should be easier for people on the road, and it is for people at some companies. For others, things haven't gotten any better. The irony here is that it is still just as difficult to access secure data over the Net. The widespread infiltration of the Internet, which makes it easier for employees to communicate back to their home system, also increases the likelihood that the data can be intercepted. A devious spy from another company could snoop on private data transmissions over the Internet. In addition, many companies have custom software that must be adapted to work over the Net. Whenever the software is updated, it is very difficult to distribute the new versions to the people in the field. The company must either ship new diskettes, ship out a new laptop, wait until the salesperson is back in the office, or download software over the network. The latter is a very difficult endeavor, most often meeting with failure. Java can help solve the distribution problem. With Java, you can either write the custom software as applets, which can be cached on the local hard drive (as shown in Figure 28.3), or create a software distribution applet that downloads new versions of the local applications, as shown in Figure 28.4. A digitally signed applet can download updates to the local software, as well as update any information stored on the local hard disk. Figure 28.4 : A custom software installation applet can also assist in software installation. You still have the problem of downloading important information without someone intercepting the information. The Secure Socket Layer (SSL) protocol enables you to access Web pages securely. SSL uses a combination of a digitally signed certificate and an encrypted network session. Getting a Secure Web ServerIf you want to use SSL to download your applets, you must get a Web server that supports the SSL protocol. Netscape Communications (http://home.netscape.com) has a whole line of Web servers, all of which support the SSL protocol. The secure Web server from Open Market Systems (http://www.openmarket.com) also supports SSL.
There is also a version of the Apache Web server that supports
SSL. If you are within the United States, you can download the
Apache-SSL Web server from Community Connexion, Inc. (http://www.c2.org).
Apache-SSL is free for non-commercial use. If you want to use
it for commercial purposes, you must buy a license from C2.
Once you get a secure Web server, you must also get a digitally signed certificate in order to use SSL. There are several certificate authorities around, one of which is Verisign (http://www.verisign.com). One of the nice things about the Apache-SSL server is that it will generate a local certificate that you can use for testing. You must still obtain a signed certificate if you want someone else to access your Web server securely. Preventing ImpersonationsThe Secure Socket Layer, or another secure form of HTTP, is vital in downloading applets securely. When you download one of your company's applets, you must to be sure that it really came from your company. The digital signature mechanism warns you if you download an unsigned applet, which prevents all but the most devious impersonation attacks. If someone is able to digitally sign an applet with a signature you think is valid, you will not know anything is wrong. Of course, if this happens, it means that you have trusted someone you shouldn't have. Chapter 26, "Securing Applets with Digital Signatures," contains more information about digital signatures and their relationship to applets. If you use SSL to download your applet, it cannot be impersonated, because SSL ensures that you are talking to the correct Web server. Accessing Remote DataYou can use SSL to send and receive encrypted data without using any encryption software yourself. The URL class enables you to open up URLs with an https protocol type, which uses SSL for communications. Because of the way the applet security manager works, you cannot intermix http and https URL accesses in a single applet. If your applet was loaded using the http protocol type, you can open URLs only with a protocol type of http. If your applet was downloaded via https, you can open URLs only with a protocol type of https. What the restriction means is that if you need to download information securely, you must also download the applet securely. It is one of the simple ways that Java protects you from yourself. If you were allowed to download applets insecurely and then download information securely, you would be vulnerable to an impersonation attack. Since the SSL support is built into the URL class (actually, into the browser itself), you can use the methods discussed in Chapter 6 "Communicating with a Web Server," to store and retrieve files using the URL class. You cannot use any of the socket mechanisms to do this, however. Passing Keys to ClientsOne of the difficulties in performing encrypted communications is agreeing on an encryption key. You have to have a secure way to even agree on a key; otherwise, someone could just eavesdrop on your key exchange and see what key you're using. Don't Reuse Symmetric KeysYou might be tempted to generate a nice key for symmetric key encryption and let all your applets use that key. Unless you have a foolproof method of ensuring that only trustworthy people can get your applet (which is easier said than done), you run the risk of a malicious person downloading your applet and examining it to find the key you're using. It should be obvious that just using SSL doesn't prevent someone from stealing your key. SSL only prevents someone from impersonating your server, and from watching your applet being downloaded (since the download is encrypted). The amount of risk involved in reusing a symmetric key isn't worth the trouble. Using Public Key Encryption to Get a Private KeyPublic key encryption is generally very costly. You would not want to carry on an interactive session using public key encryption. Public keys are very handy for exchanging a private key, however. Suppose you had a client and a server connected together using an insecure TCP/IP socket, as shown in Figure 28.5. Figure 28.5 : A client connects to a server using an insecure socket. Next, the client generates a random private encryption key. The client then encrypts the private key using the server's public encryption key and passes the encrypted key to the server, as shown in Figure 28.6. Figure 28.6 : The client encrypts a private key using the server's public key. Now, the server can decrypt the private session key and the two can use the private key to exchange data. It is safe for you to embed the server's public key in the client applet, because even if someone looked at it, they wouldn't learn anything that isn't already public knowledge. Because each session key is randomly generated, no one else can figure out your session key just by downloading the applet. Anyone who did so would just generate a different key. Passing a Private Key as an Applet ParameterBecause you are using secure sockets to download your applet, you can take advantage of the fact that the applet and its parent Web page are transmitted in encrypted form. Instead of the client generating the session key and using public key encryption to pass the session key to the server, the server can pass the key to the client applet using the <PARAM> tag.
This mechanism has some peculiar drawbacks to it, stemming from
the fact that you must use CGI (or its equivalent) to pass the
key information back. If you are lucky enough to have a Java Web
server that also does SSL, you don't have to worry about this.
Unfortunately, since many, if not all, of the current Java Web
servers do not support SSL, you have to come up with some unique
ways of passing keys around.
The problem here is that a CGI program is supposed to generate content in response to a GET or a POST and then exit. Figure 28.7 illustrates the typical life of a CGI program. Unfortunately, since the response isn't sent back to the client until the CGI program terminates, by the time the client receives the random private session key, the program that generated the key is gone. There are a number of ways you can solve this problem. One way is to have your CGI program start up another program that also knows the session key. Once the client knows the session key, it connects to the program started by the CGI program. Figure 28.8 illustrates this sequence. Figure 28.8 : A CGI program can spawn another program that communicates securely with the client. This solution may be fine for some situations, but it has a number of drawbacks:
Another solution is a bit less taxing on the system resources, but is harder to implement. In this solution, the server is a program that is already running, in the same way that the Web server is always running. When a CGI program starts up, it requests a new session key from the server and then passes the key to the client. The server then listens for an incoming connection. Figure 28.9 illustrates this relationship. Figure 28.9 : The CGI program gets a key from the server, which was already running. This architecture has some advantages over the previous one:
Implementing a Single-Client Secure ServerIf you need something more than a simple http GET or POST interface and you need encryption, you'll probably have to settle on a socket connection. If you can find a CORBA or RMI implementation that supports encryption, that would be much better. For a single-client secure server, you need a CGI program that invokes your server program. Since most server programs have a number of similar features, it makes sense to create an abstract class that handles many of the common features. The SingleSecureServer class, shown in Listing 28.1, implements a number of useful methods for creating a single-client secure server. The server expects to be started by a CGI program, and passes the port number it is listening on and the secure session key back to the CGI program as output. Listing 28.1 Source Code for SingleSecureServer.java
All your CGI program needs to do is start the server program, read two lines, and generate an HTML page that tells the requesting browser where to get the applet. While you could write the CGI program in any language you choose, Java seems like the ideal choice for this book. Listing 28.2 shows a CGI program that starts up a secure telnet server. This server uses an excellent Java Telnet applet written by Bret Dahlgren. The source code to the applet can be found on the World Wide Web at http://w3.gwis. com/~thorn/telnet/. In order to support secure telnet sessions, the Telnet application had to be modified slightly. It now supports a sessionKey parameter which, if present, tells it to use encryption for the session. The encryption used is DES3, provided by the Acme cryptography library. Listing 28.2 Source Code for SecureLoginStartup.java
Listing 28.3 shows the HTML information generated by this CGI program: Listing 28.3 Output from SecureLoginStartup Content-type: text/html Content-length: 378 <HTML><HEAD> <TITLE> Secure Login Session </TITLE> <BODY> <H1>Secure Login</H1> <APPLET codebase="/classes" code="Telnet.class" width=600 height=400> <PARAM name="fields" value="off"> <PARAM name="host" value="flamingo"> <PARAM name="port" value="1126"> <PARAM name="sessionKey" value="8b4243347b3a69b8aa12594153c15c8c"> You need Java for secure logins. </APPLET> </BODY></HTML> The CGI program is started by a small shell script that sets the Java CLASSPATH variable before running: #!/bin/sh export CLASSPATH=/usr/local/etc/httpd/htdocs/classes:/usr/local/java/lib/classes.zip /usr/local/java/bin/java SecureLoginStartup The startup sequence for the secure Telnet applet is as follows:
The class that actually creates the telnet connection and passes the information back and forth to the encryption routines is shown in Listing 28.4. It is fairly short. Essentially, it creates the telnet connection, and then uses a simple bridging class to link two streams together. Listing 28.4 Source Code for SecureLoginClient.java
The SecureLoginServer class,
which is a subclass of SingleSecureServer,
does little more than create a session key and create the SecureLoginClient
to handle the client connection. Most subclasses of SingleSecureServer
will probably be this simple. Listing 28.5 shows the SecureLoginServer
class.
Listing 28.5 Source Code for SecureLoginServer.java
Finally, the bridging mechanism to link two streams together is
very simple. The StreamBridge
class, shown in Listing 28.6, sets up a thread and constantly
reads data from one stream and writes it to another. It can operate
in either block mode or single character mode. The single character
mode is necessary for the encryption streams, because if you do
a block mode read on the encryption stream, it won't return until
it fills the entire block. You don't necessarily want it that
way.
Listing 28.6 Source Code for StreamBridge.java
You can use this same framework to implement other secure protocols. For example, you could use the POP3 and SMTP classes from Chapter 11, "Sending E-Mail from an Applet," and create a secure mail system. This framework is essentially the "Poor Man's SSL." It uses SSL to get the initial setup information back and forth, and then uses other encryption for the rest of the session. Implementing a Multiclient Secure ServerIf you want to implement a secure server that handles multiple simultaneous sessions, you have to do a little more work. As it turns out, however, if you are careful in the design of your single-client server, you can reuse large amounts of it. The difference between the single-client and multiclient approach is that the multiclient server is always running, whereas the single-client server is spawned by the CGI program. The interesting thing here is that the CGI program has to communicate with both servers in a similar way. It needs to know the port number and session key regardless of the type of server implementation. Similarities like this are usually an indication that there may be some code reuse brewing somewhere. For a multiclient server, your CGI program can use a socket connection to get the port number and session key. Since the SingleSecureServer is already set up to run as a thread, it is ridiculously simple to make a multiclient server that just spawns new instances of a SingleSecureServer every time a CGI program connects to it. It's ridiculously simple now, but it wasn't in the first design of the SingleSecureServer. Originally, the SingleSecureServer didn't run as a thread. Its run method was called something else, and it didn't implement Runnable. When it came time to create a multiclient server, I realized that it took only a few changes to adapt the single-client server so it could run either way. This is what I call "reuse by re-engineering." Sometimes, you go to design a new system and discover that there is another class that almost works for you, but not quite. With a little change, the class could do what you need and still perform its previous functions. You run the risk of introducing bugs back into the original system, but it surely beats having to keep two copies of almost identical code. As you make these small design changes, try to make a note of what you had to change. Not necessarily a detailed description, but a general one. You will start to see common themes-design strategies that you have taken in the past that inhibit code reuse. The next time you design a class, keep those previous problems in mind, and maybe your class will not need to be changed. This accumulated knowledge is what really makes a good object-oriented designer. To support multiple simultaneous clients using the SingleSecureServer framework, you need a server that listens for socket connections from the CGI program and then spawns new SingleSecureServer threads. Listing 28.7 shows the MultiLoginServer class that does this. Listing 28.7 Source Code for MultiLoginServer.java
Finally, the CGI program that connects to the multiclient server is similar to the single-client CGI program. The only difference between the two programs is in their main methods. This being the case, it makes sense to just create a subclass of the single-client CGI program and create a new main. Listing 28.8 shows the multiclient CGI program. Listing 28.8 Source Code for MultiLoginStartup.java
Creating Other Secure Remote Access ProgramsYou can use the SingleSecureServer class as a framework for implementing other secure remote access programs. Frankly, this solution is not the optimal one, because you have to work on the socket level. With RMI and CORBA available in Java, you shouldn't have to open up raw sockets for simple communications. They are still useful when you need to grab a large chunk of raw data, but for passing messages back and forth, sockets are a step backwards. Be on the lookout for an ORB product that supports secure communications. If there isn't one now, there should be soon. Security is a growing issue on the Internet. |
|
|
|