Home > Articles > Security > General Security and Privacy

  • Print
  • + Share This
  • 💬 Discuss

Web Application Attacks

Now that we understand how the frequently exploited buffer overflow and password-cracking attacks operate, let's turn our attention to a class of attacks that is rapidly growing in prominence: World Wide Web application exploits. More and more organizations are placing applications on the Internet for all kinds of services, including electronic commerce, trading, information retrieval, voting, government services, and so on. New applications are being built with native Web support, and legacy applications are being upgraded with fancy new Web front ends. As we "webify" our world, the Web has proven to be a particularly fruitful area for attackers to exploit.

In my investigations of a large number of Web sites, I have frequently encountered Web applications that are subject to account harvesting, undermining session tracking mechanisms, and SQL injection. The concepts behind these vulnerabilities are not inherently Web-specific, as these same problems have plagued all kinds of applications for decades. However, because Web applications seem particularly prone to these types of errors, it is important to understand these attacks and defend against them.

All of the Web attack techniques described in this section can be conducted even if the Web server uses the SSL protocol. So often, I hear someone say, "Sure, our Web application is secure ... we use SSL!" SSL can indeed help by strongly authenticating the Web server to the browser and preventing an attacker from intercepting traffic, when it is used properly. In other words, SSL supports authentication, and protects data in transit. You should definitely employ SSL to protect your Web application. However, SSL doesn't do the whole job of protecting a Web application. There are still a large number of attacks that function perfectly well over an SSL-encrypted connection. When the data is located in the browser, SSL doesn't prevent changes to that data by the person sitting at the browser. If an attacker is browsing your Web application, he or she might just change some crucial data in the browser. If your Web application trusts whatever comes back, the bad guy might be able to undermine your Web application completely. Remember, the browser is potentially enemy territory, with an attacker sitting at its controls, so you can't trust what comes back from it unless you explicitly validate that data. Let's look at such attacks in more detail, starting with account harvesting.

Account Harvesting

Account harvesting is a good example of a technique that has been applied to all kinds of systems for decades, but now seems to be a particular problem with Web applications. Using this technique, an attacker can determine legitimate user IDs and even passwords of a vulnerable application. Account harvesting is really a simple concept, targeting the authentication process when an application requests a user ID and password. The technique works against applications that have a different error message for users who type in an incorrect user ID than for users who type a correct user ID with an incorrect password.

Consider the error message screens for the application shown in Figure 7.27 and Figure 7.28. These screens are from a proprietary Web application called Mock Bank, written by Arion Lawrence, a brilliant colleague of mine. We use Mock Bank internally to show common real-world problems with Web applications to our clients, as well as to train new employees in the methods of ethical hacking. The first screen shows what happens when a user types in a wrong user ID, and the second shows the output from a correct user ID and an incorrect password. The actual HTML and appearance of the browser in both pages are identical. However, look at the location line in the browser of each figure a bit more closely. Notice that when the user ID is incorrect, error number 1 is returned, as in Figure 7.27. When the user ID is valid and the password is wrong, error number 2 is returned, as in Figure 7.28. This discrepancy is exactly what an attacker looks for when harvesting accounts.

Figure 7.27

Figure 7.27 Mock Bank's error message when a nonvalid (i.e., bad) user ID is entered.

Figure 7.28

Figure 7.28 Mock Bank's error message when a valid (i.e., good) user ID is entered with a bad password. Note the change in the URL error number parameter.

Based on this difference in error messages in the URL, an attacker can write a custom script to interact with the Web application, conducting a dictionary or brute-force attack guessing all possible user IDs, and using an obviously false password (such as zzzzz). The script will try each possible user ID. If an error message is returned indicating that the user ID is valid, the attacker's script writes the user ID to a file. Otherwise, the next guess is tested. This is pure user ID guessing through scripting, adding a bit of intelligence to discriminate between invalid and valid user IDs. In this way, an attacker can harvest a large number of valid user IDs from the target application. In this Mock Bank example, the parameter called error is the differentiating point between the two conditions. Of course, any element of the returned Web page, including the HTML itself, comments in the HTML, hidden form elements, cookies, or anything else, could be the differentiator between the bad user ID and good user ID conditions. The attacker will choose a suitable differentiating point to include in the logic check of the login attack script.

