Securing PHP Applications Part II – Securing PHP code

5. SQL injections
What is it?
This type of attack is one of the most common attacks. SQL injections occur after two failures of the part of developers: failure to filter data as it enters the application (filter input) and failure to escape data as it is sent to the database (escape output). For example, let’s suppose we have the following query:

<?php
$sql = "SELECT *
        FROM   users
        WHERE  username = '''
        AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";
?>


If this query is sent to MySQL the following error is displayed:

You have an error in your SQL syntax. Check the manual that corresponds to your
MySQL server version for the right syntax to use near 'WHERE username = ''' AND
password = 'a029d0df84eb55

Now, the user finds out information about two columns of your database table and knows which is your full WHERE clause. In this context he can try to get information about users, for example or, worst, to delete users, like this:

<?php
$sql = "SELECT *
        FROM   users
        WHERE  username = 'chris' --
        AND    password = 'a029d0df84eb5549c641e04a9ef389e5'";
?>

If he knows a user or many is even easier.

How should I protect my application from it?
As discussed above the solution for this type of attack is to always filter input and always escape output.

6. Session attacks: fixation, hijacking and injection
6.1. Session fixation
What is it?
Session fixation is a method of obtaining a valid session identifier without the
need to predict or capture one. It enables a malicious user to easily impersonate a
legitimate user by forcing the session ID. It is the simplest and most effective method
for a malicious user to obtain a valid session ID.

For example, this type of attack can come from a link like this:

<a href=http://www.example.com/index.php?PHPSESSID=1234> Click here </a>

A user clicks on this link and goes to your site. The attacker waits for the user to login and this is the moment where he puts his hands on the valid session ID of the user.

How should I protect my application from it?
In this case, PHP comes with a really easy solution: the use of session_regenerate_id() function which will change the user session ID. Important is to use this function in critical moments like: after a user logs in, after a user change his password, etc.

6.2. Session hijacking
What is it?
This is the most common type of session attack. This refers to any method that an attacker can use to access another user’s session. The first step for any attacker is to obtain a valid session identifier, and therefore the secrecy of the session identifier is paramount. With other words, this attack comes after a session fixation attack.

How should I protect my application from it?
Well, in this case, there are three methods of defense:
- user agent verification
This is a very basic way of verifying the user’s identity. When you create the session ID, you could grab the HTTP_USER_AGENT variable. Then you could verify it on each new page view. Unfortunately, if the session has been hijacked, the malicious agent could have grabbed the user agent info and spoofed it. A better method would be to store the hash of the user agent string. Better yet would be to store the hash plus a seed and verify that.

- IP addres verification
This is very similar to user agent verification. In some cases it is more secure. You store the users’ IP when you first generate their session, and then on every page load you verify that IP address. There are two major drawbacks to this method. A lot of locations are behind a NAT proxy, so it is possible that the attacker and the user both have the same IP address. The other issue comes from large ISPs like AOL. A number of them, and AOL specifically, have massive proxy setups that send the user out via a different IP address with every page request.

This is a method that is not really used, because of its drawbacks.

- secondary token
In this method you set up two points of verification. You create a token for the users utilizing a different method from the session ID. When they first log in, create a hash of that token and store it in their session. You can then verify it on every page load. You can also regenerate this token frequently, allowing only a very short window for the attacker to guess it.

6.3. Session injection
What is it?
This type of attack appears when you allow user input into session without validating it.

How should I protect my application from it?
By filtering and validating the user input.

7. Code injection / Includes
What is it?
This type of attack describes the risk that can appear if you include some files (or execute all kind of information) directly from $_GET, for example:

<?php
    include "{$_GET['path']}/header.inc";
?>

Here a malicious user can insert all kinds of scripts or code that will be executed on your server.

This situation can appear also when using a form with a GET method instead of POST. It’s no difference if a user clicks this link:

http://example.org/login.php?username=chris&password=mypass

Or submits this form:

<form action="http://example.org/login.php" method="GET">
    <p>Username: <input type="text" name="username" /></p>
    <p>Password: <input type="password" name="password" /></p>
    <p><input type="submit" /></p>
</form>

How should I protect my application from it?
Very simple: don’ t allow this kind of includes, or, if it is really necessary, filter and validate de input.

8. Improper error handling
When dealing with PHP code in the development process of an application we should be aware of all the errors that could appear and to resolve them. After releasing the application we must disable the possibility of displaying errors to the user, because in this way we make it vulnerable.

So, the first thing we should do, of course after we fix all errors, is to set the error_reporting from E_ALL or E_ALL|E_NOTICE to error_reporting(0), put the display_errors directive to 0 (we can use the ini_set() function or change directly in the php.ini file if we are allowed) and to log all errors using the log_errors() and error_log() functions. Probably you ask yourself why to bother if you fixed all errors? Well, is very possible that a malicious user to inject some bad code into your application, that can produce errors and these errors must be logged, so that you can fixed them and primary, to be aware of them.

