NAME

Plack::Middleware::XSRFBlock - Block XSRF Attacks with minimal changes to your app

VERSION

version 0.0.19

SYNOPSIS

The simplest way to use the plugin is:

use Plack::Builder;

my $app = sub { ... };

builder {
    enable 'XSRFBlock';
    $app;
}

You may also over-ride any, or all of these values:

builder {
    enable 'XSRFBlock',
        parameter_name          => 'xsrf_token',
        cookie_name             => 'PSGI-XSRF-Token',
        cookie_options          => {},
        cookie_expiry_seconds   => (3 * 60 * 60),
        token_per_request       => 0,
        meta_tag                => undef,
        inject_form_input       => 1,
        header_name             => undef,
        secret                  => undef,
        http_method_regex       => qr{^post$}i,
        contents_to_filter_regex => qr{^(text/html|application/xhtml(?:\+xml)?)\b}i,
        blocked                 => sub {
                                    return [ $status, $headers, $body ]
                                },
    ;
    $app;
}

DESCRIPTION

This middleware blocks XSRF. You can use this middleware without any modifications to your application.

OPTIONS

ERRORS

The module emits various errors based on the cause of the XSRF detected. The messages will be of the form XSRF detected [reason]

detect_xsrf($self, $request, $env)

returns a message explaining the XSRF-related problem, or undef if there's no problem

should_be_filtered($self, $request, $env, $res)

returns true if the response should be filtered by this middleware (currently, if its content-type matches contents_to_filter_regex)

generate_token($self, $request, $env, $res)

Returns the token value to use for this response.

If the cookie is already set, and we do not want a different token for each request, returns the cookie's value.

Otherwise, generates a new value based on some random data. If secret is set, the value is also signed.

sets the given token as a cookie in the response

filter_response_html($self, $request, $env, $res, $token)

Filters the response, injecting <input> elements with the token value into all forms whose method matches http_method_regex.

Streaming responses are still streaming after the filtering.

filter_response($self, $request, $env)

Calls the application, and (if the response "should_be_filtered"), it injects the token in the cookie and (if "inject_form_input") the forms.

invalid_signature($self, $value)

Returns true if the value is not correctly signed. If we're not signing tokens, this method always returns false.

xsrf_detected($self, $args)

Invoked when the XSRF is detected. Calls the "blocked" coderef if we have it, or returns a 403.

The blocked coderef is invoked like:

$self->blocked->($env,$msg, app => $self->app);

log($self, $level, $msg)

log through the PSGI logger, if defined

EXPLANATION

This module is similar in nature and intention to Plack::Middleware::CSRFBlock but implements the xSRF prevention in a different manner.

The solution implemented in this module is based on a CodingHorror article - Preventing CSRF and XSRF Attacks.

The driving comment behind this implementation is from the Felten and Zeller paper:

When a user visits a site, the site should generate a (cryptographically
strong) pseudorandom value and set it as a cookie on the user's machine.
The site should require every form submission to include this pseudorandom
value as a form value and also as a cookie value. When a POST request is
sent to the site, the request should only be considered valid if the form
value and the cookie value are the same.  When an attacker submits a form
on behalf of a user, he can only modify the values of the form. An
attacker cannot read any data sent from the server or modify cookie
values, per the same-origin policy.  This means that while an attacker can
send any value he wants with the form, he will be unable to modify or read
the value stored in the cookie. Since the cookie value and the form value
must be the same, the attacker will be unable to successfully submit a
form unless he is able to guess the pseudorandom value.

What's wrong with Plack::Middleware::CSRFBlock?

Plack::Middleware::CSRFBlock is a great module. It does a great job of preventing CSRF behaviour with minimal effort.

However when we tried to use it uses the session to store information - which works well most of the time but can cause issues with session timeouts or removal (for any number of valid reasons) combined with logging (back) in to the application in another tab (so as not to interfere with the current screen/tab state).

Trying to modify the existing module to provide the extra functionality and behaviour we decided worked better for our use seemed too far reaching to try to force into the existing module.

FURTHER READING

SEE ALSO

Plack::Middleware::CSRFBlock, Plack::Middleware, Plack

BUILD STATUS

Build Status

AUTHOR

Chisel chisel@chizography.net

COPYRIGHT AND LICENSE

This software is copyright (c) 2023 by Chisel Wright.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

CONTRIBUTORS