[Bps-public-commit] rt-authen-externalauth branch, master, updated. 0.25-5-g436255c
Shawn Moore
shawn at bestpractical.com
Thu Jun 15 14:33:09 EDT 2017
The branch, master has been updated
via 436255c04b4881bb6d8eec9a57b8593033d863a9 (commit)
from 94e6194437cf09777319918f514eab947698bcfc (commit)
Summary of changes:
lib/RT/Authen/ExternalAuth.pm | 34 ++++++++++++++++++++++++++++++++++
lib/RT/Authen/ExternalAuth/DBI.pm | 16 ++++++++++++++--
2 files changed, 48 insertions(+), 2 deletions(-)
- Log -----------------------------------------------------------------
commit 436255c04b4881bb6d8eec9a57b8593033d863a9
Author: Aaron Kondziela <aaron at bestpractical.com>
Date: Tue Jan 24 18:20:28 2017 -0500
Fix timing sidechannel vulnerability in password checking
"eq" operators for comparing against passwords are replaced by a new
RT::Util::constant_time_eq to resolve a timing sidechannel vulnerability.
This addresses CVE-2017-5361.
Fixes: T#161960
diff --git a/lib/RT/Authen/ExternalAuth.pm b/lib/RT/Authen/ExternalAuth.pm
index aed6922..fd58a26 100644
--- a/lib/RT/Authen/ExternalAuth.pm
+++ b/lib/RT/Authen/ExternalAuth.pm
@@ -294,6 +294,7 @@ This is free software, licensed under:
use RT::Authen::ExternalAuth::LDAP;
use RT::Authen::ExternalAuth::DBI;
+use Encode qw/encode/;
use strict;
@@ -889,4 +890,37 @@ sub CanonicalizeUserInfo {
};
}
+=head2 C<constant_time_eq($a, $b)>
+
+Taken verbatim from RT 4.4's RT::Util.
+
+=cut
+
+sub constant_time_eq {
+ my ($a, $b) = @_;
+
+ my $result = 0;
+
+ # generic error message avoids potential information leaks
+ my $generic_error = "Cannot compare values";
+ die $generic_error unless defined $a and defined $b;
+ die $generic_error unless length $a == length $b;
+ die $generic_error if ref($a) or ref($b);
+
+ for (my $i = 0; $i < length($a); $i++) {
+ my $a_char = substr($a, $i, 1);
+ my $b_char = substr($b, $i, 1);
+
+ # encode() is set to die on malformed
+ my @a_octets = unpack("C*", encode('UTF-8', $a_char, Encode::FB_CROAK));
+ my @b_octets = unpack("C*", encode('UTF-8', $b_char, Encode::FB_CROAK));
+ die $generic_error if (scalar @a_octets) != (scalar @b_octets);
+
+ for (my $j = 0; $j < scalar @a_octets; $j++) {
+ $result |= $a_octets[$j] ^ $b_octets[$j];
+ }
+ }
+ return 0 + not $result;
+}
+
1;
diff --git a/lib/RT/Authen/ExternalAuth/DBI.pm b/lib/RT/Authen/ExternalAuth/DBI.pm
index 3fe6cda..6b11861 100644
--- a/lib/RT/Authen/ExternalAuth/DBI.pm
+++ b/lib/RT/Authen/ExternalAuth/DBI.pm
@@ -32,6 +32,7 @@ Provides the database implementation for L<RT::Authen::ExternalAuth>.
'p_field' => 'password',
# Example of custom hashed password check
+ # (See below for security concerns with this implementation)
#'p_check' => sub {
# my ($hash_from_db, $password) = @_;
# return $hash_from_db eq function($password);
@@ -123,6 +124,17 @@ An example, where C<FooBar()> is some external hashing function:
Importantly, the C<p_check> subroutine allows for arbitrarily complex password
checking unlike C<p_enc_pkg> and C<p_enc_sub>.
+Please note, the use of the C<eq> operator in the C<p_check> example above
+introduces a timing sidechannel vulnerability. (It was left there for clarity
+of the example.) There is a comparison function available in this extension that is
+hardened against timing attacks. The comparison from the above example could
+be re-written with it like this:
+
+ p_check => sub {
+ my ($hash_from_db, $password) = @_;
+ return RT::Authen::ExternalAuth::constant_time_eq($hash_from_db, FooBar($password));
+ },
+
=item p_enc_pkg, p_enc_sub
The Perl package and subroutine used to encrypt passwords from the
@@ -250,7 +262,7 @@ sub GetAuth {
# Jump to the next external authentication service if they don't match
if(defined($db_p_salt)) {
$RT::Logger->debug("Using salt:",$db_p_salt);
- if(${encrypt}->($password,$db_p_salt) ne $pass_from_db){
+ unless (RT::Authen::ExternalAuth::constant_time_eq(${encrypt}->($password,$db_p_salt), $pass_from_db)) {
$RT::Logger->info( $service,
"AUTH FAILED",
$username,
@@ -258,7 +270,7 @@ sub GetAuth {
return 0;
}
} else {
- if(${encrypt}->($password) ne $pass_from_db){
+ unless (RT::Authen::ExternalAuth::constant_time_eq(${encrypt}->($password), $pass_from_db)) {
$RT::Logger->info( $service,
"AUTH FAILED",
$username,
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list