Writing Secure Enterprise Applications
Pages: 1, 2
Summary: Cross-site scripting vulnerabilities, frequently called XSS vulnerabilities, occur when a Web site displays on an HTML page without being properly filtered. This allows arbitrary HTML (that was entered by the user) to be displayed in the user's browser. This is perhaps best understood with an example.
The sample XSS Web page merely displays its input. Figure 1 shows the rendering of a simple HTML page when run with the URL http://myserver/myapp/XSSDemo?userInput=bar.
Figure 1: Sample output screen of an unfiltered HTML form
If you enter "foo" into the text box and press Submit, the page redraws with the word "bar" replaced with the word "foo" at the bottom. The source code for this page is:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>XSS Vulnerability Sample</title> </head> <body> <h1>XSS Vulnerability Sample</h1> <form method="GET" action="XSS.jsp"> Enter string here: <input type="text" name="userInput" size=50> <input type=submit value="Submit"> </form> <br> <hr> <br> Output from last command: <%= request.getParameter("userInput")%> </body> </html>
Now consider what will happen if the following text is submitted via the text box:
alert("If you see this you have a potential XSS vulnerability!");
Figure 2: The result of not filtering input is an XSS vulnerability
Figure 2 shows the (surprising) output. As you will notice, the small script that was entered is executed in the browser.
Examples: This is probably the most common Web vulnerability. In general, if you write a Web site and do not understand and actively try to prevent XSS vulnerabilities, then your site almost certainly has them.
Prevention: To prevent XSS vulnerabilities, all user input must be escaped before being output to the browser. Typically this involves converting special characters to HTML escapes—for example, converting "<" to "<". You can find a great deal of documentation about this on the Web, for example at CERT's Coordination Center.
Summary: Unless careful attention is paid to error handling, partial execution of operations can occur when an error is detected. This can frequently lead to an incorrect security operation. A second way in which errors can lead to vulnerabilities is by exposing sensitive information. In Java, sensitive information frequently is exposed by displaying the stack trace and exception message. This can contain information about the program internals. One specific case worth mentioning is that if error text is displayed, it must be escaped to prevent XSS vulnerabilities if the user can control any part of the text being displayed. For example, the message "User 'joe' not found." is an XSS vulnerability unless the username is escaped.
Typical Attacks: Attackers, through knowledge of a Web site, identify places where errors are improperly handled and try to exploit them. The exact exploitation depends on the exact form of the vulnerability. Attackers can write tools to help various illegal inputs look for these vulnerabilities.
One interesting note is that frequently these vulnerabilities can be "accidentally exploited." That is, a non-malicious user unintentionally performs an incorrect operation and would really like to get an appropriate error message but instead executes part or all of the operation. One can imagine this leading to problems such as negative bank account balances.
Examples: Many documented cases of error-handling vulnerabilities exist. A typical case occurred in Bugzilla where, when the database was not available, the error page printed the database username and password. If the user got direct access to the database, the username and password could have been used to bypass Bugzilla's security (find the details here).
A variant of improper error handling occurred in BEA's WebLogic Server. When users attempted to modify the JNDI tree without proper permission, they received an error. But sometimes the operation succeeded (see the security advisory for details). This problem was introduced during a bug fix in the code. Initially the code was secure, performing an access check, generating an error if denied, and then performing the JNDI modification. Someone noticed that there was a bug when the JNDI tree that was being modified was empty and added a special case into the method, before the access check. The introduction of vulnerabilities of this form is common and demonstrates the need for continued security vigilance throughout all phases of development.
Prevention: As briefly touched on earlier, all error messages should be carefully examined for XSS vulnerabilities and properly escaped when needed. Furthermore, error checking should occur early in all operations. When the error is detected the operation should be terminated. Beware of swallowing exceptions.
Summary: On-disk or in-memory artifacts containing confidential data, when improperly secured, can be obtained and used by attackers. Frequently this involves insecure passwords, caches, and configurations.
Typical Attacks: Attacks frequently occur on the server machine where on-disk or in-memory artifacts are accessed. This can be done either by a valid user on the server machine (most cybercrime is perpetrated by insiders) or when an attacker gains access to the server machine through an OS vulnerability. On the client, a process's memory frequently can be accessed via a core dump or a debugger. A user's cookies are also stored on disk and frequently can be accessed.
Examples: phpAnyVote, a survey/voting program, had an interesting storage problem. phpAnyVote works by allowing people to vote on specific issues; each user can vote only once. The single-vote semantics are implemented by storing the user's name in a cookie on the browser and then ensuring that the user has not voted before. A knowledgeable user can modify the cookie to another value and therefore impersonate another user, thereby allowing multiple votes. This SecurityFocus article describes this in more detail.
Prevention: Use encryption and signing as needed. Signing ensures that data has not been tampered with, and encryption ensures both confidentiality and tamper resistance. In the phpAnyVote example, signing the username with a secret key or encrypting it would have ensured that the user could not easily modify it. Especially on the server, try to utilize OS security (for example, to protect access to files). In general, examine all artifacts for security requirements and apply protections as appropriate.
Summary: User input, when not properly validated, normalized, or escaped, and passed to a back-end program such as a database, can allow an attacker to perform arbitrary operations. This is very similar to XSS vulnerabilities but, in XSS, the user input is passed to the browser while in this case it is passed to a back-end program.
Typical Attacks: By far the most common example of this attack is SQL injection. Googling "sql injection flaw vulnerability" returns nearly 33,000 hits. SQL injection occurs when unescaped user input is passed to a SQL call allowing the user input to contain arbitrary SQL commands. Imagine a Web site that asks for a search string and then searches in the database for it. Knowledge about the database and its syntax typically are required to successfully execute this attack.
Examples: One of the many SQL injection flaws occurred in Microsoft's SQL Server. SQL Server comes with several stored procedures, and two of these allowed SQL injection to occur under certain database configurations. The vulnerabilities allowed arbitrary SQL queries and the execution of arbitrary OS commands. For more details, read the US-CERT article.
Prevention: As with XSS vulnerabilities, care must be taken when handling user data. Data should be normalized (for example, remove %XX and \0xx escapes) and examined for validity. Invalid inputs might contain illegal characters such as embedded nulls or illegal path components such as "../". When discovered, illegal inputs should generate an error. Err on the side of being overly restrictive and possibly rejecting some valid user inputs, rather than insufficiently restrictive and possibly allowing some injection flaw vulnerabilities.
Summary: A denial of service (DOS) vulnerability renders a Web site inaccessible or unusable. This can occur in many different ways but frequently includes attacks that cause the site to crash, reject connections, or perform too slowly to be usable. DOS attacks come in two forms. Distributed denial of service (DDOS) vulnerabilities require many computers to execute, while basic DOS attacks require only one or a few computers.
Typical Attacks: Typical DDOS attacks try to overwhelm the network with too much activity. These are exceedingly difficult to protect against. Even if your Web site is incredibly robust, with enough traffic there is always a weak link— if not your site, then perhaps your routers, firewalls, ISP, name server, and so on.
Examples: The IBM Lotus Domino server had a vulnerability that typifies a basic DOS attack. In this attack some incomplete requests sent to the server would cause the server to hang, requiring a reboot. A single user can bring down the server with ease.
One of the more interesting basic DOS attacks is known as the "smurf" attack. This attack relies on the Internet Control Message Protocol (ICMP) "echo" command. This is the command that is used by the "ping" program. The echo command takes as an argument the address to send the response to. ICMP allows you to specify not only a machine but also a subnet in which case it will send to all machines on that subnet. The smurf attack works by sending echo commands to hosts specifying subnets as the reply address. For every host you send the echo commands to, that host will generate multiple responses (one per machine on the subnet). This allows a single attacking machine to generate large amounts of network traffic and thereby drive the target network to a standstill.
Prevention: The first line of defense has to come from your platform software. BEA WebLogic Server has several options for controlling how it protects against DOS attacks. These are documented in the lockdown document. Search for "denial of service" to find the exact location. Ensure that other pieces of your platform including Web servers, firewalls, and databases are configured for maximum protection as well.
The second line of defense comes from careful application processing. Ensure that all code that reads from user input streams (for example, files entered by the user, form fields, sockets) have careful error checking. Most basic DOS attacks are bugs in the system (frequently improper error handling). Taking care around places that process user input can dramatically increase the robustness of your application.
This article has demonstrated a number of security vulnerabilities and how you can avoid them. As these vulnerabilities demonstrate, security issues pervade all aspects of a Web site, from the HTML to the back-end server. To develop a secure Web site, make sure you discuss security issues from the beginning of the requirement process through the design, implementation, and deployment. Do not consider security as an afterthought. Should your Web site have configuration options that affect security, ensure that they are configured appropriately. Protect your on-disk and in-memory data. Never trust the client. Always assume that the client is actually an attacker and ensure that you validate all incoming data. Finally, and perhaps most important, create, document, and enforce appropriate security processes.
Neil Smithline has implemented and architected several J2EE applications. His current role as BEA WebLogic Server security architect, exposes him to all aspects of application security.