Friday 6 January 2017

CodeIgniter Security Classes

CodeIgniter Security Class

CodeIgniter contain security class methods which will help to create a secure application and process input data. The methods are given below.
  • XSS Filtering
  • CSRF (Cross-site Request Forgery)
  • Class Reference

XSS Filtering

XSS stands for Cross-site Scripting. It is used to disable JavaScript or other types of code that try to hijack cookies and perform other type of malicious acts. When it encounters anything harmful, it is rendered safe by converting the data to character entities.
XSS filtering uses xss_clean() method to filer data.
  1. $data = $this->security->xss_clean($data);  
There is an optional second parameter, is_image, which is used to test images for XSS attacks. When this parameter is set to TRUE, it doesn't return an altered string, instead it returns TRUE if image is safe and FALSE if it contains malicious information.
  1. if ($this->security->xss_clean($file, TRUE) === FALSE)  
  2.     {  
  3.         //file failed in xss test  
  4.     }  

CSRF (Cross-site Request Forgery)

To enable CSRF do the following settings in application/config/config.php file.
  1. $config['csrf_protection'] = TRUE;  
If you are using form helper, then a hidden csrf field will be automatically inserted in your form_open()/ field.
Otherwise, you can manually add it using,
get_csrf_token_name() (it returns name of csrf) and
get_csrf_hash() (it returns value of csrf).
Generated tokens may be kept same throughout the life of CSRF cookie or may be regenerated on every submission. The default generation of token provides a better security but it also have usability concerns as other tokens like multiple tabs/windows, asynchronous actions, etc become invalid. Regeneration behavior can be set in application/config/config.php file as shown below.
  1. $config['csrf_regenerate?] = TRUE;  

Class Reference

  1. Class CI_Security                  
  1. xss_clean ($str [, $is_image = FALSE])  
Parameters - $str (mixed) ? input string or an array of strings
Returns - XSS-clean data
Return-type - mixed
From input data it removes XSS exploits and returns the clean string.
  1. Sanitize_filename ($str [, $relative_path = FALSE])  
Parameters - $str (string) ? File name/path
$relative_path (bool) ? Whether tp preserve any directories in the file path
Returns - Sanitized file name/path
Return-type - string
It prevents directory traversal and other security threats by sanitizing filenames. It is mainly useful for files which were supplied via user input.
  1. Entity_decode (($str [, $charset = NULL])  
Parameters - $str (string) ? Input string
$charset (string) ? Character set of the input string
Returns - Entity-decoded string
Return-type - string
It tries to detect HTML entities that don't end in a semicolon because some browser allows that.
$charset parameter is left empty, then your configure value in $config['charset'] will be used.
  1. Get_random_bytes ($length)  
Parameters - $length (int) ? Output length
Returns - A binary system of random bytes or FALSE on failure.
Return-type - string
It is used for generating CSRF and XSS tokens.

Preventing, Enabling from CSRF

In this tutorial we'll learn to protect CodeIgniter application from the cross-site request forgery attack. It is one of the most common vulnerabilities in web application. CSRF protection is quite easy in CodeIgniter due to its built-in feature.

What is CSRF attack

A CSRF attack forces a logged-on victim's browser to send a forged HTTP request, including victim's session cookie and other authentication information, to a web application.
For example, suppose you have a site with a form. An attacker could create a bogus form on his site. This form could contain hidden inputs and malicious data. This form is not actually sent to the attacker's site, in fact it comes to your site. Thinking that the form is genuine, your site will process it.
Now just suppose that the attacker's form point towards the deletion form in your site. If a user is logged in and redirected to the attacker's site and when perform search, his account will be deleted without knowing him. That is the CSRF attack.

Token Method

To protect from CSRF we need to connect both the HTTP requests, form request and form submission. There are several ways to do this, but in CodeIgniter hidden field is used which is called CSRF token. The CSRF token is a random value that changes with every HTTP request sent.
When CSRF token is inserted in the website form, it also gets saved in the user's session. When the form is submitted, the website matches both the token, the submitted one and one saved in the session. If they match, request is made legitimate. The token value changes each time the page is loaded, which makes it tough for the hackers to guess the current token.

Enabling CSRF Protection

To enable CSRF make the following statement TRUE from FALSE in application/config/config.php file.
  1. $config['csrf_protection'] = TRUE;  

Token Generation

With each request a new CSRF token is generated. When object is created, name and value of the token are set.
  1. $this->csrf_cookie_name = $this->csrf_token_name;  
  2. $this->_csrf_set_hash();  
The function for it is,
  1. function _csrf_set_hash()  
  2. {  
  3.       if ($this->csrf_hash == '')  
  4.         {  
  5. if ( isset($_COOKIE[$this->csrf_cookie_name] ) AND  
  6.              $_COOKIE[$this->csrf_cookie_name] != '' )  
  7.            {  
  8.              $this->csrf_hash = $_COOKIE[$this->csrf_cookie_name];  
  9.           } else {  
  10.                $this->csrf_hash = md5(uniqid(rand(), TRUE));  
  11.          }  
  12.        }  
  13.     return $this->csrf_hash;  
  14. }  
First, function checks the cookie's existence. If it exists, its current value is used because when security class is instantiated multiple times, each request would overwrite the previous one.
Function also creates a globally available hash value and save it for further processing. The token's value is generated. Now it has to be inserted into every form of the website with the help of function form_open().
The method csrf_verify() is called each time a form is sent. This method does two things. If no POST data is received, the CSRF cookie is set. And if POST data is received, it checks the submitted value corresponds to the CSRF token value in session. In the second case, CSRF token value is discarded and generated again for the next request. This request is legitimate and whole process starts again.

CodeIgniter DataBase

Database Configuration

In CodeIgniter, go to application/config/databse.php for database configuration file.
Database Configuration1
In database.php file, fill the entries to connect CodeIgniter folder to your database.
Database Configuration2
The config settings are stored in a multi-dimensional array as shown above. Fill out your connection details to connect to database.
You can also specify failover in the situation where main connection cannot be established. This can be specified by setting failover as shown below. You can write as many failovers as you want.
Database Configuration3

Automatically connecting Database

The auto connect feature will load your database class with every page load.
To add auto connect go to application/config/autoload.php and add the word database to library array.

Manually connecting Database

If you need to connect database only in some pages of your project, you can use below code to add the database connectivity in any page, or add it to your class constructor which will make the database globally available for that class.
  1. $this->load->database();  

Connecting multiple Database

If you need to connect more than one database simultaneously, do the following.
  1. $db1 = $this->load->database(?group_one?, TRUE);  
  2. $db1 = $this->load->database(?group_two?, TRUE);  
Here, group_one and group_two are the group names which will be replaced by your group name

CodeIgniter Database INSERT record

In this example, we will INSERT different values in database showing meaning of Indian names through CodeIgniter.
In application/controller, file baby_form.php is created.
  1. <?php  
  2. defined('BASEPATH') OR exit('No direct script access allowed');  
  3.   
  4. class Baby_form extends CI_Controller {  
  5.       
  6.     public function index()  
  7.     {  
  8.         $this->load->view("baby_form_add");  
  9.     }  
  10.     function savingdata()  
  11.     {  
  12.         //this array is used to get fetch data from the view page.  
  13.         $data = array(  
  14.                         'name'     => $this->input->post('name'),  
  15.                         'meaning'  => $this->input->post('meaning'),  
  16.                         'gender'   => $this->input->post('gender'),  
  17.                         'religion' => $this->input->post('religion')  
  18.                         );  
  19.         //insert data into database table.  
  20.         $this->db->insert('baby',$data);  
  21.   
  22.         redirect("baby_form/index");  
  23.     }  
  24. }  
  25. ?>  
Look at the above snapshot, our table name is 'baby'.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Baby Form Add</title>  
  5. </head>  
  6. <body>  
  7.     <form method="post" action="<?php echo site_url('baby_form/savingdata'); ?>">  
  8.         <table>  
  9.             <tr>  
  10.                 <td>Name:</td>  
  11.                 <td>:</td>  
  12.                 <td><input type="text" name="name"></td>  
  13.             </tr>  
  14.             <tr>  
  15.                 <td>Meaning:</td>  
  16.                 <td>:</td>  
  17.                 <td><input type="text" name="meaning"></td>  
  18.             </tr>  
  19.             <tr>  
  20.                 <td>Gender:</td>  
  21.                 <td>:</td>  
  22.                 <td><input type="text" name="gender"></td>  
  23.             </tr>  
  24.             <tr>  
  25.                 <td>Religion:</td>  
  26.                 <td>:</td>  
  27.                 <td><input type="text" name="religion"></td>  
  28.             </tr><br><br>  
  29.             <tr>  
  30.                 <input type="submit" name="submit" value="Save">  
  31.             </tr>  
  32.         </table>  
  33.     </form>  
  34. </body>  
  35. </html>  
This is our view page which is being loaded in the controller's page.
To run it on your browser, pass URL
http://localhost/insert/index.php/Baby_form/
Codeigniter Insert database record 3
By inserting various names in the above form we have created our table as shown below.
Codeigniter Insert database record 4

CodeIgniter SELECT Database record

To fetch all data from database, one more page in Model folder of CodeIgniter will be created. There will be some changes in controller's and view's files also.
Controller file (Baby_form.php) is shown below.
  1. <?php  
  2. defined('BASEPATH') OR exit('No direct script access allowed');  
  3.   
  4. class Baby_form extends CI_Controller {  
  5.   
  6.     public function __construct()  
  7.     {  
  8.         parent::__construct();  
  9.   
  10.         //calling model  
  11.         $this->load->model("Babymodel""a");  
  12.     }  
  13.       
  14.     public function index()  
  15.     {  
  16.         $this->load->view("baby_form_select");  
  17.     }  
  18.     function savingdata()  
  19.     {  
  20.         //this array is used to get fetch data from the view page.  
  21.         $data = array(  
  22.                         'name'     => $this->input->post('name'),  
  23.                         'meaning'  => $this->input->post('meaning'),  
  24.                         'gender'   => $this->input->post('gender'),  
  25.                         'religion' => $this->input->post('religion')  
  26.                         );  
  27.         //insert data into database table.  
  28.         $this->db->insert('baby',$data);  
  29.   
  30.         redirect("baby_form/index");  
  31.     }  
  32. }  
  33. ?>  
We have added a constructor to load the model page. Highlighted code is added to fetch the inserted record. And our view page is now baby_form_select.php
View file (baby_form_select.php) is shown below.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Baby Form Add</title>  
  5. </head>  
  6. <body>  
  7.     <form method="post" action="<?php echo site_url('baby_form/savingdata'); ?>">  
  8.         <table>  
  9.             <tr>  
  10.                 <td>Name:</td>  
  11.                 <td>:</td>  
  12.                 <td><input type="text" name="name"></td>  
  13.             </tr>  
  14.             <tr>  
  15.                 <td>Meaning:</td>  
  16.                 <td>:</td>  
  17.                 <td><input type="text" name="meaning"></td>  
  18.             </tr>  
  19.             <tr>  
  20.                 <td>Gender:</td>  
  21.                 <td>:</td>  
  22.                 <td><input type="text" name="gender"></td>  
  23.             </tr>  
  24.             <tr>  
  25.                 <td>Religion:</td>  
  26.                 <td>:</td>  
  27.                 <td><input type="text" name="religion"></td>  
  28.             </tr><br><br>  
  29.             <tr>  
  30.                 <input type="submit" name="submit" value="Save">  
  31.             </tr>  
  32.         </table>  
  33.     </form>  
  34.     <table border="1">  
  35.         <thead>  
  36.             <th>ID</th>  
  37.             <th>NAME</th>  
  38.             <th>MEANING</th>  
  39.             <th>GENDER</th>  
  40.             <th>RELIGION</th>  
  41.             <th>ACTION</th>  
  42.         </thead>  
  43.         <tbody>  
  44.             <?php  
  45.                 foreach($this->a->fetchtable() as $row)  
  46.                 {  
  47.                     //name has to be same as in the database.  
  48.                     echo "<tr>  
  49.                                 <td>$row->id</td>  
  50.                                 <td>$row->name</td>  
  51.                                 <td>$row->meaning</td>  
  52.                                 <td>$row->gender</td>  
  53.                                 <td>$row->religion</td>  
  54.                     </tr>";  
  55.                 }  
  56.             ?>  
  57.         </tbody>  
  58.     </table>  
  59. </body>  
  60. </html>  
Code in baby_form_select.php file is same as baby_form_add.php. Above codes are added to fetch the record.
Here we have fetched the record in a table with the help of foreach loop. Function fetchtable() is created to fetch the record.
Model file (babymodel.php) is shown below.
  1. <?php  
  2. defined('BASEPATH') OR exit('No direct script access allowed');  
  3.   
  4. class Babymodel extends CI_Model {  
  5.   
  6.     function __construct()  
  7.     {  
  8.         //call model constructor  
  9.         parent::__construct();  
  10.     }     
  11.           
  12.         function fetchtable()  
  13.         {  
  14.             $query = $this->db->get('baby');  
  15.             return $query->result();  
  16.         }  
  17. }  
  18. ?>  
In URL, type http://localhost/CodeIgniter/index.php/Baby_form
Codeigniter Select database record 4
Look at the above snapshot, all data has been fetched from the table 'baby'.

Login Form in CodeIgniter (without MySQL)

Here, we'll make a simple login page with the help of session.
Go to file autoload.php in application/config/autoload.php
Login Form in CodeIgniter1
Set session in library and helper.
Create controller page Login.php in application/controllers folder.
  1. <?php  
  2. defined('BASEPATH') OR exit('No direct script access allowed');  
  3.   
  4. class Login extends CI_Controller {  
  5.       
  6.     public function index()  
  7.     {  
  8.         $this->load->view('login_view');  
  9.     }  
  10.     public function process()  
  11.     {  
  12.         $user = $this->input->post('user');  
  13.         $pass = $this->input->post('pass');  
  14.         if ($user=='juhi' && $pass=='123')   
  15.         {  
  16.             //declaring session  
  17.             $this->session->set_userdata(array('user'=>$user));  
  18.             $this->load->view('welcome_view');  
  19.         }  
  20.         else{  
  21.             $data['error'] = 'Your Account is Invalid';  
  22.             $this->load->view('login_view'$data);  
  23.         }  
  24.     }  
  25.     public function logout()  
  26.     {  
  27.         //removing session  
  28.         $this->session->unset_userdata('user');  
  29.         redirect("Login");  
  30.     }  
  31.   
  32. }  
  33. ?>  
Look at the above snapshot, we have created a session for a single user with Username juhi and Password 123. For a valid login and logout we will use this username and password.
Create view page login_view.php in application/views folder.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Login Page</title>  
  5. </head>  
  6. <body>  
  7.     <?php echo isset($error) ? $error : ''; ?>  
  8.     <form method="post" action="<?php echo site_url('Login/process'); ?>">  
  9.         <table cellpadding="2" cellspacing="2">  
  10.             <tr>  
  11.                 <td><th>Username:</th></td>  
  12.                 <td><input type="text" name="user"></td>  
  13.             </tr>  
  14.             <tr>  
  15.                 <td><th>Password:</th></td>  
  16.                 <td><input type="password" name="pass"></td>  
  17.             </tr>  
  18.   
  19.             <tr>  
  20.                 <td> </td>  
  21.                 <td><input type="submit" value="Login"></td>  
  22.             </tr>  
  23.         </table>  
  24.     </form>  
  25. </body>  
  26. </html>  
Create view page welcome_view.php in application/views folder to show the successful login message.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title></title>  
  5. </head>  
  6. <body>  
  7.     Welcome <?php echo $this->session->userdata('user'); ?>   
  8. <br>  
  9.     <?php echo anchor('Login/logout''Logout'); ?>  
  10.   
  11.   
  12. </body>  
  13. </html>  
Output
Type URL localhost/login/index.php/Login
Login Form in CodeIgniter5
Now on entering wrong information we'll be see unsuccessful message which we have set in login_view page in else part.
Login Form in CodeIgniter6
Login Form in CodeIgniter7
Now on entering right information, we'll see welvome_view.php message.
Login Form in CodeIgniter8
Login Form in CodeIgniter9
Click on Logout, we'll be directed to Login page.

Login page (with database)

In earlier example, we learnt a simple login page with one single username and session.
Now we'll make it with more than one users using database. A sign in and login page will be there for users.
Following pages are made in this example.
In application/controllers
  • Main.php
In application/views
  • login_view.php
  • invalid.php
  • data.php
  • signin.php
In application/models
  • login_model.php
In the first page, you'll have the option for Login and Sign In.
On Login, if user has entered correct credentials matching to database then he will be directed to data.php page. But if he has entered wrong information then incorrect username/password message will appear.
We have named our CodeIgniter folder as login_db. And our table name is signup.
Login page 1
We need to do some basic settings in our login_db CodeIgniter folder.
Go to autoload.php file, and do the following settings.
Login page 2
In the above snpashot, we have loaded the libraries and helper.
In database.php file, fill your username and database name. Our database name is codeigniter.
Login page 3
Now, we?ll start the example.
We have made file Main.php in application/controllers folder,
  1. <?php  
  2. defined('BASEPATH') OR exit('No direct script access allowed');  
  3.   
  4. class Main extends CI_Controller {  
  5.   
  6.     public function index()  
  7.     {  
  8.         $this->login();  
  9.     }  
  10.   
  11.     public function login()  
  12.     {  
  13.         $this->load->view('login_view');  
  14.     }  
  15.   
  16.     public function signin()  
  17.     {  
  18.         $this->load->view('signin');  
  19.     }  
  20.   
  21.     public function data()  
  22.     {  
  23.         if ($this->session->userdata('currently_logged_in'))   
  24.         {  
  25.             $this->load->view('data');  
  26.         } else {  
  27.             redirect('Main/invalid');  
  28.         }  
  29.     }  
  30.   
  31.     public function invalid()  
  32.     {  
  33.         $this->load->view('invalid');  
  34.     }  
  35.   
  36.     public function login_action()  
  37.     {  
  38.         $this->load->helper('security');  
  39.         $this->load->library('form_validation');  
  40.   
  41.         $this->form_validation->set_rules('username''Username:''required|trim|xss_clean|callback_validation');  
  42.         $this->form_validation->set_rules('password''Password:''required|trim');  
  43.   
  44.         if ($this->form_validation->run())   
  45.         {  
  46.             $data = array(  
  47.                 'username' => $this->input->post('username'),  
  48.                 'currently_logged_in' => 1  
  49.                 );    
  50.                     $this->session->set_userdata($data);  
  51.                 redirect('Main/data');  
  52.         }   
  53.         else {  
  54.             $this->load->view('login_view');  
  55.         }  
  56.     }  
  57.   
  58.     public function signin_validation()  
  59.     {  
  60.         $this->load->library('form_validation');  
  61.   
  62.         $this->form_validation->set_rules('username''Username''trim|xss_clean|is_unique[signup.username]');  
  63.   
  64.         $this->form_validation->set_rules('password''Password''required|trim');  
  65.   
  66.         $this->form_validation->set_rules('cpassword''Confirm Password''required|trim|matches[password]');  
  67.   
  68.         $this->form_validation->set_message('is_unique''username already exists');  
  69.   
  70.     if ($this->form_validation->run())  
  71.         {  
  72.             echo "Welcome, you are logged in.";  
  73.          }   
  74.             else {  
  75.               
  76.             $this->load->view('signin');  
  77.         }  
  78.     }  
  79.   
  80.     public function validation()  
  81.     {  
  82.         $this->load->model('login_model');  
  83.   
  84.         if ($this->login_model->log_in_correctly())  
  85.         {  
  86.   
  87.             return true;  
  88.         } else {  
  89.             $this->form_validation->set_message('validation''Incorrect username/password.');  
  90.             return false;  
  91.         }  
  92.     }  
  93.   
  94.     public function logout()  
  95.     {  
  96.         $this->session->sess_destroy();  
  97.         redirect('Main/login');  
  98.     }  
  99.   
  100. }  
  101. ?>  
In application/views folder, login_view.php file is made.
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="utf-8">  
  5.     <title>Login Page</title>  
  6. </head>  
  7. <body>  
  8.     <h1>Login</h1>  
  9.       
  10.     <?php  
  11.   
  12.     echo form_open('Main/login_action');  
  13.   
  14.     echo validation_errors();  
  15.   
  16.     echo "<p>Username: ";  
  17.     echo form_input('username'$this->input->post('username'));  
  18.     echo "</p>";  
  19.   
  20.     echo "<p>Password: ";  
  21.     echo form_password('password');  
  22.     echo "</p>";  
  23.   
  24.     echo "</p>";  
  25.     echo form_submit('login_submit''Login');  
  26.     echo "</p>";  
  27.   
  28.     echo form_close();  
  29.   
  30.     ?>  
  31.   
  32.     <a href='<?php echo base_url()."index.php/Main/signin"; ?>'>Sign In</a>     
  33. </body>  
  34. </html>  
In application/views folder, data.php file is made.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title></title>  
  5. </head>  
  6. <body>  
  7.     <h1>Welcome, You are successfully logged in.</h1>  
  8.   
  9.     <?php  
  10.     echo "<pre>";  
  11.     echo print_r($this->session->all_userdata());  
  12.     echo "</pre>";  
  13.     ?>  
  14.   
  15.     <a href='<?php echo base_url()."index.php/Main/logout"; ?>'>Logout</a>  
  16.   
  17. </body>  
  18. </html>  
In application/views folder, signin.php file is made.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Sign Up Page</title>  
  5. </head>  
  6. <body>  
  7.     <h1>Sign In</h1>  
  8.   
  9.     <?php  
  10.   
  11.     echo form_open('Main/signin_validation');  
  12.   
  13.     echo validation_errors();  
  14.   
  15.     echo "<p>Username:";  
  16.     echo form_input('email');  
  17.     echo "</p>";  
  18.   
  19.     echo "<p>Password:";  
  20.     echo form_password('password');  
  21.     echo "</p>";  
  22.   
  23.     echo "<p>Confirm Password:";  
  24.     echo form_password('cpassword');  
  25.     echo "</p>";  
  26.   
  27.     echo "<p>";  
  28.     echo form_submit('signin_submit''Sign In');  
  29.     echo "</p>";  
  30.   
  31.     echo form_close();  
  32.   
  33.     ?>  
  34.   
  35. </body>  
  36. </html>  
In application/views folder, invalid.php file is made.
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <title>Invalid Page</title>  
  5. </head>  
  6. <body>  
  7.     <h1>Sorry, You don't have access to this page.</h1>  
  8.   
  9.     <a href='<?php echo base_url()."Main/login"; ?>'>Login Again</a>  
  10.   
  11. </body>  
  12. </html>  
In application/models folder, login_model.php file is made.
  1. <?php  
  2.   
  3. class Login_model extends CI_Model {  
  4.   
  5.     public function log_in_correctly() {  
  6.   
  7.         $this->db->where('username'$this->input->post('username'));  
  8.         $this->db->where('password'$this->input->post('password'));  
  9.         $query = $this->db->get('signup');  
  10.   
  11.         if ($query->num_rows() == 1)  
  12.         {  
  13.             return true;  
  14.         } else {  
  15.             return false;  
  16.         }  
  17.   
  18.     }  
  19.   
  20.       
  21. }  
  22. ?>  
On entering the URL, http://localhost/login_db/index.php/Main/
Following page will appear.
Login page 4
Enter the information to Login.

After entering information, click on Login button. We have entered the wrong information and hence it will show the error message as shown below.

On entering the information from database, we' ll be directed to data.php page.
Login page7
Click on Login button.
Login page8
Clicking on Logout button, you'll be directed to the Main page.
On clicking Sign In, following page will appear.
Login page9
Login page10
Login page11