From 876b5ee795bbaa7e8a5b5214e410d1b2648b41b6 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Mon, 5 Dec 2016 08:17:21 +0000 Subject: [PATCH] Bug 17720: CSRF - Handle unicode characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the pod of Digest::MD5: """ Since the MD5 algorithm is only defined for strings of bytes, it can not be used on strings that contains chars with ordinal number above 255 (Unicode strings). The MD5 functions and methods will croak if you try to feed them such input data. What you can do is calculate the MD5 checksum of the UTF-8 representation of such strings. """ Test plan: - Set a MySQL/MariaDB password with unicode characters: UPDATE user SET password=PASSWORD('❤') WHERE USER='koha_kohadev'; FLUSH PRIVILEGES - Update your $KOHA_CONF file - Restart Memcached - Hit the files modified by this patch => Without this patch, you will get a software error (with "Wide character in subroutine entry" in the logs). => With this patch, everything will go fine --- basket/sendbasket.pl | 4 ++-- members/deletemem.pl | 5 +++-- members/member-password.pl | 5 +++-- members/memberentry.pl | 5 +++-- members/moremember.pl | 3 ++- opac/opac-memberentry.pl | 9 +++++---- opac/opac-sendbasket.pl | 4 ++-- t/db_dependent/Koha/Patrons.t | 1 + tools/import_borrowers.pl | 6 +++--- tools/picture-upload.pl | 7 ++++--- 10 files changed, 28 insertions(+), 21 deletions(-) diff --git a/basket/sendbasket.pl b/basket/sendbasket.pl index 040ae09..faeebf4 100755 --- a/basket/sendbasket.pl +++ b/basket/sendbasket.pl @@ -53,7 +53,7 @@ my $dbh = C4::Context->dbh; if ( $email_add ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $query->param('csrf_token'), }); my $email = Koha::Email->new(); @@ -178,7 +178,7 @@ else { virtualshelves => C4::Context->preference("virtualshelves"), csrf_token => Koha::Token->new->generate_csrf( { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), } ), ); diff --git a/members/deletemem.pl b/members/deletemem.pl index b51c721..c764f35 100755 --- a/members/deletemem.pl +++ b/members/deletemem.pl @@ -26,6 +26,7 @@ use strict; use CGI qw ( -utf8 ); use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); use C4::Context; use C4::Output; use C4::Auth; @@ -148,7 +149,7 @@ if ( $op eq 'delete_confirm' or $countissues > 0 or $flags->{'CHARGES'} or $is_ op => 'delete_confirm', csrf_token => Koha::Token->new->generate_csrf( { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), } ), ); @@ -158,7 +159,7 @@ if ( $op eq 'delete_confirm' or $countissues > 0 or $flags->{'CHARGES'} or $is_ die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); my $patron = Koha::Patrons->find( $member ); diff --git a/members/member-password.pl b/members/member-password.pl index d2255f8..82cd642 100755 --- a/members/member-password.pl +++ b/members/member-password.pl @@ -21,6 +21,7 @@ use Koha::Token; use Koha::Patron::Categories; use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); my $input = new CGI; @@ -69,7 +70,7 @@ if ( $newpassword && !scalar(@errors) ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); @@ -151,7 +152,7 @@ $template->param( RoutingSerials => C4::Context->preference('RoutingSerials'), csrf_token => Koha::Token->new->generate_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); diff --git a/members/memberentry.pl b/members/memberentry.pl index 27e6687..61ebed9 100755 --- a/members/memberentry.pl +++ b/members/memberentry.pl @@ -26,6 +26,7 @@ use warnings; use CGI qw ( -utf8 ); use List::MoreUtils qw/uniq/; use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); # internal modules use C4::Auth; @@ -290,7 +291,7 @@ if ($op eq 'save' || $op eq 'insert'){ die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); @@ -752,7 +753,7 @@ $template->param( $template->param( csrf_token => Koha::Token->new->generate_csrf( { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), } ), ); diff --git a/members/moremember.pl b/members/moremember.pl index 0661d0f..70aed84 100755 --- a/members/moremember.pl +++ b/members/moremember.pl @@ -37,6 +37,7 @@ use strict; #use warnings; FIXME - Bug 2505 use CGI qw ( -utf8 ); use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); use C4::Context; use C4::Auth; use C4::Output; @@ -275,7 +276,7 @@ $template->param( picture => 1 ) if $patron_image; $template->param( csrf_token => Koha::Token->new->generate_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); diff --git a/opac/opac-memberentry.pl b/opac/opac-memberentry.pl index e03d503..59306bc 100755 --- a/opac/opac-memberentry.pl +++ b/opac/opac-memberentry.pl @@ -19,6 +19,7 @@ use Modern::Perl; use CGI qw ( -utf8 ); use Digest::MD5 qw( md5_base64 md5_hex ); +use Encode qw( encode ); use String::Random qw( random_string ); use C4::Auth; @@ -200,7 +201,7 @@ elsif ( $action eq 'update' ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => $borrower->{userid}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $cgi->param('csrf_token'), }); @@ -221,7 +222,7 @@ elsif ( $action eq 'update' ) { borrower => \%borrower, csrf_token => Koha::Token->new->generate_csrf({ id => $borrower->{userid}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); @@ -262,7 +263,7 @@ elsif ( $action eq 'update' ) { borrower => GetMember( borrowernumber => $borrowernumber ), csrf_token => Koha::Token->new->generate_csrf({ id => $borrower->{userid}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); } @@ -285,7 +286,7 @@ elsif ( $action eq 'edit' ) { #Display logged in borrower's data hidden => GetHiddenFields( $mandatory, 'modification' ), csrf_token => Koha::Token->new->generate_csrf({ id => $borrower->{userid}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); diff --git a/opac/opac-sendbasket.pl b/opac/opac-sendbasket.pl index 77fc370..25b6eac 100755 --- a/opac/opac-sendbasket.pl +++ b/opac/opac-sendbasket.pl @@ -55,7 +55,7 @@ my $dbh = C4::Context->dbh; if ( $email_add ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $query->param('csrf_token'), }); my $email = Koha::Email->new(); @@ -198,7 +198,7 @@ else { virtualshelves => C4::Context->preference("virtualshelves"), csrf_token => Koha::Token->new->generate_csrf( { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), } ), ); diff --git a/t/db_dependent/Koha/Patrons.t b/t/db_dependent/Koha/Patrons.t index 7be731c..89bcd8a 100644 --- a/t/db_dependent/Koha/Patrons.t +++ b/t/db_dependent/Koha/Patrons.t @@ -71,6 +71,7 @@ is( $retrieved_patron_1->cardnumber, $new_patron_1->cardnumber, 'Find a patron b subtest 'guarantees' => sub { plan tests => 8; my $guarantees = $new_patron_1->guarantees; + use Data::Printer colored => 1; warn p $guarantees->unblessed; is( ref($guarantees), 'Koha::Patrons', 'Koha::Patron->guarantees should return a Koha::Patrons result set in a scalar context' ); is( $guarantees->count, 0, 'new_patron_1 should have 0 guarantee' ); my @guarantees = $new_patron_1->guarantees; diff --git a/tools/import_borrowers.pl b/tools/import_borrowers.pl index f5a7921..f22f2ef 100755 --- a/tools/import_borrowers.pl +++ b/tools/import_borrowers.pl @@ -59,8 +59,8 @@ use Text::CSV; # č use CGI qw ( -utf8 ); -# use encoding 'utf8'; # don't do this use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); my (@errors, @feedback); my $extended = C4::Context->preference('ExtendedPatronAttributes'); @@ -113,7 +113,7 @@ if ( $uploadborrowers && length($uploadborrowers) > 0 ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); @@ -392,7 +392,7 @@ if ( $uploadborrowers && length($uploadborrowers) > 0 ) { $template->param( csrf_token => Koha::Token->new->generate_csrf( { id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), } ), ); diff --git a/tools/picture-upload.pl b/tools/picture-upload.pl index 7e403bb..87cac77 100755 --- a/tools/picture-upload.pl +++ b/tools/picture-upload.pl @@ -26,6 +26,7 @@ use File::Copy; use CGI qw ( -utf8 ); use GD; use Digest::MD5 qw(md5_base64); +use Encode qw( encode ); use C4::Context; use C4::Auth; use C4::Output; @@ -88,7 +89,7 @@ if ( ( $op eq 'Upload' ) && $uploadfile ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); @@ -176,7 +177,7 @@ elsif ( $op eq 'Delete' ) { die "Wrong CSRF token" unless Koha::Token->new->check_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), token => scalar $input->param('csrf_token'), }); @@ -195,7 +196,7 @@ else { $template->param( csrf_token => Koha::Token->new->generate_csrf({ id => C4::Context->userenv->{id}, - secret => md5_base64( C4::Context->config('pass') ), + secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ), }), ); output_html_with_http_headers $input, $cookie, $template->output; -- 2.1.4