After running a script to harvest good user IDs, the attacker can try to harvest passwords. If the target application doesn't lock out user accounts due to a given number of invalid password attempts, the attacker can write another script or use the Brutus or Hydra tools we discussed earlier in this chapter to try password guessing across the network. The attacker takes the user IDs previously harvested and tries guessing all passwords for that account using login scripting. If the target application does lock out accounts, the attacker can easily conduct a DoS attack using the harvested user ID information.

Account Harvesting Defenses

For all of your Web applications (or any other application, for that matter), you must make sure that you use a consistent error message when a user types in an incorrect user ID or password. Rather than telling the user, "Your user ID was incorrect," or "Your password was incorrect," your application should contain a single error message for improper authentication information. You could display a message saying, "Your user ID or password was incorrect. Please enter them again, or call the help desk." Note that all accompanying information sent back to the browser must be completely consistent for the two scenarios, including the raw HTML, URL displayed in the browser, cookies, and any hidden form elements. Even a single space or period that is different between the two authentication error conditions could tip off an attacker's script.

Undermining Web Application Session Tracking and Other Variables

Another technique commonly used to attack Web applications deals with undermining the mechanisms used by the Web application to track user actions. After a user authenticates to a Web application (by providing a user ID and password, or through a client-side certificate on an HTTPS session), most Web applications generate a session ID to track the user's actions for the rest of the browsing session of that site. The Web application generates a session ID and passes it to the client's browser, essentially saying, "Here, hold this now and give it back to me every time you send another request for the rest of this session." This session ID is passed back and forth across the HTTP or HTTPS connection for all subsequent interactions that are part of the session, such as browsing Web pages, entering data into forms, or conducting transactions. The application uses this information to track who is submitting the request. In essence, the session ID allows the Web application to maintain the state of a session with a user.

Note that a session ID can have any name the application developer or the development environment used to create the Web application assigned to it. It does not have to be called sessionID, sid, or anything else in particular. A Web application developer could call the variable Joe, but it would still be used to track the user through a series of interactions.

Furthermore, a session ID is completely independent of the SSL connection in the vast majority of applications. The session ID is application-level data, generated by the application and exchanged by the Web browser and Web server. Although it is encrypted by SSL as it moves across the network, the session ID can be altered at the browser by the browser user without impacting the underlying SSL connection.

Implementing Session IDs in Web Applications

So how do Web applications implement session IDs? Three of the most popular techniques for transmitting session IDs are URL session tracking, hidden form elements, and cookies. For URL session tracking, the session ID is written right on the browser's location line, as shown in Figure 7.29, and passed as a parameter in an HTTP GET request. For all subsequent Web requests, the URL is passed back to the server, which can read the session ID from this HTTP field and determine who submitted the request.

Figure 7.29

Figure 7.29 Session tracking using the URL.

A second technique for tracking session IDs involves putting the session ID information into the HTML itself, using hidden form elements. With this technique, the Web application sends the browser an HTML form with elements that are labeled as hidden. One of these form elements includes the session ID. When it displays the Web page, the browser does not show the user these hidden elements, but the user can readily see them simply by invoking the browser's view source function for the page. In the raw HTML, a hidden form element will have the following appearance:

<INPUT TYPE="HIDDEN" NAME="Session" VALUE="34112323">

Cookies are the most widely used session tracking mechanisms. A cookie is simply an HTTP field that the browser stores on behalf of a Web server. A cookie contains whatever data the server wants to put into it, which could include user preferences, reference data, or a session ID. There are two types of cookies: persistent cookies and nonpersistent cookies. A persistent cookie is written to the local file system when the browser is closed, and will be read the next time the browser is executed. Persistent cookies, therefore, are most often used to store long-term user preferences. A nonpersistent cookie, on the other hand, is stored in the browser's memory and is deleted when the browser is closed. This type of cookie has a short but useful life, and is often used to implement session IDs.

Attacking Session Tracking Mechanisms

