Derrek Bertrand
Derrek Bertrand

Reputation: 626

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?

Upvotes: 0

Views: 960

Answers (2)

Derrek Bertrand
Derrek Bertrand

Reputation: 626

So the above answer is almost there, but it has the following flaws:

  • It requires its own config type. No go; we just want production to be immune. Anything else should be stress-testable in place.
  • It doesn't cover FAKE_CSRF_TOKEN being not defined by a sloppy dev
  • It must be able to be committed to the primary tree! Git is a common deployment mechanism, and as little as possible should be outside VCS

So I defined the function as such:

protected function tokensMatch($request)
{
    $parent = parent::tokensMatch($request);

    //if it isn't an actual token match, and we aren't on production
    if (! $parent && 'production' !== env('APP_ENV')) {
        //then get the token
        $token = $request->input('_token');
        $fake = env('FAKE_CSRF_TOKEN');

        //and test it versus our fake
        //it must actually be defined to work (no blanks)
        //generate an actual random string for security!
        if(strlen($fake) && $token === $fake)
            return true;
    }

    //otherwise, just return what we normally would
    return $parent;
}

Upvotes: 0

morphatic
morphatic

Reputation: 7975

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.

Upvotes: 1

Related Questions