From ae83b89a0bbb17de4f2c4f5b80387943d3425ea7 Mon Sep 17 00:00:00 2001
From: csteipp <csteipp@wikimedia.org>
Date: Mon, 22 Feb 2016 12:50:40 -0800
Subject: [PATCH] SECURITY: Throw exception on unknown hash algorithm

To prevent a bad password configuration from accidentally allowing
users to bypass authentication, throw an exception if either hash or
hash_pbkdf2 return false.

Also, ensure md5() returned a sane hash.

Bug: T127420
Change-Id: If3664941236e4065eb8db11b0a211fd6210de631
---
 includes/password/MWOldPassword.php    | 4 ++++
 includes/password/MWSaltedPassword.php | 4 ++++
 includes/password/Pbkdf2Password.php   | 9 ++++++++-
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/includes/password/MWOldPassword.php b/includes/password/MWOldPassword.php
index afa5cac..43c1355 100644
--- a/includes/password/MWOldPassword.php
+++ b/includes/password/MWOldPassword.php
@@ -44,5 +44,9 @@ class MWOldPassword extends ParameterizedPassword {
 			$this->args = array();
 			$this->hash = md5( $plaintext );
 		}
+
+		if ( !is_string( $this->hash ) || strlen( $this->hash ) < 32 ) {
+			throw new PasswordError( 'Error when hashing password.' );
+		}
 	}
 }
diff --git a/includes/password/MWSaltedPassword.php b/includes/password/MWSaltedPassword.php
index 6c6895a..40d2b6a 100644
--- a/includes/password/MWSaltedPassword.php
+++ b/includes/password/MWSaltedPassword.php
@@ -42,5 +42,9 @@ class MWSaltedPassword extends ParameterizedPassword {
 		}
 
 		$this->hash = md5( $this->args[0] . '-' . md5( $plaintext ) );
+
+		if ( !is_string( $this->hash ) || strlen( $this->hash ) < 32 ) {
+			throw new PasswordError( 'Error when hashing password.' );
+		}
 	}
 }
diff --git a/includes/password/Pbkdf2Password.php b/includes/password/Pbkdf2Password.php
index 080e3b0..808fd8a 100644
--- a/includes/password/Pbkdf2Password.php
+++ b/includes/password/Pbkdf2Password.php
@@ -55,8 +55,15 @@ class Pbkdf2Password extends ParameterizedPassword {
 				(int)$this->params['length'],
 				true
 			);
+			if ( !is_string( $hash ) ) {
+				throw new PasswordError( 'Error when hashing password.' );
+			}
 		} else {
-			$hashLen = strlen( hash( $this->params['algo'], '', true ) );
+			$hashLenHash = hash( $this->params['algo'], '', true );
+			if ( !is_string( $hashLenHash ) ) {
+				throw new PasswordError( 'Error when hashing password.' );
+			}
+			$hashLen = strlen( $hashLenHash );
 			$blockCount = ceil( $this->params['length'] / $hashLen );
 
 			$hash = '';
-- 
2.8.1