Many Web-based applications have vulnerabilities in properly allocating and controlling these session IDs. An attacker might be able to establish a session, get assigned a session ID, and alter the session ID in real time. For applications that don't handle session tracking properly, if the attacker changes the session ID to a value currently assigned to another user, the application will think the attacker's session belongs to that other user! In this way, the attacker usurps the legitimate user's session ID, a process sometimes referred to as session cloning. As far as the application is concerned, the attacker becomes the other user. Of course, both the legitimate user and the attacker are using the same session ID at the same time. Still, many Web-based applications won't even notice this problem, accepting and processing transactions from both the attacker and the legitimate user.

In fact, it's pretty hard for an application to even figure out that this has happened. Suppose the application associates a session ID number with the IP address of the user. Well, there's a problem in that many users might be surfing from behind a single proxy or a many-to-one dynamic NAT device, so all such users will have the same apparent IP address. One user on the other side of the proxy could still clone the session of another user of the proxy. Furthermore, trying to nail the session ID to the IP address is bad because sometimes a user who surfs through a large ISP will have a changed apparent source IP address, right in the middle of a surfing session! Because of some complex routing and proxying that some ISPs perform, a completely legitimate user might get a different IP address in real time. Web applications that check session credentials against the IP addresses would think that such users are really being attacked, when they aren't. They were just given a different IP address.

An application with predictable session credentials allows an attacker to do anything a legitimate user can do. In an online banking application, the attacker could transfer funds or possibly write online checks. For online stock trading, the attacker could make trades on behalf of the user. For an online health care application ... well, you get the idea.

To perform this kind of attack, the bad guy first needs to determine another user's session ID. To accomplish this, the attacker logs in to the application using a legitimate account assigned to the attacker, and observes the session ID assigned to that session. The attacker looks at how long the session ID is and the types of characters (numeric, alphabetic, or others) that make it up. The attacker then writes a script to log in again and again, gathering hundreds of session IDs to determine how they change over time or to see if they are related in any way to the user ID. Then, applying some statistical analysis to the sampled session IDs, the attacker attempts to predict session IDs that belong to other users.

So how does an attacker actually manipulate the session ID? First, the attacker logs in to the application using his or her own account to be assigned a session ID. Then, the attacker attempts to modify this session ID to clone the session of another user. For many session tracking mechanisms, such modifications are trivial. With URL session tracking, the attacker simply types over the session ID in the URL line of the browser. If hidden form elements are used to track sessions, the attacker can save the Web page sent by the server to the local file system. The attacker then edits the session ID in the hidden form elements of the local copy of the Web page, and reloads the local page into the browser. By simply submitting the form back to the server, the attacker can send the new session ID and could clone another user's session.

If sessions are tracked using persistent cookies, the attacker can simply edit the local cookie file. In Mozilla Firefox and Netscape browsers, all persistent cookies are stored in a single file called cookies.txt. For Internet Explorer, cookies from different servers are stored in their own individual files in the Temporary Internet Files directory for each user. An attacker can edit these persistent cookies using any text editor, as shown in Figure 7.30. To exploit a session ID based on a persistent cookie, the attacker can log in to the application to get a session ID, close the browser to write the cookie file, edit the cookies using his or her favorite text editor, and relaunch the browser, now using the new session ID. The browser must be closed and relaunched during this process because persistent cookies are only written and read when the browser is closed and launched.

Figure 7.30

Figure 7.30 Editing nonpersistent cookies using Notepad.

Editing persistent cookies is trivial. But how can an attacker edit nonpersistent cookies, which are stored in the browser's memory and are not written to the local file system? Many Web application developers just assume that a user cannot view or alter nonpersistent cookies, especially those passed via SSL, so they don't bother worrying about protecting the information stored in such cookies. Unfortunately, bad guys use very powerful techniques for altering nonpersistent cookies.

To accomplish this feat, Web application attackers most often rely on a specialized Web proxy tool designed to manipulate Web applications. A Web application manipulation proxy sits between the browser and the server, as shown in Figure 7.31. All HTTP and HTTPS gets channeled through the proxy, which gives the attacker a window to view and alter all of the information passed in the browsing session, including nonpersistent cookies. Thus, the bad guy has a very fine-grained level at which to modify any cookies that are passing by. What's more, these specialized proxies let the attacker edit any raw HTTP/HTTPS fields and HTML information including cookies, hidden form elements, URLs, frame definitions, and so on.

