Bug 17720: CSRF - Handle unicode characters

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

Signed-off-by: Josef Moravec <josef.moravec@gmail.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Edit: removed debugging leftover

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
This commit is contained in:
Jonathan Druart 2016-12-05 08:17:21 +00:00 committed by Kyle M Hall
parent 59a322ae70
commit 8edb7f6fb9
9 changed files with 27 additions and 21 deletions

View File

@ -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') ) ),
}
),
);

View File

@ -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 );

View File

@ -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') ) ),
}),
);

View File

@ -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') ) ),
}
),
);

View File

@ -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') ) ),
}),
);

View File

@ -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') ) ),
}),
);

View File

@ -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') ) ),
}
),
);

View File

@ -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') ) ),
}
),
);

View File

@ -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;