From 842ac4647276ba5354289082adbdca75e0b19107 Mon Sep 17 00:00:00 2001 From: Vitaly Belekhov Date: Thu, 4 Jan 2018 22:50:05 +0700 Subject: Bug 1301887 - File::Slurp triggers warnings on perl 5.24 (#53) * Bug 1301887 - File::Slurp triggers warnings on perl 5.24 and it is recommended to not use it (#21) r=mtyson * Fix for vrite in aa735d4 * Added https://gitweb.gentoo.org/proj/gentoo-bugzilla.git/commit/?id=ca7bfc9c485c959fad2aee1f7c1dbc0fb484553b --- Bugzilla/Config.pm | 9 ++++----- Bugzilla/Install/Filesystem.pm | 3 +-- Bugzilla/Install/Requirements.pm | 5 ----- Bugzilla/JobQueue.pm | 6 +++--- Bugzilla/Template.pm | 17 ++++++++--------- Bugzilla/Util.pm | 27 ++++++++++++++++++++++++++- 6 files changed, 42 insertions(+), 25 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm index 1c02d9dda..458616701 100644 --- a/Bugzilla/Config.pm +++ b/Bugzilla/Config.pm @@ -16,10 +16,9 @@ use autodie qw(:default); use Bugzilla::Constants; use Bugzilla::Hook; -use Bugzilla::Util qw(trick_taint); +use Bugzilla::Util qw(trick_taint read_text write_text); use JSON::XS; -use File::Slurp; use File::Temp; use File::Basename; @@ -284,7 +283,7 @@ sub write_params { my $param_file = bz_locations()->{'datadir'} . '/params.json'; my $json_data = JSON::XS->new->canonical->pretty->encode($param_data); - write_file($param_file, { binmode => ':utf8', atomic => 1 }, \$json_data); + write_text($param_file, $json_data); # It's not common to edit parameters and loading # Bugzilla::Install::Filesystem is slow. @@ -301,8 +300,8 @@ sub read_param_file { my $file = bz_locations()->{'datadir'} . '/params.json'; if (-e $file) { - my $data; - read_file($file, binmode => ':utf8', buf_ref => \$data); + my $data = read_text($file); + trick_taint($data); # If params.json has been manually edited and e.g. some quotes are # missing, we don't want JSON::XS to leak the content of the file diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 43512e79c..d30ae18dc 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -31,7 +31,6 @@ use File::Path; use File::Basename; use File::Copy qw(move); use File::Spec; -use File::Slurp; use IO::File; use POSIX (); @@ -536,7 +535,7 @@ sub update_filesystem { # Remove old assets htaccess file to force recreation with correct values. if (-e "$assetsdir/.htaccess") { - if (read_file("$assetsdir/.htaccess") =~ //) { + if (read_text("$assetsdir/.htaccess") =~ //) { unlink("$assetsdir/.htaccess"); } } diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index a688a0ffa..61496d843 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -155,11 +155,6 @@ sub REQUIRED_MODULES { module => 'Math::Random::ISAAC', version => '1.0.1', }, - { - package => 'File-Slurp', - module => 'File::Slurp', - version => '9999.13', - }, { package => 'JSON-XS', module => 'JSON::XS', diff --git a/Bugzilla/JobQueue.pm b/Bugzilla/JobQueue.pm index d5ceda8e9..6ff85d84f 100644 --- a/Bugzilla/JobQueue.pm +++ b/Bugzilla/JobQueue.pm @@ -14,8 +14,8 @@ use warnings; use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Install::Util qw(install_string); +use Bugzilla::Util qw(read_text); use File::Basename; -use File::Slurp; use base qw(TheSchwartz); use fields qw(_worker_pidfile); @@ -124,7 +124,7 @@ sub subprocess_worker { # And poll the PID to detect when the working has finished. # We do this instead of system() to allow for the INT signal to # interrup us and trigger kill_worker(). - my $pid = read_file($self->{_worker_pidfile}, err_mode => 'quiet'); + my $pid = read_text($self->{_worker_pidfile}, err_mode => 'quiet'); if ($pid) { sleep(3) while(kill(0, $pid)); } @@ -139,7 +139,7 @@ sub subprocess_worker { sub kill_worker { my $self = Bugzilla->job_queue(); if ($self->{_worker_pidfile} && -e $self->{_worker_pidfile}) { - my $worker_pid = read_file($self->{_worker_pidfile}); + my $worker_pid = read_text($self->{_worker_pidfile}); if ($worker_pid && kill(0, $worker_pid)) { $self->debug("Stopping worker process"); system "$0 -f -p '" . $self->{_worker_pidfile} . "' stop"; diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 41b9265c6..decffe1e8 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -32,7 +32,6 @@ use Digest::MD5 qw(md5_hex); use File::Basename qw(basename dirname); use File::Find; use File::Path qw(rmtree mkpath); -use File::Slurp; use File::Spec; use IO::Dir; use List::MoreUtils qw(firstidx); @@ -502,7 +501,7 @@ sub _concatenate_css { next unless -e "$cgi_path/$files{$source}"; my $file = $skins_path . '/' . md5_hex($source) . '.css'; if (!-e $file) { - my $content = read_file("$cgi_path/$files{$source}"); + my $content = read_text("$cgi_path/$files{$source}"); # minify $content =~ s{/\*.*?\*/}{}sg; # comments @@ -512,7 +511,7 @@ sub _concatenate_css { # rewrite urls $content =~ s{url\(([^\)]+)\)}{_css_url_rewrite($source, $1)}eig; - write_file($file, "/* $files{$source} */\n" . $content . "\n"); + write_text($file, "/* $files{$source} */\n" . $content . "\n"); } push @minified, $file; } @@ -522,9 +521,9 @@ sub _concatenate_css { if (!-e $file) { my $content = ''; foreach my $source (@minified) { - $content .= read_file($source); + $content .= read_text($source); } - write_file($file, $content); + write_text($file, $content); } $file =~ s/^\Q$cgi_path\E\///o; @@ -563,7 +562,7 @@ sub _concatenate_js { next unless -e "$cgi_path/$files{$source}"; my $file = $skins_path . '/' . md5_hex($source) . '.js'; if (!-e $file) { - my $content = read_file("$cgi_path/$files{$source}"); + my $content = read_text("$cgi_path/$files{$source}"); # minimal minification $content =~ s#/\*.*?\*/##sg; # block comments @@ -572,7 +571,7 @@ sub _concatenate_js { $content =~ s#\n{2,}#\n#g; # blank lines $content =~ s#(^\s+|\s+$)##g; # whitespace at the start/end of file - write_file($file, ";/* $files{$source} */\n" . $content . "\n"); + write_text($file, ";/* $files{$source} */\n" . $content . "\n"); } push @minified, $file; } @@ -582,9 +581,9 @@ sub _concatenate_js { if (!-e $file) { my $content = ''; foreach my $source (@minified) { - $content .= read_file($source); + $content .= read_text($source); } - write_file($file, $content); + write_text($file, $content); } $file =~ s/^\Q$cgi_path\E\///o; diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 5fe64621b..57ce5f6b6 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -24,7 +24,7 @@ use parent qw(Exporter); validate_email_syntax check_email_syntax clean_text get_text template_var display_value disable_utf8 detect_encoding email_filter - join_activity_entries); + join_activity_entries read_text write_text); use Bugzilla::Constants; use Bugzilla::RNG qw(irand); @@ -39,6 +39,8 @@ use Scalar::Util qw(tainted blessed); use Text::Wrap; use Encode qw(encode decode resolve_alias); use Encode::Guess; +use File::Basename qw(dirname); +use File::Temp qw(tempfile); sub trick_taint { require Carp; @@ -106,6 +108,29 @@ sub html_quote { return $var; } +sub read_text { + my ($filename) = @_; + open my $fh, '<:encoding(utf-8)', $filename; + local $/ = undef; + my $content = <$fh>; + close $fh; + return $content; +} + +sub write_text { + my ($filename, $content) = @_; + my ($tmp_fh, $tmp_filename) = tempfile('.tmp.XXXXXXXXXX', + DIR => dirname($filename), + UNLINK => 0, + ); + binmode $tmp_fh, ':encoding(utf-8)'; + print $tmp_fh $content; + close $tmp_fh; + # File::Temp tries for secure files, but File::Slurp used the umask. + chmod(0666 & ~umask, $tmp_filename); + rename $tmp_filename, $filename; +} + sub html_light_quote { my ($text) = @_; # admin/table.html.tmpl calls |FILTER html_light| many times. -- cgit v1.2.1 From 7b7a210cd57140e85c36c9c5bfed35389f7952d5 Mon Sep 17 00:00:00 2001 From: Dylan William Hardison Date: Fri, 16 Feb 2018 11:37:21 -0500 Subject: Bug 1433400 (CVE-2018-5123) Prevent cross-site image requests from leaking contents of certain fields due to regex search r=jfearn,a=dylan --- Bugzilla/CGI.pm | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'Bugzilla') diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index 44c089a20..9b1ff9235 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -288,6 +288,69 @@ sub close_standby_message { } } +our $ALLOW_UNSAFE_RESPONSE = 0; +# responding to text/plain or text/html is safe +# responding to any request with a referer header is safe +# some things need to have unsafe responses (attachment.cgi) +# everything else should get a 403. +sub _prevent_unsafe_response { + my ($self, $headers) = @_; + my $safe_content_type_re = qr{ + ^ (*COMMIT) # COMMIT makes the regex faster + # by preventing back-tracking. see also perldoc pelre. + # application/x-javascript, xml, atom+xml, rdf+xml, xml-dtd, and json + (?: application/ (?: x(?: -javascript | ml (?: -dtd )? ) + | (?: atom | rdf) \+ xml + | json ) + # text/csv, text/calendar, text/plain, and text/html + | text/ (?: c (?: alendar | sv ) + | plain + | html ) + # used for HTTP push responses + | multipart/x-mixed-replace) + }sx; + my $safe_referer_re = do { + # Note that urlbase must end with a /. + # It almost certainly does, but let's be extra careful. + my $urlbase = correct_urlbase(); + $urlbase =~ s{/$}{}; + qr{ + # Begins with literal urlbase + ^ (*COMMIT) + \Q$urlbase\E + # followed by a slash or end of string + (?: / + | $ ) + }sx + }; + + return if $ALLOW_UNSAFE_RESPONSE; + + if (Bugzilla->usage_mode == USAGE_MODE_BROWSER) { + # Safe content types are ones that arn't images. + # For now let's assume plain text and html are not valid images. + my $content_type = $headers->{'-type'} // $headers->{'-content_type'} // 'text/html'; + my $is_safe_content_type = $content_type =~ $safe_content_type_re; + + # Safe referers are ones that begin with the urlbase. + my $referer = $self->referer; + my $is_safe_referer = $referer && $referer =~ $safe_referer_re; + + if (!$is_safe_referer && !$is_safe_content_type) { + print $self->SUPER::header(-type => 'text/html', -status => '403 Forbidden'); + if ($content_type ne 'text/html') { + print "Untrusted Referer Header\n"; + if ($ENV{MOD_PERL}) { + my $r = $self->r; + $r->rflush; + $r->status(200); + } + } + exit; + } + } +} + # Override header so we can add the cookies in sub header { my $self = shift; @@ -302,6 +365,7 @@ sub header { else { %headers = @_; } + $self->_prevent_unsafe_response(\%headers); if ($self->{'_content_disp'}) { $headers{'-content_disposition'} = $self->{'_content_disp'}; -- cgit v1.2.1 From 128fe6cd6b8139e496c3be50bb70d1df933ef6ca Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 16 Feb 2018 11:39:07 -0500 Subject: Bumped version to 5.0.4 --- Bugzilla/Constants.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 479212686..b4d22f8bf 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -200,7 +200,7 @@ use Memoize; # CONSTANTS # # Bugzilla version -use constant BUGZILLA_VERSION => "5.0.3+"; +use constant BUGZILLA_VERSION => "5.0.4"; # A base link to the current REST Documentation. We place it here # as it will need to be updated to whatever the current release is. -- cgit v1.2.1 From 37784703eba80cb61d1734a11e09b62fa0eaeae9 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 16 Feb 2018 14:24:54 -0500 Subject: Bumped versions post-release --- Bugzilla/Constants.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Bugzilla') diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index b4d22f8bf..edaa8baa5 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -200,7 +200,7 @@ use Memoize; # CONSTANTS # # Bugzilla version -use constant BUGZILLA_VERSION => "5.0.4"; +use constant BUGZILLA_VERSION => "5.0.4+"; # A base link to the current REST Documentation. We place it here # as it will need to be updated to whatever the current release is. -- cgit v1.2.1