Figure 7.31

Figure 7.31 A Web application manipulation proxy lets the attacker alter the HTTP and HTTPS elements passing through it, including nonpersistent cookies.

It is crucial to note that these Web application manipulation attacks are not person-in-the-middle attacks where a bad guy changes another user's data going to the application. In these Web application manipulation attacks, the bad guy controls both the browser and the proxy. Attackers use the proxy to alter their own data going to and from the Web application, including session ID numbers and other variables. That way, any victim Web server that trusts the information that comes from the browser will be tricked. The attacker applies the browser and Web application manipulation proxy in tandem: The browser browses, while the proxy lets the attacker change the elements inside the HTTP and HTML itself.

Because this proxy concept is so powerful in attacking Web applications, various security developers have released a large number of these Web application manipulation proxies, both on a free and a commercial basis. Table 7.2 shows some of the most useful Web application manipulation proxies, as well as their claims to fame.

Table 7.2. Web Application Manipulation Proxies

Tool Name

Licensing Terms


Claim to Fame





First to be released and easiest to use


Paros Proxy



Incredibly feature rich; my favorite among the free tools


TCP Relay



Supports HTTP/HTTPS and any other TCP protocol





Free, open source, and actively updated, with a modular interface for adding new tools and features


SPI Dynamics SPIProxy/



Records browsing and then automates attacks, integrates with other SPI Dynamics tools


Web Sleuth



Excellent filtering capabilities


To launch this kind of attack, the bad guy runs the browser and the Web application manipulation proxy, either on separate systems or on a single machine. To get a feel for how these tools work, let's look at the one with the simplest user interface, Achilles, which is shown in Figure 7.32. In the main Achilles window, all information from the HTTP or HTTPS session is displayed for the attacker to view. When the browser or server sends data, Achilles intercepts it, allowing it to be edited before passing it on. In this way, Achilles pauses the browsing session, giving the attacker a chance to alter it. The attacker can simply point to and click any information in this session in the main window and type right over it. The attacker then clicks the Send button, which transfers the data from Achilles to the server or browser.

Figure 7.32

Figure 7.32 The Achilles screen, one of the easiest to use Web application manipulation proxies.

Most Web application manipulation proxies support HTTPS connections, which are really just HTTP connections protected using SSL. To accomplish this, as displayed in Figure 7.33, the proxy sets up two SSL connections: one session between the browser and the proxy, and the other between the proxy and the Web server. All data is encrypted at the browser and sent to the proxy. At the proxy, the data is decrypted and displayed to the attacker, letting the bad guy alter it. Then, the data is encrypted across another, separate SSL session and sent to the victim Web server. When a response is served up by the server, the same process is applied in the opposite direction. Most of the proxies even come with a built-in digital certificate for server-side SSL to establish the connection with the Web browser. The Web server never knows that there is a proxy in the connection. The attacker's browser might display a warning message saying that the certificate from the server isn't signed by a trusted certificate authority, because the proxy inserts its own certificate in place of the Web server's certificate. However, the attacker is running both the browser and the proxy, so the warning message can be ignored by the attacker.

Figure 7.33

Figure 7.33 Handling HTTPS (that is, HTTP over SSL) with a Web application manipulation proxy.

Although Achilles is the easiest to use of the Web application manipulation proxies, it isn't the most powerful. My current favorite Web application manipulation proxy is Paros Proxy, shown in Figure 7.34. Originally developed by the fine folks at ProofSecure, the Paros proxy maintains an excellent history of all HTTP requests and responses as the attacker surfs a given site through the proxy. Later, the attacker can review all of the action, with every page, variable, and other element recorded. Further, in addition to supporting server-side SSL, like most of the Web application manipulation proxies already do, Paros also allows its user to import a client-side SSL certificate that can be used to authenticate to a Web site that requires a client certificate. This client-side support is a strong differentiator among the free tools. Paros also features a built-in automated Paroweb spider that can surf to every linked page on a target Web site, storing its HTML locally for later inspection, all the while harvesting URLs, cookies, and hidden form elements for later attack.

Figure 7.34

Figure 7.34 The Paros Proxy is one of the best freely available Web application manipulation proxies.

