WWW::CSRF(3pm)
π WWW::CSRF π
okay bestie, sit DOWN, because we're talking about WWW::CSRF β a little Perl module from the User Contributed Perl Documentation section, and it's literally here to stop bad guys from doing crimes with your users' cookies. no cap. π
β¨ NAME β¨
WWW::CSRF β generate and check tokens to protect against CSRF attacks π‘οΈ
πΈ SYNOPSIS πΈ
first things first, you pull in the goods:
use WWW::CSRF qw(generate_csrf_token check_csrf_token CSRF_OK);
then you make a token and hide it in literally every HTML form as a hidden <input>:
my $csrf_token = generate_csrf_token($username, "s3kr1t");
and then, in any action that has side effects (aka anything that actually does something, bestie), you grab that form field back and check it like this:
my $status = check_csrf_token($username, "s3kr1t", $csrf_token);
die "Wrong CSRF token" unless ($status == CSRF_OK);
that's it. that's the whole flow. iconic. π
π COPYRIGHT π
Copyright 2013 Steinar H. Gunderson.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
π¦ DESCRIPTION π¦
so like. this module generates tokens. tokens that protect your site from a little attack called Cross-Site Request Forgery β CSRF for short, XSRF if you're feeling spicy. πΆοΈ
what even is CSRF? okay so picture this: an attacker fools a browser into making a request to a web server, right? and that browser will automatically include some form of credentials β cookies, cached HTTP Basic authentication, whatever β and boom, the attacker is abusing the web server's trust in the user for malicious use. not the vibe. π
the most common way to mitigate this is sending a special, hard-to-guess token with every request, and then requiring that any request that is not idempotent (i.e., has side effects) must come with such a token. and the way this works is critically dependent on one thing: an attacker can easily make the victim's browser make a request, sure, but the browser security model β the same-origin policy</c>, or SOP for short β prevents third-party sites from reading the results of that request. so they can knock, but they cannot read the mail. πͺ
CSRF tokens should have at least the following properties, and yes this is a list, we love a list:
- They should be hard-to-guess, so they should be signed with some key known only to the server. π
- They should be dependent on the authenticated identity, so that one user cannot use its own tokens to impersonate another user. no identity theft on our watch fr fr.
- They should not be the same for every request, or an attack known as BREACH can use HTTP compression to gradually deduce more and more of the token. scary!! π±
- They should contain an (authenticated) timestamp, so that if an attacker manages to learn one token, he or she cannot impersonate a user indefinitely. β°
and WWW::CSRF simplifies the (simple, but tedious) work of creating and verifying such tokens. tedious work is literally our villain origin story. π§
β οΈ heads up bestie: resources that are protected against CSRF should also be protected against a different attack known as clickjacking. there are many defenses against clickjacking (which ideally should be combined), but a good start is sending aX-Frame-OptionsHTTP header set toDENYorSAMEORIGIN. see the Wikipedia article on clickjacking <http://en.wikipedia.org/wiki/Clickjacking> for more information. π«Ά
This module provides the following functions:
π generate_csrf_token($id, $secret, \%options)
This routine generates a CSRF token to send out to already authenticated users. (Unauthenticated users generally need no CSRF protection, as there are no credentials to impersonate. slay, one less thing.)
$id is the identity you wish to authenticate; usually, this would be a user name of some sort.
$secret is the secret key authenticating the token. This should be protected in the same matter you would protect other server-side secrets, e.g. database passwords β if this leaks out, an attacker can generate CSRF tokens at will. π₯ keep it secret, keep it safe, keep it out of your group chat.
The keys in %options are relatively esoteric and need generally not be set, but currently supported are:
"Time"β for overriding the time value added to the token. If this is not set, the value oftime()is used. β³"Random"β for controlling the random masking value used to protect against the BREACH attack. If set, it must be exactly 20 random bytes; if not, these bytes are generated with a call toBytes::Random::Secure. π²
The returned CSRF token is in a text-only form suitable for inserting into a HTML form without further escaping (assuming you did not send in strange things to the "Time" option). π
π check_csrf_token($id, $secret, $csrf_token, \%options)
This routine checks the integrity and age of the a token generated by "generate_csrf_token". The values of $id and $secret correspond to the same parameters given to "generate_csrf_token", and $csrf_token is the token to verify. Also, you can set one or more of the following options in %options:
"Time"β for overriding the time value used to check the age of the token. If this is not set, the value oftime()is used. β°"MaxAge"β for setting a maximum age for the CSRF token in seconds. If this is negative, no age checking is performed, which is not recommended. The default value is a week, or604800seconds. π¬
This routine returns one of the following constants:
"CSRF_OK"β The token is verified correct. β"CSRF_EXPIRED"β The token has an expired timestamp, but is otherwise valid. π°οΈ"CSRF_INVALID_SIGNATURE"β The token is not properly authenticated; either it was generated using the wrong secret, for the wrong user, or it has been tampered with in-transit. π"CSRF_MALFORMED_TOKEN"β The token is not in the correct format. π
In general, you should only allow the requested action if "check_csrf_token" returns "CSRF_OK". that's the whole rule, don't be out here accepting vibes instead of tokens.
π‘ fun fact that is genuinely useful: you are allowed to call "check_csrf_token" multiple times with e.g. different secrets. This is useful in the case of key rollover, where you change the secret for new tokens, but want to continue accepting old tokens for some time to avoid disrupting operations. it's giving graceful migration, honestly. π¦
β SEE ALSO β
Wikipedia has an article with more information on CSRF:
L<http://en.wikipedia.org/wiki/Cross-site_request_forgery>
and that's the whole page bestie!! πΈ this one's from perl v5.32.0, dated 2021-01-03 β so go forth, sign your tokens, check your tokens, and keep your $secret absolutely nowhere near the internet. mwah. πππ«Ά
π¦ where this page comes from
- debian bookworm: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu jammy: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libwww-csrf-perl 1.00-1.1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms