Web Securities (Preventing SQL Injection, XSS, XSRF / Form Spoofing)

Tags:
Web security are an important and essential feature of any Web Application. Its important for any Web Developer to secure Web Applications from external attacks as much as possible. Recently, I have been working on implementing Web Security and decided to write an article on how to secure web applications from the following attacks:
  • 1. SQL Injection
  • 2. Cross Site Scripting (XSS)
  • 3. Cross Site Request Forgery (XSRF)
Before I start explaining each of the above terms, it's important to note that any data / input that's being received from visitors must be filtered/checked and should not be blindly trusted as safe.

1. SQL Injection: SQL Injection is a way a user can enter 'malicious' input and resulting in getting access to someone else's account or can also cause severe damage to the database. To read more please check out the wiki. Consider the following case: There's a username / password form, and you have the following Code for validating user info:

  1. $checkSQL = "SELECT * FROM user WHERE username LIKE '{$_POST['user']}' AND password LIKE '{$_POST['pass']}' ";
  2. $sqlResult = mysql_query($checkSQL, $dbLink);
Assuming: HTML input fields are 'name' and 'pass' for username and password.
Now, what if the user enters the following values for username and password:
username: %' OR 1=1 --
pasword: hahaha

With the above SQL code, the visitor will be able to enter into the site. because 1=1 will be true and because -- is a comment on SQL, anything after that will be ignored. This is a simple attack. A user can even go a step further and add a command like 'DROP TABLE user' etc., which can be very dangerous. So, its important to escape (filter) user data.

For PHP 4/5 and people using the mysql_connect & mysql_query methods for carrying out query, there's this method called mysql_real_escape_string( ) to escape a string before carrying it out. But, I actually like to specifically filter out characters like '-', or '%', or quotes (single/double), they are never used in username or password anyway. So, I use this method to eliminate those characters.

  1. strtr($userInput, array( '\' => '', '"' => '' , '--' => '', '%' => '') );
strtr is faster than using regex, hence i prefer strtr

For people using PDO (if you are new to PDO, I would kindly ask you to read about it, it has many great features of traditional mysql_query), the SQL statement can be prepared and then executed. Example:

  1. $stmt = $dbLink->prepare('SELECT * FROM user WHERE username LIKE ? AND password LIKE ?');
  2. $stmt->execute(array($_POST['user'], $_POST['pass']));

Using Prepared statement can eliminate the possibility of SQL Injection, however, I still prefer to use the strtr method to filter out the content, just to be on the safe side.

#2. (Cross Site Scripting) XSS: Cross Site Scripting is a technique user can use to enter script tags into the page, and can cause damage to get access to the visitor's cookie information / hijack sensitive data. (visitors refer to people visiting your site). Read more at wiki

To eliminate this, htmlentities method can be used to convert every tag's '<' and '>' as well as single and double quote characters.

  1. htmlentities($userData, ENT_QUOTES);

#3: Cross-Site Request Forgery (XSRF): This is a very interesting attack, its an attack by which say, if you have an online store, a visitor's purchase order can be made on your site without the visitor actually making the order. Read more on wiki

The way basically it works is this, the visitor visits another site were the following code is written:

  1. <img src="http://www.mysite.com/shop/confirm_order.php" alt="confirm" />

When a visitor say has added some items on your site's store and has them on shopping basket, but has not checked out, and also didn't log out. He visits another site where the above img tag is there. What will happen is basically, the img will request that page to be executed, and since the visitor of your site has not logged out (i.e his cookie has not expired and he is considered logged in), the confirm_order.php page will be visited, and the order will be made. (Note: I realize this may not be a good example.. but I hope you get the rough idea)

To prevent this, I use this technique called 'tokenize' method, which I learned by reading O'reilly's PHP book. The idea is simple. A unique key or token should be created at the start of page and store in on Session, and also will be posted as a hidden field on the form. When visitor submits the form, then the token value stored at session will be matched with hidden Form's value to ensure that its coming from that page.

This is what you do in Form's page:

  1. // store a unique value in session
  2. $_SESSION['token'] = md5(time());
  3.  
  4. // now on the form.. add an extra hidden field
  5. <input type="hidden" name="token" value="<?=$_SESSION['token']?>" />

Then, on submission page, do the following:

  1. if(!isset($_POST['token']) || $_POST['token'] != $_SESSION['token']) {
  2. // error, form spoofing, return to users' page or do something else
  3. }
  4. // otherwise, carry out executing this page normally.

A quick note: Its better to avoid using $_REQUEST and to always use $_POST to get access to $_POST variables.

Thanks to the author

Thanks to the author of this article.

nice, but missing Session Fixation

Nice post. However, you should have covered Session Fixation as well. Session Fixation is also an important part of Web security.

Good stuff

Nice post.

Good Read

I am developing a secure website account system, and your post is really good and it covers the 3 main security issues. A thing I would add is to use a $token = uniqid(); for generating tokens (your 3rd example). It generates a unique integer based on current time stamp, and is more secure that time().

Isabelle

Fantastic!!!

Great post. Keep up the good work

Thanks,
R.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
6 + 1 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.