laravellaravel-5benchmarkingstress-testingsiege

Run siege tests on Laravel 5


So I have a laravel 5 project, and I'd like to benchmark the test server I'm using with the siege tool.

Unfortunately, I've realized you can't log in because the CSRF is normally received from the submission form. There is no form in siege, so this token can't be sent.

I can see this being tackled in a few ways, but I'm looking for something that can be left in source control and not negatively affect security. What is a good way to get siege to work with Laravel without a bunch of maintenance or just being lazy and disabling CSRF?


Solution

  • Two things:

    1. You CAN set siege up to log into your site. See this ServerFault post for more info, but this would only test your login form.
    2. You CAN, using the same method, send the _token parameter with any request

    Apparently, the documentation for this is found in the comments in the code, not in the official manual.

    The question you're left with is what value to pass with the _token variable. Obviously, a fake value is exactly the kind of thing that CSRF is supposed to protect against. I think the easiest way to do this is going to be to modify app/Http/Middleware/VerifyCsrfToken.php to add a special condition that will "match" against a pre-set value.

    First thing I would do is to create a variable in my .env file that contains my face CSRF token, e.g.

    FAKE_CSRF_TOKEN=dd0dda7d4b5e92fafd9e5bebfabd7709
    

    And then in App\Http\Middleware\VerifyCsrfToken (i.e. the file I referred to above), you would override the tokensMatch($request) function. You might do something like:

    protected function tokensMatch($request)
    {
        $parent = parent::tokensMatch($request);
        $token = $request->input('_token');
        return $parent || $token == env('FAKE_CSRF_TOKEN');
    }
    

    Then in your tests, just always pass your fake CSRF token value as _token. Of course,

    This code should never be run on a production server!

    If it was me, I might create a special .env.siege file and set APP_ENV=siege on my testing or staging server. Then I would re-write the above tokensMatch() function to do something like this:

    protected function tokensMatch($request)
    {
        $parent = parent::tokensMatch($request);
        if ('siege' === env('APP_ENV')) {
            $token = $request->input('_token');
            return $parent || $token == env('FAKE_CSRF_TOKEN');
        }
        return $parent;
    }
    

    That way, even if this altered middleware somehow made it onto your production server, you'd have some extra protection against a fake CSRF attack. The end result is that you'll be able to stress test your server almost exactly as if it were in a production environment, without disabling CSRF.

    All this being said, I don't know how resource-intensive CSRF checks actually are in practice. It might just be simpler to turn CSRF off for your stress test, rather than making the changes I suggest here.