Reputation: 6398
I am using codeigniter on the backend .
Recently i heard about the term "CSRF" and decided to protect the requests.
Almost all actions on my site is through Ajax & some times i am creating/appending page content using DOM manipulation [here the doubt, how can i inject the CSRF token to the view files ?]
Okkey ,after that how can i validate that ?
Assume that i added these values as token and passed to server ,then can i use constructors to check & validate this ?
Ex :
Class Cl_Controller extends Ci_controller
{
function __construct()
{
//loading libraries,models,helpers etc...
if (isset($this->input->get_post("CSRF_TOKEN")) || _another_condition_)
{
// The CSRF TOKEN is invalid or null ,the action cannot be done...
}
}
function register()
{
//some codes...
}
function delete_user()
{
//some codes
}
}
Is it possible to do some thing link this ?
Please suggest me some good ideas & usual practices.
Thank you.
Upvotes: 1
Views: 3243
Reputation: 7902
For my ajax calls I usually perform two checks;
Make sure it is an ajax request, using a small helper file.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('ajax_check')) {
/**
* Check AJAX
*
* Checks to see if you (or the royal I) are dealing with an AJAX call.
*
* @return boolean
*/
function ajax_check() {
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
return TRUE;
} else {
show_404();
return FALSE;
}
}
}
if ( ! function_exists('ajax_response')) {
/**
* JSON Response Wrapper
*
* Wraps up any data nicely for sending back to an ajax call
*
* @return string
*/
function ajax_response($status, $data) {
if (!is_array($data)) {
$data = array();
}
// Set the JSON header appropriately
header('Content-Type: application/json');
// Echo out the array into json
echo json_encode(array_merge(array('status' => $status), $data));
exit;
}
}
if ( ! function_exists('ajax_force_fail')) {
/**
* Force AJAX Failure
*
* If you ever need to, force an AJAX to fail
*/
function ajax_force_fail() {
$_ci =& get_instance();
$_ci->output->set_status_header(500);
}
}
Usage like;
public function some_function() {
$this->load->helper('ajax');
ajax_check();
try {
// do something
ajax_response('success', array('data' => $some_var));
} catch (Exception $e) {
ajax_response('failure', array('data' => $e->getMessage()));
}
}
And a similar approach to xsrf. File:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if ( ! function_exists('xsrf_get_token')) {
/**
* Get XSRF Token
*
* Returns a token that exists for one request that verifies that
* the action was executed by the person that requested it
*
* @return string
*/
function xsrf_get_token() {
$ci =& get_instance();
if ($ci->session->userdata('xsrf_hash')) {
$token = $ci->session->userdata('xsrf_hash');
} else {
// Generate the token
$token = sha1(microtime().$ci->uri->uri_string());
// Set it in the session
$ci->session->set_userdata('xsrf_hash', $token);
}
//Return it
return $token;
}
}
if ( ! function_exists('xsrf_get_token_field')) {
/**
* Get XSRF Token Field
*
* Returns an xhtml form element to include xsrf token.
* You can specify the id/name attribute of the input.
* Has a dependancy to get_xsrf_token().
*
* @param string The id/name to be used
* @return string
*/
function xsrf_get_token_field($name='auth_token') {
return '<input type="hidden" id="'.$name.'" name="'.$name.'" value="' .xsrf_get_token(). '" />';
}
}
if ( ! function_exists('xsrf_delete_token')) {
/**
* Delete XSRF Token
*
* Deletes the xsrf token
*
* @return boolean
*/
function xsrf_delete_token() {
$ci =& get_instance();
if ($ci->session->userdata('xsrf_hash')) {
$ci->session->unset_userdata('xsrf_hash');
return TRUE;
} else {
return FALSE;
}
}
}
if ( ! function_exists('xsrf_check_token')) {
/**
* Get XSRF Token Field
*
* Checks that the token is still valid, returns true if so.
* Deletes old token after valid or fail.
* Has a dependacy to xsrf_delete_token()
*
* @param string The challenge token
* @return boolean
*/
function xsrf_check_token($challenge_token) {
// CI
$ci =& get_instance();
// Get the stored token
$token = $ci->session->userdata('xsrf_hash');
// Delete the old token
xsrf_delete_token();
// Returns if the token is the right token
return ($token == $challenge_token);
}
}
Usage (controller);
public function some_other_function() {
$this->form_validation->set_rules('username', 'Username', 'required|callback_check_token');
if($this->form_validation->run() == TRUE ) {
// do something
} else {
// something else
}
}
// callback function
public function check_token($val) {
if (xsrf_check_token($val) == TRUE) {
return TRUE;
} else {
$this->form_validation->set_message('check_token', 'Oops');
return FALSE;
}
}
In view;
<form action="" method="post">
<?php echo xsrf_get_token_field(); ?>
...
</form>
Upvotes: 3