CSRF Protection in Code Igniter using Form Tokens
ScreenCast Commentary
Today we are going to talk about CSRF (or Cross Site Request Forgery), otherwise known as session riding, see-surf, and XRSF, and how to built a token system in Code Igniter to mitigate any potential attacks using CSRF.
To start, the core of CSRF lies in web browsers making requests that they are “technically” authorized to do, however the user doesn’t actually know the request is being made (otherwise known as a confused deputy attack). Consider things like image tags, or iFrames, they make calls to external URL’s all the time.. if instead of a call to an actual image, the image tag calls a URL with malacious GET variables in the URL, some damage can occur.
One solution to this problem is the use of form tokens, or a unique and random string put into a hidden POST variable and into a cookie every time the page is loaded. This makes it nearly impossible to make a POST request from an external source because that token must be validated on the server side based on the POSTed token value and the set cookie value. Remember the same basic principle works in any PHP application, Code Igniter just makes session management a lot simpler.
Remember if an application vulnerable to XSS (Cross Site Scripting) it could possibly navigate through the DOM and find the token value, making it possible for an automated attack. Read up on the “samy is my hero” MySpace attack for more on that.
End Commentary
CSRF with POST variables is dangerous because an attacker can setup a false form, maybe just asking for your favorite color, and then post hidden content to a form/site that you have a session on. Below is the code we used inside the Code Igniter Auth class and the main controller to implement a form token system.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Auth {
function Auth() {
$this->ci =& get_instance();
}
function token() {
$token = md5(uniqid(rand(),true));
$this->ci->session->set_userdata('token',$token);
return $token;
}
}
/* End of file Auth.php */
<?php
class Welcome extends Controller {
function Welcome()
{
parent::Controller();
$this->load->model('search_model');
}
function index()
{
if($this->input->post('login')) {
$this->session->set_userdata('logged_in','yes');
}
if($this->input->post('logout')) {
$this->session->set_userdata('logged_in','no');
}
if(strcmp($this->session->userdata('logged_in'),'yes')==0) {
$data['logged_in'] = true;
if($this->input->post('search')) {
if($this->input->post('token') == $this->session->userdata('token')) {
$this->search_model->add_search($this->input->post('search'));
}
}
} else {
$data['logged_in'] = false;
}
$data['token'] = $this->auth->token();
$data['search_amt'] = $this->search_model->post_amt();
$this->load->view('welcome_message',$data);
}
}
/* End of file welcome.php */
/* Location: ./system/application/controllers/welcome.php */
Comments