Above I discussed about the PHP errors, but in an application which make use of a database can appear some other types of errors, the database errors. These types of errors can be handled using a try, catch and throw structure (for more details see this http://php.net/manual/en/language.exceptions.php ).

For a better resolution of the errors that could appear in an application I advice you to create a error handling mechanism which you can apply every time (PHP provides the set_error_handler() function).

9. Authentication and Authorization
What is it?
Everybody knows (at least I think so) what is authentication and authorization and probably ask himself why are them in this list of vulnerabilities. Well, let’s start with authentication: here a user must insert a valid username and a valid password. Now, a malicious user, who may know the username or not, can use look at the login form, see what’s the authentication script (the php file that resolve this) and create his own script that consists of a loop of username and password pairs. This way he tries to find out the password, for example, if know the username.

How should I protect my application from it?
What you can do is to create your own safeguard: a script that temporarily suspend an account once a maximum number of login failures are recorded or a simple throttling mechanism. Also, is highly recommended that your application to accept long passwords (greater than 4 characters) containing numbers too. The encryption mechanism is also important, that why some programmers use a salt string when encrypting a password throught the md5() mechanism.

A throttling mechanism looks like this:

<?php
    /* mysql_connect() */
    /* mysql_select_db() */
 
    $clean = array();
    $params = array();
 
    $now = time();
    $max = $now - 15;
 
    $salt = 'SHIFLETT';
 
    if (ctype_alnum($_POST['username'])){
      $clean['username'] = $_POST['username'];
    }
    else{
      /* ... */
    }
 
    $clean['password'] = md5($salt . md5($_POST['password'] . $salt));
    $params['username'] = mysql_real_escape_string($clean['username']);
 
    $sql = "SELECT last_failure, password
            FROM   users
            WHERE  username = '{$params['username']}'";
 
    if ($result = mysql_query($sql)){
      if (mysql_num_rows($result)){
        $record = mysql_fetch_assoc($result);
        if ($record['last_failure']> $max){
          /* Less than 15 seconds since last failure */
        }
        elseif ($record['password'] == $clean['password']){
          /* Successful Login */
        }
        else{
          /* Failed Login */
          $sql = "UPDATE users
                  SET    last_failure = '$now'
                  WHERE  username = '{$params['username']}'";
 
          mysql_query($sql);
        }
      }
      else{
        /* Invalid Username */
      }
    }
    else{
      /* Error */
    }
    ?>

10. Shared hosting
What is it?
a) On a shared host, all your files are public and accessible to the others that use the same host. And, this is the reason that all your files can be very easily hacked. For example: assuming that you have a script named file.php and hosted at example.org, a file such as /path/to/source.php can be exposed simply by visiting:

http://example.org/file.php?file=/path/to/source.php

The worst part is that, if you keep your database information in a file too. Like the one above, this can be easily hacked.
b) Your sessions can be, also, easily readed and modified (session injection).

How should I protect my application from it?
a) In this case the best approach is to keep more of your site information in a database and the access to this database to be kept in a file that only root can read and that adheres to the following format:
SetEnv DB_USER “myuser”
SetEnv DB_PASS “mypass”

This file must be included from http.conf, like this: Include “/path/to/db.conf”.

b) The solution for that is to save your sessions in a database and to make use of the session_set_save_handler() function. I, for example, didn’t need to make use of this practice, but if your session keep very important information you may use it.

Maybe there are voices which say that safe mode can be the solution. Well, think again I would answer. Why, because safe mode doesn’t prevent the attacker for reading session data or other files owned by the server.

—————————————————————————————————-
OBS: This list is getting greater and greater every day so, don’t take it as a full reference of attack types.

As a rule, that every developer should follow: “Do NOT trust user input!”. I’m sure that you already knew it, but I think is better to have somebody to remember it from time to time. So, all input must be filtered and all output must be escaped.

And, as goodby I provide you a list of a few security tips. Most of these assume that you have full control over your environment. If you do not have this level of control, talk to your hosting provider or change some of the php.ini settings on the fly as your code runs.
• Turn off error display (do use the error log) in the php.ini file.
• Make sure register_globals is turned off in the php.ini file
• Use secure socket layer (SSL) certificates on your sites where required.
• Keep your included library, SQLite files (if in use), and settings files outside your
document root (so that they are not accessible via the web server).

Related posts:

  1. Securing PHP applications Part I – Securing PHP code

2 Responses to “Securing PHP Applications Part II – Securing PHP code”

  1. Chris Meller says:

    Disappointing that the SQL Injection section didn’t include anything about PDO and bound parameters. “Filter it” wasn’t a real answer and sometimes might not be an option, “–” could be valid in a comment field, you can’t just filter it out.

  2. Claudia says:

    Hi Cris,

    This articles about security represent an overview. If you read my first article on this theme, you’ll probably understand:
    “There are a lot of books treating this issue. So, why another post about this subject. Well, here a try to cover this problem in a short way so that you don’t have to read hundreds of pages or to search all over the Internet for this.”

    Anyway, I take your comment like an suggestion and I’ll write a post about that later.

    Thx

Leave a Reply