adbario / slim-csrf

CSRF protection for Slim 3 framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Csrf protection fails when used with secure session

opened this issue · comments

I'm using your csrf protection with your secure session but the csrf check always fails. I've added the middlewares like this:

$app->add($container->get('csrf'));
$app->add(new \AdBar\SessionMiddleware($container['settings']['session']));

The csrf token is created and added to the form correctly.
It seems like the session is cleaned before the csrf token can be validated.
If i start the session with session_start() before middleware declaration, it works.

Hi and thanks for posting. Which version of the script you're using? The lates version requires SessionMiddleware to have Container itself as a first parameter. There will be some bigger changes coming soon when I get extra time to work with this script, already started that.

I'm using latest secure session and i get failed csrf token check when i submit the form. Looking at page source i see the token is added to hidden input and correctly sent on request. Can you check it ? Thank you.

Hi, I just made some updates for the package and it now works a bit differently. I ran some test with Twig-View and PHP-View and everything is working very well. Please read the README for correct settings.

Hello,

I got the same problem and I don't see how to solve it

Hi,

could you share your code with me and the version numbers you're using for csrf and session?

I use the latest versions for both session and csrf middleware and I just apply README instructions

I cannot replicate the issue by following README, so please show me your code for the files that use these parts.

Sorry, I can't show you the code because it's a commercial project but I notice the problem seems to come from the session middleware: it works perfectly in controllers but not in middlewares (need to call session_start())

Your middleware has to be in correct order, so session needs to be started before other middlewares that uses it, which basically means that in code session middleware should be added after them as they are used in reverse order. Also you need to make sure that all middlewares that needs to access sessions, it will be injected from container.

All my middlewares are loaded from container and before Session.
I just check Session access with another empty middleware (coded quickly just for test purpose) and the result is still the same.

So in your code you have these lines with this order?

/** Csrf */
$app->add($app->getContainer()->get('csrf'));

/** Session */
$app->add(new \Adbar\SessionMiddleware($container->get('settings')['session']));

Anyway, I cannot replicate the issue and I would need to see some of your code to help you out.

Also check your page source that the token is added correctly into your form .

Yes, everything is exactly as the README said, the template call too.

Well, I just did a test with a very simple code and it works exactly as it should. This demo uses latest Slim, Twig-View and CSRF. When you find the things you do differently, you'll find why it's not working.

composer require slim/slim
composer require slim/twig-view
composer require adbario/slim-csrf
<?php

/**
 * index.php
 */

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

require __DIR__ . '/../vendor/autoload.php';

/** SETUP */

// Settings
$settings = [
    'session' => [
        // Session cookie settings
        'name'           => 'slim_session',
        'lifetime'       => 24,
        'path'           => '/',
        'domain'         => null,
        'secure'         => false,
        'httponly'       => true,

        // Set session cookie path, domain and secure automatically
        'cookie_autoset' => true,

        // Path where session files are stored, PHP's default path will be used if set null
        'save_path'      => null,

        // Session cache limiter
        'cache_limiter'  => 'nocache',

        // Extend session lifetime after each user activity
        'autorefresh'    => false,

        // Encrypt session data if string is set
        'encryption_key' => null,

        // Session namespace
        'namespace'      => 'slim_app'
    ]
];

// Init App
$app = new \Slim\App(['settings' => $settings]);


/** DEPENDENCIES */

// Get Container
$container = $app->getContainer();

// Twig-View
$container['view'] = function ($container) {
    $view = new \Slim\Views\Twig(__DIR__ . '/../templates', [
        'cache' => false
    ]);

    // Instantiate and add Slim specific extension
    $basePath = rtrim(str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()), '/');
    $view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));

    return $view;
};

// Session
$container['session'] = function ($container) {
    return new \Adbar\Session(
        $container->get('settings')['session']['namespace']
    );
};

// CSRF
$container['csrf'] = function ($container) {
    return new \Adbar\Slim\Csrf(
        $container->get('session'),
        $container->get('view')
    );
};


/** MIDDLEWARE */

// CSRF
$app->add($container->get('csrf'));

// Session
$app->add(new \Adbar\SessionMiddleware($settings['session']));


/** ROUTES */
$app->any('/', function (Request $request, Response $response) {
    return $this->view->render($response, 'home.twig');
});


/** RUN APP */
$app->run();
{# home.twig #}

<h1>This is CSRF test</h1>

<form method="post">
    {{ csrf|raw }}
    <input type="submit" value="Send">
</form>

Ok, I have a better idea of where the problem is: the browser.
From the beginning, I use Chromium (or Google Chrome) to test my project, I just tested it with Firefox and everything working well !
Also, I tried your test on Chromium and Firefox and the result was the same: CSRF validation always fails with Chromium but works well with Firefox.

You have definitely something strange going on with your Chrome then, as this is all server side. And my Chrome (59.0.3071.109) on Mac works fine. Browser testing should be one of the first things to do when troubleshooting :)

At least try to reset all your browser settings.

Very strange, I have exactly the same Chrome version as you but on Linux...
(Tested on Windows too, same result)

Also, I notice that Chrome send 2 requests (2 log entries per refresh), 1 second apart

commented

I solved a similar problem, looking for any code that calls the PHP function "session_write_close()",
I found that one of the middlewares I was using caused the error,
it somehow "closes" the session before the csrf tokens have been saved.
I haven't had time to investigate the issue thoroughly, but I'll leave this comment in case anyone would find it helpful.