|
|
@@ -538,7 +538,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
|
|
|
}
|
|
|
|
|
|
$password = $this->_basicResolver->resolve($creds[0], $this->_realm);
|
|
|
- if ($password && $password == $creds[1]) {
|
|
|
+ if ($password && $this->_secureStringCompare($password, $creds[1])) {
|
|
|
$identity = array('username'=>$creds[0], 'realm'=>$this->_realm);
|
|
|
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
|
|
|
} else {
|
|
|
@@ -640,7 +640,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
|
|
|
|
|
|
// If our digest matches the client's let them in, otherwise return
|
|
|
// a 401 code and exit to prevent access to the protected resource.
|
|
|
- if ($digest == $data['response']) {
|
|
|
+ if ($this->_secureStringCompare($digest, $data['response'])) {
|
|
|
$identity = array('username'=>$data['username'], 'realm'=>$data['realm']);
|
|
|
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
|
|
|
} else {
|
|
|
@@ -844,4 +844,26 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
|
|
|
|
|
|
return $data;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Securely compare two strings for equality while avoided C level memcmp()
|
|
|
+ * optimisations capable of leaking timing information useful to an attacker
|
|
|
+ * attempting to iteratively guess the unknown string (e.g. password) being
|
|
|
+ * compared against.
|
|
|
+ *
|
|
|
+ * @param string $a
|
|
|
+ * @param string $b
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ protected function _secureStringCompare($a, $b)
|
|
|
+ {
|
|
|
+ if (strlen($a) !== strlen($b)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $result = 0;
|
|
|
+ for ($i = 0; $i < strlen($a); $i++) {
|
|
|
+ $result |= ord($a[$i]) ^ ord($b[$i]);
|
|
|
+ }
|
|
|
+ return $result == 0;
|
|
|
+ }
|
|
|
}
|