CodeIgniter Forums
My CodeIgniter CSRF + Form Helpers - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Libraries & Helpers (https://forum.codeigniter.com/forumdisplay.php?fid=22)
+--- Thread: My CodeIgniter CSRF + Form Helpers (/showthread.php?tid=5993)



My CodeIgniter CSRF + Form Helpers - El Forum - 02-11-2008

[eluser]Unknown[/eluser]
Hi all,

I've created a CSRF & Form (Extended from CI Form) helpers that aim to tackle the CSRF exploit, and would like to contribute it to anybody who would be interested.

Save the following code into: system/application/helpers/csrf_helper.php
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* start the session just in case it has not already been started.
* suppress any warning message if it has already been started.
*/
@session_start();  

if (! function_exists('csrf_is_token_valid'))
{
    /**
     * @method bool csrf_is_token_valid() checks if a csrf token is valid
     * @return bool true if token is valid. false if token is invalid.
     */
    function csrf_is_token_valid()
    {
        $result = false;
        if (isset($_POST[csrf_varname()]))
        {
            $result = ((strcmp(csrf_value(), $_POST[csrf_varname()])) == 0);
        }
        return $result;
    }
}  

if (! function_exists('csrf_token'))
{
    /**
     * @method void csrf_token($varlen, $str_to_shuffer) construct a random input field name and assign the token to it.
     * @param int $varlen the length of the input field name that will be generated
     * @param string $str_to_shuffer the string that will be used to generate the input field name
     */
    function csrf_token($varlen = 3, $str_to_shuffer = "abcdefghijklmnopqrstuvwxyz0123456789_")
    {
        $start_pos = mt_rand(0, (strlen($str_to_shuffer) - $varlen));
        $_SESSION["CSRF_NONCE_VARNAME_{$_SERVER["REQUEST_URI"]}"] = substr(str_shuffle($str_to_shuffer), $start_pos, $varlen);
        $_SESSION["CSRF_NONCE_VALUE_{$_SERVER["REQUEST_URI"]}"]    = dohash(microtime() . mt_rand());
    }
}  

if (! function_exists('csrf_varname'))
{
    /**
     * @method string csrf_varname($varlen, $str_to_shuffer) return the generated input field name
     * @param int $varlen the length of the input field name that will be generated
     * @param string $str_to_shuffer the string that will be used to generate the input field name
     * @return string the generated input field name
     */
    function csrf_varname($varlen = 3, $str_to_shuffer = "abcdefghijklmnopqrstuvwxyz0123456789_")
    {
        if (!isset($_SESSION["CSRF_NONCE_VARNAME_{$_SERVER["REQUEST_URI"]}"]))
        {
            csrf_token($varlen, $str_to_shuffer);
        }
        return $_SESSION["CSRF_NONCE_VARNAME_{$_SERVER["REQUEST_URI"]}"];
    }
}  

if (! function_exists('csrf_value'))
{
    /**
     * @method string csrf_value($varlen, $str_to_shuffer) return the token
     * @param int $varlen the length of the input field name that will be generated
     * @param string $str_to_shuffer the string that will be used to generate the input field name
     * @return string the token
     */
    function csrf_value($varlen = 3, $str_to_shuffer = "abcdefghijklmnopqrstuvwxyz0123456789_")
    {
        if (!isset($_SESSION["CSRF_NONCE_VALUE_{$_SERVER["REQUEST_URI"]}"]))
        {
            csrf_token($varlen, $str_to_shuffer);
        }
        return $_SESSION["CSRF_NONCE_VALUE_{$_SERVER["REQUEST_URI"]}"];
    }
}  

if (! function_exists('csrf_clean'))
{
    /*
     * @method void csrf_clean() clears the session variables that store the csrf token
     */
    function csrf_clean()
    {
        session_unregister("CSRF_NONCE_VARNAME_{$_SERVER["REQUEST_URI"]}");
        session_unregister("CSRF_NONCE_VALUE_{$_SERVER["REQUEST_URI"]}");
    }
}  

if (isset($_POST) && count($_POST) > 0 && isset($_SESSION["CSRF_NONCE_VARNAME_{$_SERVER["REQUEST_URI"]}"]))
{
    if (!csrf_is_token_valid()) die("A form re-post or an unknown error has occurred.");
}
?>

Save the following code into: system/application/helpers/MY_form_helper.php
Code:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
if (! function_exists('form_csrf'))
{
    /*
     * @method string form_csrf($varlen, $str_to_shuffer) returns a constructed hidden input field of the csrf token
     * @param int $varlen the length of the input field name that will be generated
     * @param string $str_to_shuffer the string that will be used to generate the input field name
     * @return string the hidden input field
     */
    function form_csrf($varlen = 3, $str_to_shuffer = "abcdefghijklmnopqrstuvwxyz0123456789_")
    {
        csrf_token($varlen, $str_to_shuffer);
        return form_hidden(csrf_varname(), csrf_value());
    }
}
?>

Edit the file: system/application/config/autoload.php so as to get CI to autoload the necessary helpers.
Code:
/*
| -------------------------------------------------------------------
|  Auto-load Helper Files
| -------------------------------------------------------------------
| Prototype:
|
|    $autoload['helper'] = array('url', 'file');
*/

$autoload['helper'] = array('csrf', 'form', 'security');

To protect your form against CSRF, you just need to add:
Code:
<?=form_csrf();?>
into your form.

Example:
Code:
<form method="post">
<?=form_csrf();?>
<ul>
    <li>name<ul>
        <li>&lt;input name="n" type="text" /&gt;</li>
    </ul>
    </li>
    <li>email<ul>
        <li>&lt;input name="e" type="text" /&gt;</li>
        <li>&lt;input name="s" type="submit" value="submit" /&gt;</li>
    </ul>
    </li>
</ul>
&lt;/form&gt;

and you are done! Whenever the form get submitted, the CSRF Helper will validate the token.

You can find a more complete post of my codes here.


My CodeIgniter CSRF + Form Helpers - El Forum - 02-28-2008

[eluser]fdog[/eluser]
Thanks xciden! I've been needing a helper like this for a while.


My CodeIgniter CSRF + Form Helpers - El Forum - 02-21-2010

[eluser]kenjis[/eluser]
session_unregister() is deprecated. It's better not to use it.

http://php.net/session_unregister

This function has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged.


My CodeIgniter CSRF + Form Helpers - El Forum - 09-27-2010

[eluser]echoDreamz[/eluser]
Deprecated + the fact that CodeIgniter does not use PHP's native sessions.


My CodeIgniter CSRF + Form Helpers - El Forum - 06-12-2012

[eluser]Linh Pham[/eluser]
Hi there,
i have used this helper to prevent duplicate form submition,
i tried 3 click times on the submit button and it does not work,
so how to use this?

submit to insert the record into the database and with 3 click times and had 3 same records, so that it's not good for my aim, i just want only record will be insert into db


My CodeIgniter CSRF + Form Helpers - El Forum - 06-12-2012

[eluser]skunkbad[/eluser]
[quote author="Linh Pham" date="1339566280"]Hi there,
i have used this helper to prevent duplicate form submition,
i tried 3 click times on the submit button and it does not work,
so how to use this?

submit to insert the record into the database and with 3 click times and had 3 same records, so that it's not good for my aim, i just want only record will be insert into db[/quote]

I made my own CSRF library, and you can use it too if you want:

https://bitbucket.org/skunkbad/community-auth-ci-session-version/src/6165a8696bcc/application/libraries/csrf.php

Use is really easy, especially if you use the MY_form_helper:

https://bitbucket.org/skunkbad/community-auth-ci-session-version/src/6165a8696bcc/application/helpers/MY_form_helper.php

All you have to do is load the library in your controller:

Code:
$this->load->library('csrf');

Then, to check for valid form submission:

Code:
if( $this->csrf->token_match )
{
   // ...
}

CodeIgniter has it's own CSRF protection now, but this library can be used in older version of CI, or in combination with CI's CSRF protection. It's been fully tested and I use it every day.


My CodeIgniter CSRF + Form Helpers - El Forum - 06-13-2012

[eluser]Linh Pham[/eluser]
[quote author="skunkbad" date="1339568755"][quote author="Linh Pham" date="1339566280"]Hi there,
i have used this helper to prevent duplicate form submition,
i tried 3 click times on the submit button and it does not work,
so how to use this?

submit to insert the record into the database and with 3 click times and had 3 same records, so that it's not good for my aim, i just want only record will be insert into db[/quote]

I made my own CSRF library, and you can use it too if you want:

https://bitbucket.org/skunkbad/community-auth-ci-session-version/src/6165a8696bcc/application/libraries/csrf.php

Use is really easy, especially if you use the MY_form_helper:

https://bitbucket.org/skunkbad/community-auth-ci-session-version/src/6165a8696bcc/application/helpers/MY_form_helper.php

All you have to do is load the library in your controller:

Code:
$this->load->library('csrf');

Then, to check for valid form submission:

Code:
if( $this->csrf->token_match )
{
   // ...
}

CodeIgniter has it's own CSRF protection now, but this library can be used in older version of CI, or in combination with CI's CSRF protection. It's been fully tested and I use it every day.[/quote]

Thank you so much, it does work fine on my app