Welcome Guest, Not a member yet? Register   Sign In
How to disable CSRF temporaly for callback controllers ?
#11

[eluser]jpwdesigns[/eluser]
HI thanks for the post first of all.

I've got the
Code:
if(stripos($_SERVER["REQUEST_URI"],'/callbacker') === FALSE)
{
    $config['csrf_protection'] = TRUE;
}
else
{
    $config['csrf_protection'] = FALSE;
}
bit in my config which works great when accessing the site normally.

However, I have a controller on a cron which runs the page not through wget in order to avoid session overhead etc... like this:

cd /var/www/vhosts/mydomain.com/httpdocs; /usr/bin/php index.php controlername classname

This causes an error because the Request Uri isn't there.
Code:
<h4>A PHP Error was encountered</h4>

<p>Severity: Notice</p>
<p>Message:  Undefined index:  REQUEST_URI</p>
<p>Filename: config/config.php</p>
<p>Line Number: 297</p>

How can I get around that?
#12

[eluser]Ricardo Martins[/eluser]
try to use $_SERVER['SCRIPT_FILENAME'] == /path/to/file.php instead of request_uri
#13

[eluser]jpwdesigns[/eluser]
unfortunately that produces a file path to index.php
#14

[eluser]jpwdesigns[/eluser]
Ok, here is the solution (hack) i've got working for anyone else needing it:


Code:
if (isset($_SERVER["REQUEST_URI"]))
{
    if(stripos($_SERVER["REQUEST_URI"],'/mypage') === FALSE)
    {
        $config['csrf_protection'] = TRUE;
    }
    else
    {
        $config['csrf_protection'] = FALSE;
    }
}
else
{
    $config['csrf_protection'] = TRUE;
}
#15

[eluser]Jacob Graf[/eluser]
Works great! Wish there was a more elegant solution, but this will do for now. Thanks!
#16

[eluser]benjamin[/eluser]
Thanks!
#17

[eluser]solid9[/eluser]
Okay these codes below worked for me,

Code:
if(stripos($_SERVER["SCRIPT_FILENAME"],'reset_password_final')==FALSE)
    {
        $config['csrf_protection'] = FALSE;
    }
    else
    {
        $config['csrf_protection'] = TRUE;
    }

But I don't know how to use this below,
Code:
$config['csrf_exclude_uris'] = array('api/person/add');


Anyone would like to explain to me how to use the last code?

thanks in advanced.
#18

[eluser]CroNiX[/eluser]
if the URL is www.theirsite.com/api/person/add, CSRF will not be run.
#19

[eluser]Unknown[/eluser]
Here's my solution which is not a hack and uses Eric Barnes whitelist code check. What I also needed is control over what to do when encountering a CSRF error. CI just trows an error out of the box, which is not quite user friendly.

So I extended the Security class to include the whitelist code and to use a variable instead of throwing an error message when the CSRF check fails. Then you should have a base controller whose constructor checks the variable to handle the CSRF error when it occurs. Here's an example that just redirects the user to the current url:
Code:
&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* MY_Controller Class
*
* Base controller for all our controllers.
*/
class MY_Controller extends CI_Controller
{

    /**
     * Constructor
     */
    function __construct()
    {
        parent::__construct();

        $this->_check_csrf();
    }

    private function _check_csrf()
    {
        // Manually handle CSRF errors
        if ($this->security->csrf_error) {
            // Your logic to handle the error
            redirect(current_url());
        }
    }

}

/* End of file MY_Controller.php */
/* Location: ./application/core/MY_Controller.php */

The only thing you have to watch out with this method is to properly handle the CSRF error on all your routes, otherwise your application's CSRF security will be voided. You should never let go through a request which's CSRF check has failed, so you should at least do a redirect or throw out an error.

I hope that this will be useful for some of you, cheers!

And here is the Security class code:
Code:
&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
* MY_Security Class
*
* Extended base security class for better CSRF handling.
*/
class MY_Security extends CI_Security {

    /**
     * Constructor
     */
    function __construct()
    {
        parent::__construct();

        $this->csrf_error = FALSE;
    }

    // --------------------------------------------------------------------

    /**
     * Verify Cross Site Request Forgery Protection
     *
     * @return    object
     */
    public function csrf_verify()
    {
        // If no POST data exists we will set the CSRF cookie
        if (count($_POST) == 0)
        {
            return $this->csrf_set_cookie();
        }

        // Check if URI has been whitelisted from CSRF checks
        if ($exclude_uris = config_item('csrf_exclude_uris'))
        {
            $uri = load_class('URI', 'core');
            if (in_array($uri->uri_string(), $exclude_uris))
            {
                return $this;
            }
        }

        // Do the tokens exist in both the _POST and _COOKIE arrays?
        if ( ! isset($_POST[$this->_csrf_token_name]) OR
             ! isset($_COOKIE[$this->_csrf_cookie_name]))
        {
            return $this->csrf_set_error();
        }

        // Do the tokens match?
        if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
        {
            return $this->csrf_set_error();
        }

        // We kill this since we're done and we don't want to
        // polute the _POST array
        unset($_POST[$this->_csrf_token_name]);

        // Nothing should last forever
        unset($_COOKIE[$this->_csrf_cookie_name]);
        $this->_csrf_set_hash();
        $this->csrf_set_cookie();

        log_message('debug', "CSRF token verified ");

        return $this;
    }

    // --------------------------------------------------------------------

    /**
     * Set CSRF Error
     *
     * @return    void
     */
    public function csrf_set_error()
    {
        $this->csrf_error = TRUE;
    }

}


/* End of file MY_Security.php */
/* Location: ./application/core/MY_Security.php */
#20

[eluser]theshiftexchange[/eluser]
Damn - I just found this post after I made my own solution. Oh well - incase people were wondering - this is my current solution for 2.1.

This allows me to turn off CSRF for a specific URI. Could be improved - but you get the idea.


MY_Security.php
Code:
&lt;?php
/**
* A fix to ignore CSRF tokens for the jquery_validation
*
*/

class MY_Security extends CI_Security
{
    public function __construct()
    {
        parent::__construct();

    }
  
public function csrf_verify()
{
  // Firstly - manually get our controller/method
  // We cant use the CI instance yet

  $uri = $_SERVER['REQUEST_URI'];
  if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
  {
   $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
  }
  elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
  {
   $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
  }
  

  // Check if this is a jquery remote check
  $pos = strrpos ($uri, "welcome/remote");

  if ($pos === false)
  {
   // No? Then complete the csrf check as normal
   return parent::csrf_verify();

  }
  else
  {
   // Yes? Then just ignore it as if nothing happened
   return $this;
  }  
}

public function csrf_show_error()
{
  redirect ('');
}
}


in my case "welcome/remote" is my specific controller/function I dont want CSRF on.




Theme © iAndrew 2016 - Forum software by © MyBB