Understanding the Dangers to Your Web App

By Paul McFedries

There are, it often seems, almost as many security exploits as there are lowlifes trying to compromise our web apps. However, the most common security dangers fall into four main categories: SQL injection, cross-site scripting, insecure file uploads, and unauthorized access.

SQL injection

Probably the most common exploit, SQL injection involves inserting some malicious code into an ordinary SQL command, such as a SELECT or DELETE statement. Consider the following sign-in form:

<form>
  <label for="username">User name:</label>
  <input id="username" type="text" name="user">
  <label for="password">Password:</label>
  <input id="password" type="password" name="pass">
</form>

When this form is submitted, a PHP script to sign in the user might look, in part, like this:
<?php
  $user = $_POST['user'];
  $pass = $_POST['pass'];
      $sql = "SELECT *
      FROM users
      WHERE username='$user' AND password='$pass'";
?>

That works fine as long as the user types a legit username and password, but what happens if some scoundrel types admin' # in the user field and nothing at all in the password field? Here’s the resulting value of the $sql variable:

SELECT * FROM users WHERE username=&apos;admin&apos; #&apos; AND password=&apos;&apos;

The key here is the hash symbol (#), which marks the beginning of a comment in an SQL command, meaning that the rest of the line is ignored. (Just so you know, MySQL also uses — to mark the start of a comment.) That is, the actual SQL command that gets processed is this:

SELECT * FROM users WHERE username=&apos;admin&apos;

Congratulations, some criminal has just signed in as the administrator!

As another example, suppose your web app has a button that, when clicked, deletes an item from the current user’s data. Your Ajax call might pass along a user-id and an item-id, meaning that your PHP script would do something like the following to remove the specified item:

<?php
  $user_id = $_POST['user-id'];
  $item_id = $_POST['item-id'];
  $sql = "DELETE
      FROM items
      WHERE userid='$user_id' AND itemid='$item_id'";
?>

Looks fine from here, but suppose some fiend passes the following as the user-id value: whatever' OR 1=1 #. Assuming the item-id value is blank, here’s the resulting $sql variable value:

DELETE FROM items WHERE userid='whatever' OR 1=1 #' AND itemid=''

Taking the comment symbol (#) into account, the actual command looks like this:

DELETE FROM items WHERE userid=&apos;whatever&apos; OR 1=1

The 1=1 part always returns TRUE, so the result is that the command deletes everything from the items table!

Cross-site scripting (XSS)

Cross-site scripting (usually shortened to XSS) is a way of surreptitiously forcing an innocent user to launch an attacker’s malicious script. This most often happens when the malefactor uses a phishing email or similar ruse to trick the user into visiting a page that spoofs a form used on a legitimate site.

For example, suppose the form asks the user to enter her credit card number and password. If this was a normal form submission and the user entered either the wrong credit card number of the wrong password, the PHP script on the server might redisplay the form to ask the user to try again:

<?php
  $cc = $_POST['credit-card'];
  $pw = $_POST['password'];
 
  // Code that checks these inputs goes here
 
  // If one or both inputs are invalid:
  echo '<input type="text" name="credit-card" value="' . $cc . '">';
  echo '<input type="password" name="password">';
?>

Notice, in particular, that this “helpful” script redisplays the credit card value (stored in the $cc variable) in the text field. Imagine, then, that our attacker’s spoofed form actually sends the following text instead of the credit card number:

"><script>alert(&apos;Ha ha!&apos;);</script><a href="

Here’s the resulting HTML:

<input type="text" name="credit-card" value="">
<script>
  alert('Ha ha!');
</script>
<a href="">
<input type="password" name="password" value="">

What happens here? That’s right: The JavaScript code between the <script> and </script> tags executes. In the real world it’s unlikely to just display an innocuous alert box.

Insecure file uploads

If your web app allows users to upload files — for example, you might want to allow each user to upload a small image to use as a profile avatar — then you open up a new can of security worms because a malicious user can:

  • Upload huge files, which tax the server’s resources.
  • Upload a nasty script instead of, say, an image.
  • Overwrite existing server files.

Unauthorized access

If your web app requires users to sign in with a username (or email address) and password, then keeping those passwords secure is of paramount importance. Otherwise, an unauthorized interloper could sign in as a legitimate user and either destroy or tamper with that user’s data, post messages or other content under that user’s name, and even delete the user’s account.