Ben Parker once advised his young nephew Peter, whose super-hero alter ego is Spider-man, that “With great power comes great responsibility.” CakePHP framework provides us a rich tool-set to build high performance web applications. The applications built using CakePHP are secure at much extent as long as it comes with some nice features such as Authentication component and Access controlled lists.
But.. when it comes to develop high end commercial applications, some additional security measures must be taken to make your application robust as a matter of responsibility.
Alright. Now let us see how can we make our defense stronger.
With addition to use Authentication component and Access controlled lists, we should take help of Data validation and Data sanitization while building application in CakePHP. Validating data restricts user to provide the required input and of correct type. Server side validations are strongly recommended considering the form spoofing. But a drawback in only relying upon Data validation is it cannot sense the markup language and hence leaves your application open for the XSS (Cross Site Scripting) vulnerability.
To avoid the XSS vulnerability, CakePHP provides us the Sanitize class. It provides us the flexibility to filter data coming straight from the (malicious) user. As Sanitize class can be treated as a library, it can be used in the controllers and models as well.
As far as SQL injection is concerned, cake handles it auto-magically if you use Cake's ORM (Object Relational Mapping) methods such as find() and save() and proper array notation such as array('field' => 'value') rather than raw SQL.
So let us move ahead and see an example:
As your inner PHP programmer might have guessed, the very first step is to import the Sanitize class before the controller class definition
.
-
App::import('Sanitize');
-
class MyController extends AppController {
-
...
-
...
-
}//end class
As you know that we have conventional PHP functions to escape strings to avoid XSS, but when it is framework, we've to follow its way to get the auto-magic functionality. So here are some methods from the Sanitizaion class to the rescue, which are very useful while dealing with the data sent by malicious user.
1. Sanitize::paranoid(string $string, array $allowedChars);
If your are thinking to allow only alphanumeric characters from the user input, then paranoid function is a right way to move on. It simply stripes out the special characters from the user input. But still if you are kind enough to allow some special characters, use the $allowedChars array and pass the special characters to be ignored.
Demo:
2. Sanitize::html(string $string, array $options = array())
After watching how to eliminate the special characters, let us focus on how to eliminate the HTML characters from the input string so as to save our HTML page from the user by disturbing its layout or inserting new HTML code. You can simply follow the html function to achieve the same. It will convert the html characters present in the input into equivalent html entities. What??? you don't need to convert into equivalent entities, but delete the html characters present in the input string? Okay, just pass the 'remove' => TRUE in the options array and all done! Now you have the new input string with all the HTML characters filtered out
.
Demo:
3. Sanitize::escape(string $string, string $connection)
SQL injection is considered to be a serious security issue as far as form - database communication is concerned. Cake by default handles this vulnerability if you follow its ORM conventions, but when it comes to write custom queries, I highly recommend you to use this function. Depending on the system's current magic_quotes_gpc setting, the escape function escapes the SQL statements by adding slashes to the special characters.
$connection is the name of the database to quote the string for, as named in your app/config/database.php file.
Demo:
-
$inputString = "O'reilly";
-
//output: O\'reilly
4. Sanitize::clean(mixed $data, mixed $options)
The clean method takes a string or an array as input and returns the same string or array after it has been recursively "cleaned." The cleaning process covers a wide range of potential data problems, such as handing tricky backslashes, weird spaces, HTML, carriage returns, and more. It performs the following things:
- Odd spaces (including 0xCA) are replaced with regular spaces.
- Double-checking special chars and removal of carriage returns for increased SQL security.
- Adding of slashes for SQL (just calls the sql function outlined above).
- Swapping of user-inputted backslashes with trusted backslashes.
The $options argument can either be a string or an array. When a string is provided it's the database connection name. If an array is provided it will be merged with the following options:
- connection
- odd_spaces
- encode
- dollar
- carriage
- unicode
- escape
- backslash
Demo:
The above example will preserve the form data from encoding.
You can view these methods in cake/libs/sanitize.php to get a better handle on what's involved. You should never modify the base CakePHP files, however. It will make upgrading to future releases difficult and could cause unexpected behavior.
In the next part of this post, I'll try to explain the Cake's powerful Security component's functionality supported by some nice examples. Till then, have a great time and stay tuned
!
Nice post, waiting for part 2.
@red Thank you. Part 2 is on the way..
Seems like the pivotal question is whether it's possible to ensure that Sanitize isn't overlooked by including it one time in the application controller rather than in each controller individually.
Above code is just an example. It completely depends upon the need of your application. If you need to ensure security for multiple modules of your application, then better to use the Sanitize class in the AppController. Else, simply import it wherever required to avoid loading the Sanitize class in each and every call.