Another nice touch in Paros is a built-in point-and-click tool for calculating the SHA1, MD5, and Base64 value of any arbitrary text typed in by its user or pasted in from the application. When attacking Web applications, the attacker sometimes has a hunch about the encoding or hashing of a specific data element that is returned. Using this calculator, the attacker can quickly and easily test such hunches. The tool also includes automated vulnerability scanning and detection capabilities for some of the most common Web application attacks, including SQL injection, an issue we discuss later in this chapter. Finally, the Paros find and filter features let an attacker focus on specific aspects of the target Web application, such as certain cookie names, HTTP request types, or other features. What a great tool!

As we've seen, an attacker can modify session credentials using these Web application manipulation proxies, but session credentials only scratch the surface. Many Web applications send a great deal of additional variables to the browser for temporary or permanent storage in cookies or hidden form elements. Using a Web application manipulation proxy, the attacker can also view or edit any of these very enticing items passed to the browser. Some applications pass back account numbers, balances, or other critical information in cookies, expecting that they will remain unchanged and trusting them when they return from the browser.

Of particular interest are Web applications that pass back a price to the browser, such as an e-commerce shopping cart. Of course, an e-commerce application has to pass back a price so that customers can see on the screen how much they are spending, but that price should only be displayed on the screen. In addition to displaying the price on the screen, some applications use a cookie or a hidden form element to pass a price back to the browser for a shopping cart.

In such applications, the server sends the price to the browser in the form of a cookie or hidden form element, and the browser sends the price back to the server for each subsequent interaction to maintain the shopping cart or add to it. There is nothing to say that the user can't edit the price in the cookie or hidden form element while it's at the browser or in a Web application manipulation proxy. An attacker can watch the price go through a Web application manipulation proxy, edit it at the proxy, and pass it back to the server. The question here is this: Does the server trust that modified price? I've seen several e-commerce applications that trust the price that comes back from the user in the cookie or hidden form element.

For example, consider a Web application that sells shirts on the Internet. Suppose for this company, shirts should be priced at $50.00. This price is displayed on the screen in HTML, but is also passed in a cookie in a shopping cart. The attacker can use a Web application manipulation proxy to edit that cookie to say, "The $50.00 shirt is now changed to ten cents," or even zero. The price will be sent to the Web application, and if the Web application is vulnerable, the attacker will get a shirt for ten cents, or even for free. The attacker might even lower the price to a negative number, and perhaps the shirt will arrive in the mail with a check for the attacker's troubles! Quite frankly, the Web application doesn't need to send the price in the cookie. It should only send a product stock-keeping unit (SKU) number or some other reference to the product, but not its price. Furthermore, it shouldn't trust the integrity of data received from the browser, as an attacker can alter any data using a Web application manipulation proxy.

Defending Against Web Application Session Tracking and Variable Alteration Attacks

