Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
How to catch Fuel\Core\SecurityException [ Error ] ?
  • I set up to use 'csrf_autoload' and it works.
    That shows following message when it is needed.

    Fuel\Core\SecurityException [ Error ]:
    CSRF validation failed, Possible hacking attempt detected!

    So far, it is no problem. Then I'd like to show my original view for users for who don't read English.
    As FuelPHP documents show following words, so I edited "index.php" at the top level of project folder.

    "If you want to deal with CSRF validation failures when autoload is enabled, you can catch the SecurityException in your index.php."

    [ index.php ]
    try
    {
      // Boot the app...
      require APPPATH.'bootstrap.php';
     
      // ... and execute the main request
      $response = $routerequest();
    }
    catch (\SecurityException $e)
    {
      $response = $routerequest('_400_', $e);
    }
    catch (HttpBadRequestException $e)
    {
      $response = $routerequest('_400_', $e);
    }

    I added 3 lines to catch "\SecurityException" and use '_400_' response.

    [ routes.php ]
    return array(
       '_root_'  => 'index',
       '_400_'   => 'error/400',
       '_404_'   => 'error/404',
       '_500_'   => 'error/500',
    );

    I added 1 lines to use error controller action_400 method.

    [ controller/error.php ]
    public function action_400($e){ //400 Bad Request
      $data = array();
      Session::set_flash('error',$e);
      $this->template->title = '400 Bad Request';
      $this->template->content = View::forge('400',$data);
    }

    Of course, I also put [ view/400.php ]. (This is written in Japanese, so I don't show here.)

    I expected to show [ view/400.php ], but actually it shows default error message page.
    How can I catch "Fuel\Core\SecurityException" at index.php?
  • Works fine here.

    For the test I simply used this in my controller:

        public function action_400()
        {
            return Response::forge(View::forge('400'), 400);
        }

    and that returns the standard 400 view that is in fuel/core/views when a SecurityException is thrown.
  • Than you for your reply.

    I have checked it. But in my case, it doesn't work. It shows default error message.
    "Fuel\Core\SecurityException [ Error ]:
    CSRF validation failed, Possible hacking attempt detected!"

    When I change setting at config.php  'csrf_bad_request_on_fail' is false, view/400.php is shown. 
    But FuelPHP use only view/400.php, I mean controller/error/action_400 doesn't work, because error page doesn't contain template.php which is added at controller_template.

    I think this means error-catching at index.php doesn't work in this case. Because at index.php FuelPHP will
    use config/routes.php setting and routes.php will use controller/error/action_400.

    In this case, not index.php but other source code catches SecurityException and use a default error page.
    And if 'csrf_bad_request_on_fail' is true, it use only view file(view/400.php) to show an error page.

    How can I catch SecurityException at index.php?

  • if "csrf_bad_request_on_fail" is true, a HttpBadRequestException is thrown, and with false, a SecurityException is thrown. So it should be set to false. If you set it to true, you can't catch SecurityException, as it isn't thrown at all.

    I used the route

        '_400_'   => 'welcome/400',    // The main 400 route

    and added the method mentioned in my previous post to the welcome controller (I test on new fuel installs, so no other controllers present), and that works fine.

    There was a bug in index.php that I found while testing, but that was concerning URI's for which no route was defined, like

        $routerequest('some/other/route', $e);

    which I fixed in 1.9/develop, but that isn't the case for you.
  • Basically  my "csrf_bad_request_on_fail" is false. I just tried to check that when it is false,
    index.php can catch HttpBadRequestException. It works partially, it show only view without controller action. And when it turns true, I assumed \SecurityException should be catched. But so far, \SecurityException is not catched. It shows a default error message not my view.

    As I showed at the first post, my route.php is same like you. And this time, I changed controller/error.php like following:

     public function action_400(){ //400 Bad Request 
         return Response::forge(View::forge('400'), 400);                                         
    }   

    But result was same. I mean a default error message page appears.

    To confirm, I show you my setting now.

    [ index.php ]
     catch (\SecurityException $e)                                                                                
    {
      $response = $routerequest('_400_', $e);
    }

    [config.php]
      'security' => array(
     'csrf_autoload'            => true,
     'csrf_autoload_methods'    => array('post', 'put', 'delete'),
    'csrf_bad_request_on_fail' => false,
    'csrf_auto_token'          => true,
     'csrf_token_key'           => 'fuel_csrf_token',
     'csrf_expiration'          => 0,

    [routes.php]
    return array(
      '_root_'  => 'index',  
      '_400_'   => 'error/400',                                                      
      '_404_'   => 'error/404', 
      '_500_'   => 'error/500',
    );

    The version of FuelPHP is 1.8. 
  • Is your controller called at all? Did you check the log (and did you set logging to L_ALL)?

    If not, did you check if your index.php catches the exception correctly (add a die() to see)?

    If it does, did you check if the index.php closure finds the correct routing? Get the index.php from 1.9/dev to make sure you have the current code (see https://github.com/fuel/fuel/tree/1.9/develop/public).
  • At first I get 1.9/dev index.php. It makes great change.
    It can catch SecurityException at last! But not 400 but 404 error appears.(only view not controller action)

    New index.php catch SecurityException and I checked correct error was catched by Debug::dump().

    catch (\SecurityException $e)
    {                 
    Debug::dump($e);                                                                             
    $response = $routerequest('_400_', $e);
    }  

    Why this code shows 404 error page?
  • I found one problem.

    Now I can catch SecurityException but controller/error/action_400 doesn't appears.
    So I checked [$response = $routerequest('_400_', $e); ]

    This calls following line in index.php.

    $route = array_key_exists($request, Router::$routes) ? Router::$routes[$request]->translation : Config::get('routes.'.$request); 

    And I checked following part with actual value.
    Config::get('routes.'.'_400_');

    But this doesn't work.And I also check next code at other place.
    Debug::dump(Config::get('routes.'.'_400_'));
    Debug::dump(Config::get('routes'));
    Both returns "null".

    Config::get method can not get routes.php settings.
    How can I fix it?
  • Good question, I'll have to setup new tests for it as I can't reproduce it.
  • Think I found the cause: https://github.com/fuel/core/commit/7fc62869b64a055e1887bd6e31bd0eee9b85a008

    Could you verify if this fixes the problem?
  • I pull the commit and it works. When SecurityException is catched,
    it shows following value:

    Debug::dump(Config::get('routes.'.'_400_'));
    (String): "error/400" (9 characters)

    Debug::dump(Config::get('routes'));
        _root_ (String): "index" (5 characters)
         _400_ (String): "error/400" (9 characters)
         _404_ (String): "error/404" (9 characters)
         _500_ (String): "error/500" (9 characters)

    It is correct value what I want. Your fixes works on this Config::get problem.
  • But new problem comes.
    When SecurityException catched, following error appears.

    ErrorException [ Fatal Error ]:
    Class 'Auth' not found

    This is happen only SecurityException case. Same code works when there is no SecurityException.
    I tried 404 error case, but it was no problem. So far it is only SecurityException case.
    This Auth class is used at view/template.php which Controller_Template use.
    If I comment out where Auth is used, another error comes.

    Fuel\Core\PhpErrorException [ Notice ]:
    Array to string conversion

    <p><?php echo implode('</p><p>', e((array) Session::get_flash('error'))); ?></p>

    When I also comment out this line, error/action_400 shows perfectly.
    It is no problem about routing. But when SecurityException catched, FuelPHP doesn't work correctly. 
  • HarroHarro
    Accepted Answer
    It hasn't autoloaded classes at that point.

    fix here: https://github.com/fuel/core/commit/714f33a82970e17d6ef7a0d7da0ce7d4be39aea0
  • Thanks to your help, it works completely.
    Thank you very much for your help.
  • You're welcome, thanks for reporting the problem.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion