From bf9830d354c5230ad7b552583375c0ba53a32ac2 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Thu, 21 Sep 2023 12:00:17 +0200 Subject: [PATCH] Bug 34478: op-cud - Trick CGI directly Signed-off-by: Jonathan Druart --- C4/Auth.pm | 52 +++++++++++++++++++------------------ Koha/Exceptions/Token.pm | 5 ++++ debian/templates/plack.psgi | 13 ++++++++++ 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 757e97e33a..23c3562d26 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -32,6 +32,7 @@ use C4::Context; use C4::Templates; # to get the template use C4::Languages; use C4::Search::History; +use C4::Output qw( output_and_exit ); use Koha; use Koha::Logger; use Koha::Caches; @@ -53,6 +54,7 @@ use C4::Log qw( logaction ); use Koha::CookieManager; use Koha::Auth::Permissions; use Koha::Token; +use Koha::Exceptions::Token; use Koha::Session; # use utf8; @@ -189,6 +191,7 @@ sub get_template_and_user { $in->{'type'}, undef, $in->{template_name}, + { skip_csrf_check => 1 }, ); } @@ -631,6 +634,16 @@ sub get_template_and_user { $template->param( logged_in_user => $patron ); $template->param( sessionID => $sessionID ); + if ( $in->{query}->param('op-cud') ) { + C4::Output::output_and_exit( $in->{query}, $cookie, $template, 'wrong_csrf_token' ) + unless Koha::Token->new->check_csrf( + { + session_id => scalar $in->{query}->cookie('CGISESSID'), + token => scalar $in->{query}->param('csrf_token'), + } + ); + } + return ( $template, $borrowernumber, $cookie, $flags ); } @@ -791,7 +804,9 @@ sub checkauth { my $type = shift; my $emailaddress = shift; my $template_name = shift; - my $params = shift || {}; # do_not_print + my $params = shift || {}; # do_not_print, skip_csrf_check + + my $skip_csrf_check = $params->{skip_csrf_check} || 0; $type = 'opac' unless $type; if ( $type eq 'opac' && !C4::Context->preference("OpacPublic") ) { @@ -1312,7 +1327,6 @@ sub checkauth { } # finished authentification, now respond - my $auth_template_name = ( $type eq 'opac' ) ? 'opac-auth.tt' : 'auth.tt'; if ( $auth_state eq 'completed' || $authnotrequired ) { # successful login unless (@$cookie) { @@ -1328,35 +1342,22 @@ sub checkauth { my $patron = $userid ? Koha::Patrons->find({ userid => $userid }) : undef; $patron->update_lastseen('login') if $patron; - my $original_op_cud = $query->param('op-cud'); - if ( $request_method eq 'GET' ) { - $query->param('op-cud', undef); - } elsif ( $request_method eq 'POST' ) { - $query->param('op', undef); - } - - if ( defined $original_op_cud ) { + if ( $query->param('op-cud') ) { die "Cannot use GET for this request" - if $request_method ne 'POST'; - - print $query->header( - { - type => 'text/html', - charset => 'utf-8', - cookie => $cookie, - 'X-Frame-Options' => 'SAMEORIGIN', - -sameSite => 'Lax' - } - ); + if $request_method eq 'GET'; - my $template = C4::Templates::gettemplate( $auth_template_name, $type, $query ); - output_and_exit( $query, $cookie, $template, 'wrong_csrf_token' ) - unless Koha::Token->new->check_csrf( + unless ( + $skip_csrf_check + || Koha::Token->new->check_csrf( { session_id => scalar $query->cookie('CGISESSID'), token => scalar $query->param('csrf_token'), } - ); + ) + ) + { + Koha::Exceptions::Token::WrongCSRFToken->throw; + } } # In case, that this request was a login attempt, we want to prevent that users can repost the opac login @@ -1398,6 +1399,7 @@ sub checkauth { $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg; my $auth_error = $query->param('auth_error'); + my $auth_template_name = ( $type eq 'opac' ) ? 'opac-auth.tt' : 'auth.tt'; my $template = C4::Templates::gettemplate( $auth_template_name, $type, $query ); $template->param( login => 1, diff --git a/Koha/Exceptions/Token.pm b/Koha/Exceptions/Token.pm index c7fe147369..92701ebae8 100644 --- a/Koha/Exceptions/Token.pm +++ b/Koha/Exceptions/Token.pm @@ -27,6 +27,11 @@ use Exception::Class ( isa => 'Koha::Exceptions::Token', description => 'Bad pattern for random token generation' }, + 'Koha::Exceptions::Token::WrongCSRFToken' => { + isa => 'Koha::Exceptions::Token', + description => 'Invalid CSRF Token' + }, + ); =head1 NAME diff --git a/debian/templates/plack.psgi b/debian/templates/plack.psgi index 89cd6ef48f..577118148c 100644 --- a/debian/templates/plack.psgi +++ b/debian/templates/plack.psgi @@ -47,6 +47,19 @@ use CGI qw(-utf8 ); # we will loose -utf8 under plack, otherwise $CGI::PARAM_UTF8 = 1; Koha::Caches->flush_L1_caches(); Koha::Cache::Memory::Lite->flush(); + + $original_op_cud = $q->param('op-cud'); + $request_method = $q->request_method // q{}; + if ( $request_method eq 'GET' && defined $original_op_cud ) { + warn "Programming error - op-cud must not be passed with GET"; + $q->param( 'op-cud', undef ); + } elsif ( $request_method ne 'GET' && defined $q->param('op') ) { + warn "Programming error - op can only be passed with GET"; + $q->param( 'op', undef ); + } else { + $q->param( 'op', $original_op_cud ); + } + return $q; }; } -- 2.39.2