To defend your Web applications from this type of attack, you must ensure the integrity of all session tracking elements and other sensitive variables stored at the browser, whether they are implemented using URLs, hidden form elements, or cookies. To accomplish this, use the following techniques for protecting variables sent to the browser:

  • Digitally sign or hash the variables using a cryptographic algorithm, such as a Hash-Based Message Authentication Code (HMAC), as shown in Figure 7.35. When the application needs to pass a variable back to the browser, it creates a hash of the variable using a secure hash algorithm with a secret key known only to the Web application on the Web server. The variable and this hash are sent to the user. Evil users who try to change the data (and even the hash itself) will not be able to create a matching hash of their changed data, because they don't know the secret key. Thus, the application can perform an integrity check of all returned values to make sure their data and hashes match, using that secret key.
    Figure 7.35

    Figure 7.35 Applying an integrity check to a variable passed to a browser using the HMAC algorithm.

  • If you are passing multiple variables in a single cookie, be careful when concatenating all of them together and loading them into a single cookie. Suppose you want to pass one variable that has a value of dogfood and another variable that has the value court. If you just concatenate these before hashing, the value dogfood and court will have the same hash as dog and foodcourt (as well as dogfoo and dcourt, I suppose). That gives the attacker a slightly better chance at figuring out what you are mixing together in your hashing algorithm. To minimize this chance, you should separate the values in the cookie with a delimiter character that won't be included in the variable values themselves. For example, include a separation character when concatenating, such as "&", as in dogfood&court.
  • Encrypt the information in the URL, hidden form element, or cookie. Don't just rely on SSL, which protects data in transit. In addition to SSL, use some form of encryption of sensitive variables.
  • Make sure your session IDs are long enough to prevent accidental collision. I recommend that session credentials be at least 20 characters (that's 160 bits) or longer.
  • Consider making your session IDs dynamic, changing from page to page throughout your Web application. That way, an attacker will have a harder time crafting specific session ID numbers for specific users.

When applying these mechanisms to secure the variables passed to the browser, you have to make sure that you cover the entire application. Sometimes, 99.9 percent of all session tracking information in an application is securely handled, but on one screen, a single variable is passed in the clear without being encrypted or hashed. Perhaps the Web developer got lazy on one page, or had a raucous night before writing that particular code. Alternatively, maybe the page was deemed unimportant, so an inexperienced summer intern wrote the code. Regardless, if a session ID is improperly protected on a single page, an attacker could find this weakness, clone another user's session on that page, and move on to the rest of the application as that other user. With just one piece of unprotected session tracking information, the application is very vulnerable, so you have to make sure you are protected throughout the application.

Additionally, you need to give your users the ability to terminate their sessions by providing a logout feature in your Web application. When a user clicks the Logout button, his or her session should be terminated and the application should invalidate the session ID. Therefore, an attacker will not be able to steal the session ID, because it's no longer valid. Also, if a user's session is inactive for a certain length of time (e.g., for 15 minutes), your application should automatically time out the connection and terminate the session ID. That way, when users close their browsers without gracefully logging out of the session, an attacker will still not be able to usurp a live session after the time-out period expires.

Additionally, defenders can use specialized Web proxy tools to help defend against these attacks. The commercial products AppShield from Watchfire and InterDo by Kavado sit in front of a Web application and look for incoming requests in which an attacker manipulated a cookie or other state element that is supposed to remain static for a given browsing session. They also look for other suspicious behavior.

SQL Injection

Another weakness of many Web applications involves problems with accepting user input and interacting with back-end databases. Most Web applications are implemented with a back-end database that uses Structured Query Language (SQL). Based on interactions with a user, the Web application accesses the backend database to search for information or update fields. For most user actions, the application sends one or more SQL statements to the database that include search criteria based on information entered by the user. By carefully crafting a statement in a user input field of a vulnerable Web application, an attacker could extend an application's SQL statement to extract or update information that the attacker is not authorized to access. Essentially, the attacker wants to piggyback extra information onto the end of a normal SQL statement to gain unauthorized access.

To accomplish these so-called SQL injection attacks, the bad guys first explore how the Web application interacts with the back-end database by finding a user-supplied input string that they suspect will be part of a database query (e.g., user name, account number, product SKU, etc.). The attacker then experiments by adding quotation characters (i.e., ', ", and `) and command delimiters (i.e., ;) to the user data to see how the system reacts to the submitted information. In many databases, quotation characters are used to terminate string values entered into SQL statements. Additionally, semicolons often act as separating points between multiple SQL statements. Using a considerable amount of trial and error, the attacker attempts to determine how the application is interacting with the SQL database. A trial-and-error process is involved because each Web application formulates queries for a back-end database in a unique fashion. Interestingly, the Paros Web application manipulation proxy tool we discussed in the previous section has an automated SQL injection flaw detection capability, based on fuzzing user input. In the section on buffer overflows at the beginning of this chapter, we discussed fuzzing input for size by continually varying the amount of data sent until the application behaves in a strange fashion. Paros fuzzes user input not based on size, but instead focuses on altering all variables passed to a Web application, including information sent in the URL, elements of forms (both displayed and hidden form elements), and cookies. Paros looks for SQL injection flaws by sending quotes, semicolons, and other meaningful elements of SQL to the target application to make it generate a strange error message that could be a sign of an SQL injection flaw.

To get a feel for how SQL injection works, let's look at a specific example from a tool called WebGoat, a free Web application available for download from www.owasp.org. WebGoat implements a simulated e-commerce application, where users can pretend to buy HDTV equipment and other items. However, like the Mock Bank application we looked at earlier in this chapter, WebGoat is full of various Web vulnerabilities. By downloading WebGoat and experimenting with it in your lab on a Windows or Linux machine, you can improve your Web application assessment skills in a mock environment. If you can learn to find the flaws of WebGoat, you can apply the same skills in other applications and help make the world a more secure place.

WebGoat is an ideal tool for learning, as shown in Figure 7.36. It includes complete lesson plans, a report card on the users' progress so far, and almost two dozen different common Web application flaws (including SQL injection issues, as well as authentication and session tracking flaws similar to those we discussed earlier). Along the way, the tool offers hints for conquering each individual vulnerability, ranging from very ambiguous guidance to explicit directions for attacking a specific flaw. The Web-based user interface can be tweaked to make the Web application display all HTTP parameters, HTML, cookies, and even Javascript in-line for convenient analysis by the would-be attacker. Finally, to help apprentices make sure that they are absorbing the material, there's even a final challenge, a hintless component of the application the users must master on their own.

Figure 7.36

Figure 7.36 WebGoat is a great environment for learning Web application security assessment techniques.

One of the flaws designed into WebGoat involves SQL injection. The application lets users review their credit card numbers stored in the application, based on their account numbers. As illustrated in Figure 7.37, the user Joe Snow has two credit card numbers entered into the application.

Figure 7.37

Figure 7.37 In WebGoat, user Joe Snow reviews his credit card numbers via his account number.

Now, suppose this Joe Snow user is evil. For SQL injection attacks, this bad guy might start out by entering quotation characters into the application as part of an account number. Remember, many SQL environments treat quotation characters as important terminators of strings. By sending an additional quotation character, the attacker might be able to generate an error message from the backend database.

In Figure 7.38, the evil Joe Snow has submitted an account number of 101". Those closed quotes at the end are going to cause problems in the application. As a helpful hint about what's going on, WebGoat displays the SQL statement that will be used to query the back-end WebGoat database:

SELECT * FROM user_data WHERE userid = 101
Figure 7.38

Figure 7.38 The evil user types in an account number of 101" and gets an error message.

Of course, real-world applications wouldn't display the SQL itself, but WebGoat does for training purposes. Unfortunately, the application blindly takes anything entered by the attacker in the HTML form and puts it after the userid = portion of the SQL statement. If Joe Snow just enters a number, the application performs as expected, looking up the account information for that account number. However, if the attacker enters quotation marks, the resulting SQL becomes:

SELECT * FROM user_data WHERE userid = 101"

Those quotation marks at the end are the problem. Databases don't like to see such things, because they are syntax errors in SQL. Thus, the application indicates this error to Joe Snow by printing out that ugly ODBC Microsoft Access Driver message. Although that error might be ugly to most users, for evil Joe Snow, it's like gold. Any time an application responds with a syntax, SQL, SQL Syntax, ODBC, or related error message, we've got a major sign the application is vulnerable to SQL injection.

Now, to really attack this application, the bad guy injects a little SQL logic into the target application. This time, the bad guy types an account number of 101 or 'TRUE'. The resulting SQL created by the application will be:

SELECT * FROM user_data WHERE userid = 101 or 'TRUE'

Let's consider that WHERE clause in the SQL SELECT statement. We're looking for data where the userid has the value 101 or 'TRUE'. Based on the rudimentary logical operator OR, anything OR 'TRUE' is true. "The sky is purple" or 'TRUE' is a true statement, based on the nature of OR. So, this WHERE clause is true for everything in the user_data table. Thus, the application looks up all data in that table and displays it to the attacker. As shown in Figure 7.39, the bad guy now has a list of credit card numbers for other users, obtained via SQL injection.

Figure 7.39

Figure 7.39 The evil user enters an account number of 101 or 'TRUE' to get all account information via SQL injection.

Our example from WebGoat showed injection techniques for SQL query statements (a SELECT command in particular). Injected UPDATE commands can allow an attacker to modify data in the database. Ultimately, if attackers carefully construct commands within SQL, they can get raw access to the back-end database.

Defenses Against SQL Injection

To defend against SQL injection and related attacks through user input, your Web application must be developed to filter user-supplied data carefully. Remember, the application should never trust raw user input. It could contain injected commands and all kinds of general nastiness. Wherever a user enters data into the application, the application must strongly enforce the content type of data entered. A numerical user input should really only be an integer; all non-numerical characters must be filtered. Furthermore, the application must remove unneeded special characters before further processing of the user input. In particular, the application should screen out the following list of scary characters:

  • Quotes of all kinds (', ', ", ", and `)—String terminators
  • Semicolons (;)—Query terminators
  • Asterisks (*)—Wildcard selectors
  • Percent signs (%)—Matches for substrings
  • Underscore (_)—Matches for any character
  • Other shell metacharacters (&\|*?~<>^()[]{}$\n\r), which could get passed through to a command shell, allowing an attacker to execute arbitrary commands on the machine

Your best bet is to define which characters your application requires (usually just alphanumeric) and filter out the rest of the riff-raff users send you.

For those characters that might be dangerous but really necessary, introduce an escape sequence or substitute. One popular method of substituting innocuous replacements involves using an & and two letters to represent an otherwise scary character. For example, an apostrophe (') can be changed to &ap, less than (<) can become &lt, and so on.

Furthermore, your input filtering code in the Web application can look for and remove potentially damaging SQL statements, including such SQL-relevant words as SELECT, INNER, JOIN, UNION, UPDATE, and TRUE.

These potentially damaging characters and statements should be filtered out or substituted on the server side of the Web application. Many Web application developers filter input on the client side, using Javascript or other techniques, mistakenly thinking that will stop SQL injection and related attacks. Yet, an attacker can bypass any client-side filtering using a Web application manipulation proxy like Achilles or Paros to inject arbitrary data into the HTTP or HTTPS connection. Remember, the browser is potentially enemy territory, so any filtering that occurs there can be subverted by the attacker. Even pull-down menus can be subverted using a proxy, as an attacker adds further options to the menu via a proxy that can include SQL injection and related attacks.

Another level of defense against SQL injection involves limiting the permissions of the Web application when accessing the database. Don't let your Web application have database administrator capabilities on your database! That's incredibly dangerous. Build the Web application and configure the database so that the Web application logs in with a very limited permission account, with the ability to view and update only those fields of those tables that are absolutely required. Clamping down on these permissions won't eliminate SQL injection attacks, but it can really limit the attacker's ability to explore the database fully.

Finally, Web application developers should consider the use of parameterized stored procedures in their applications. In the examples we've discussed here, the Web application gathers user input and uses it to compose database query strings, which it then forwards to the database for execution. Composing these queries on the fly at the Web application results in SQL injection when attackers provide SQL-relevant commands or operators in user input. A Web architecture that uses parameterized stored procedures, on the other hand, doesn't feed raw SQL statements generated by the Web application into the database. Instead, this architecture relies on stored procedures, code that runs on the database server itself, to interact with the database. By moving the logic for interacting with the database to the database server, the Web application can provide the stored procedure a set of discrete parameters drawn from user input that are used in queries defined within the stored procedure itself. The stored procedure breaks down the user input into the individual parameters that need to be fed into the database search. Because the query logic isn't created on the fly, but is instead coded into the stored procedure relying on user input merely as a set of parameters, stored procedures help minimize the chance of SQL injection.

In this section, we've looked at three of the most common attacks against Web applications, namely account harvesting, state manipulation, and SQL injection. These are three of the biggest Web application attacks, but there are many other vulnerabilities that Web applications could face, including cross-site scripting (which involves bouncing a malicious browser script off of a Web site) and command injection (which lets an attacker inject operating system commands in user input), among many others. To learn more about such flaws, the single best source freely available on the Internet is the Open Web Application Security Project (OWASP) at www.owasp.org. Everything created by the team at OWASP is free and open source. They are the people behind WebGoat, as well as numerous other tools for testing and securing Web applications.

Their Guide to Building Secure Web Applications and Web Services is quite comprehensive, including details associated with design, architecture, implementation, event logging, and more! It really is a must-read for any Web developer today.

  • + Share This
  • 🔖 Save To Your Account


comments powered by Disqus