Bug 34369: Require CSRF token for updating system preferences

This patch adds the requirements that updating a system preference
requires a CSRF token. (Also, adding and deleting local system preferences.)

0. Apply patch
1. koha-plack --reload kohadev
2. Add local system preference
3. Update local system preference
4. Delete local system preference
5. Update normal system preference
6. Note no errors

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
David Cook 2023-08-01 06:56:23 +00:00 committed by Tomas Cohen Arazi
parent 4e32b76198
commit c6ef2aba6b
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
6 changed files with 33 additions and 2 deletions

View file

@ -25,7 +25,7 @@ use C4::Context;
use C4::Koha qw( getallthemes );
use C4::Languages qw( getTranslatedLanguages );
use C4::ClassSource qw( GetClassSources GetClassSource );
use C4::Output qw( output_html_with_http_headers );
use C4::Output qw( output_html_with_http_headers output_and_exit_if_error );
use C4::Templates;
use Koha::Acquisition::Currencies;
use Koha::Database::Columns;
@ -354,6 +354,7 @@ $tab ||= 'accounting'; # Ideally this should be "local-use" but preferences.pl
my $highlighted;
if ( $op eq 'save' ) {
output_and_exit_if_error($input, $cookie, $template, { check => 'csrf_token' });
foreach my $param ( $input->param() ) {
my ( $pref ) = ( $param =~ /pref_(.*)/ );

View file

@ -49,7 +49,7 @@ use C4::Context;
use C4::Koha qw( getallthemes );
use C4::Languages qw( getTranslatedLanguages );
use C4::ClassSource qw( GetClassSources GetClassSource );
use C4::Output qw( output_html_with_http_headers );
use C4::Output qw( output_html_with_http_headers output_and_exit_if_error );
use YAML::XS;
my %tabsysprefs; #we do no longer need to keep track of a tab per pref (yaml)
@ -235,6 +235,7 @@ if ($op) {
}
if ( $op eq 'update_and_reedit' ) {
output_and_exit_if_error($input, $cookie, $template, { check => 'csrf_token' });
foreach ( $input->param ) {
}
my $value = '';
@ -302,6 +303,7 @@ if ( $op eq 'add_form' ) {
################## ADD_VALIDATE ##################################
# called by add_form, used to insert/modify data in DB
} elsif ( $op eq 'add_validate' ) {
output_and_exit_if_error($input, $cookie, $template, { check => 'csrf_token' });
# to handle multiple values
my $value;
@ -348,6 +350,7 @@ if ( $op eq 'add_form' ) {
################## DELETE_CONFIRMED ##################################
# called by delete_confirm, used to effectively confirm deletion of data in DB
} elsif ( $op eq 'delete_confirmed' ) {
output_and_exit_if_error($input, $cookie, $template, { check => 'csrf_token' });
C4::Context->delete_preference($searchfield);
# END $OP eq DELETE_CONFIRMED
################## DEFAULT ##################################

View file

@ -58,6 +58,7 @@
<div class="prefs-tab">
<h2>[% TAB.tab_title | html %] preferences</h2>
<form action="/cgi-bin/koha/admin/preferences.pl" method="post">
[% INCLUDE 'csrf-token.inc' %]
[% UNLESS ( searchfield ) %]<div id="toolbar"><button class="save-all btn btn-primary" type="submit">Save all [% TAB.tab_title | html %] preferences</button></div>[% END %]
<input type="hidden" name="op" value="save" />
<input type="hidden" name="tab" value="[% TAB.tab_id | html %]" />

View file

@ -75,6 +75,8 @@
[% END #/ WRAPPER breadcrumbs %]
[% END #/ WRAPPER sub-header.inc %]
[% INCLUDE 'blocking_errors.inc' %]
<div class="main container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-push-2">
@ -94,6 +96,7 @@
[% ELSE %]
<form action="[% script_name | html %]" name="Aform" method="post">
[% END %]
[% INCLUDE 'csrf-token.inc' %]
<fieldset class="rows">
<legend class="sr-only">System preference details</legend>
<ol>
@ -279,6 +282,7 @@
</tr>
</table>
<form class="inline" action="[% script_name | html %]" method="post">
[% INCLUDE 'csrf-token.inc' %]
<input type="hidden" name="op" value="delete_confirmed" />
<input type="hidden" name="searchfield" value="[% searchfield | html %]" />
<input type="hidden" name="Tvalue" value="[% Tvalue | html %]" />
@ -333,6 +337,7 @@
[% ELSE %]
<form action="/cgi-bin/koha/admin/systempreferences.pl" method="post">
[% END %]
[% INCLUDE 'csrf-token.inc' %]
[% IF ( loo.type_free ) %]
<input type="text" name="value" size="[% loo.fieldlength | html %]" value="[% loo.value | html %]" />
[% END %]

View file

@ -25,6 +25,13 @@ KOHA.Preferences = {
humanMsg.displayAlert( __("Nothing to save") );
return;
}
let csrf_token_el = $( form ).find('input[name="csrf_token"]');
if (csrf_token_el.length > 0){
let csrf_token = csrf_token_el.val();
if (csrf_token){
data += '&' + 'csrf_token=' + csrf_token;
}
}
KOHA.AJAX.MarkRunning($(form).find('.save-all'), __("Saving...") );
KOHA.AJAX.Submit( {
data: data,

View file

@ -23,6 +23,7 @@ use Modern::Perl;
use C4::Context;
use C4::Service;
use C4::Log;
use Koha::Token;
=head1 NAME
@ -63,6 +64,12 @@ Used to set a single system preference.
sub set_preference {
my ( $preference ) = @_;
die "wrong_csrf_token\n" unless Koha::Token->new->check_csrf(
{
session_id => scalar $query->cookie('CGISESSID'),
token => scalar $query->param('csrf_token'),
}
);
my $value = join( ',', $query->param( 'value' ) );
C4::Context->set_preference( $preference, $value );
@ -122,6 +129,13 @@ pref_virtualshelves=0
=cut
sub set_preferences {
die "wrong_csrf_token\n" unless Koha::Token->new->check_csrf(
{
session_id => scalar $query->cookie('CGISESSID'),
token => scalar $query->param('csrf_token'),
}
);
foreach my $param ( $query->param() ) {
my ( $pref ) = ( $param =~ /pref_(.*)/ );