From 95b919c0b6b731d16e92dd748e654cefeba0bd32 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Mon, 24 Jan 2011 13:43:38 -0800 Subject: Bug 619594: (CVE-2010-4568) [SECURITY] Improve the randomness of generate_random_password, to protect against an account compromise issue and other critical vulnerabilities. r=LpSolit, a=LpSolit https://bugzilla.mozilla.org/show_bug.cgi?id=621591 --- Bugzilla/Install/Localconfig.pm | 13 +++++++++++-- Bugzilla/Install/Requirements.pm | 6 ++++++ Bugzilla/Util.pm | 9 ++++++++- mod_perl.pl | 9 +++++++-- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index 956d3c72e..3ce12207e 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -109,7 +109,9 @@ use constant LOCALCONFIG_VARS => ( }, { name => 'site_wide_secret', - default => sub { generate_random_password(256) }, + # 64 characters is roughly the equivalent of a 384-bit key, which + # is larger than anybody would ever be able to brute-force. + default => sub { generate_random_password(64) }, }, ); @@ -210,7 +212,14 @@ sub update_localconfig { my @new_vars; foreach my $var (LOCALCONFIG_VARS) { my $name = $var->{name}; - if (!defined $localconfig->{$name}) { + my $value = $localconfig->{$name}; + # Regenerate site_wide_secret if it was made by our old, weak + # generate_random_password. Previously we used to generate + # a 256-character string for site_wide_secret. + $value = undef if ($name eq 'site_wide_secret' and defined $value + and length($value) == 256); + + if (!defined $value) { push(@new_vars, $name); $var->{default} = &{$var->{default}} if ref($var->{default}) eq 'CODE'; if (exists $answer->{$name}) { diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index f45360916..e3049f2d5 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -157,6 +157,12 @@ sub REQUIRED_MODULES { module => 'List::MoreUtils', version => 0.22, }, + { + package => 'Math-Random-Secure', + module => 'Math::Random::Secure', + # This is the first version that installs properly on Windows. + version => '0.05', + }, ); my $extra_modules = _get_extension_requirements('REQUIRED_MODULES'); diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 457eb7d02..f9e8d12f7 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -54,6 +54,7 @@ use DateTime::TimeZone; use Digest; use Email::Address; use List::Util qw(first); +use Math::Random::Secure qw(irand); use Scalar::Util qw(tainted); use Template::Filters; use Text::Wrap; @@ -535,9 +536,15 @@ sub bz_crypt { return $crypted_password; } +# If you want to understand the security of strings generated by this +# function, here's a quick formula that will help you estimate: +# We pick from 62 characters, which is close to 64, which is 2^6. +# So 8 characters is (2^6)^8 == 2^48 combinations. Just multiply 6 +# by the number of characters you generate, and that gets you the equivalent +# strength of the string in bits. sub generate_random_password { my $size = shift || 10; # default to 10 chars if nothing specified - return join("", map{ ('0'..'9','a'..'z','A'..'Z')[rand 62] } (1..$size)); + return join("", map{ ('0'..'9','a'..'z','A'..'Z')[irand 62] } (1..$size)); } sub validate_email_syntax { diff --git a/mod_perl.pl b/mod_perl.pl index 3551abdaf..0c7caf173 100644 --- a/mod_perl.pl +++ b/mod_perl.pl @@ -37,6 +37,7 @@ use lib Bugzilla::Constants::bz_locations()->{'ext_libpath'}; use Apache2::ServerUtil; use ModPerl::RegistryLoader (); use File::Basename (); +use Math::Random::Secure; # This loads most of our modules. use Bugzilla (); @@ -60,8 +61,12 @@ my $cgi_path = Bugzilla::Constants::bz_locations()->{'cgi_path'}; # Set up the configuration for the web server my $server = Apache2::ServerUtil->server; my $conf = < AddHandler perl-script .cgi # No need to PerlModule these because they're already defined in mod_perl.pl -- cgit v1.2.3-24-g4f1b