mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #43 from silverstripe-security/pulls/3.5/member-enumeration-timing-attack
[SS-2017-005] User enumeration via timing attack mitigated
This commit is contained in:
commit
72702dbd50
@ -18,9 +18,18 @@ abstract class LoginForm extends Form {
|
||||
* form.
|
||||
* @var string
|
||||
*/
|
||||
|
||||
protected $authenticator_class;
|
||||
|
||||
/**
|
||||
* The minimum amount of time authenticating is allowed to take in milliseconds.
|
||||
*
|
||||
* Protects against timing enumeration attacks
|
||||
*
|
||||
* @config
|
||||
* @var int
|
||||
*/
|
||||
private static $min_auth_time = 350;
|
||||
|
||||
/**
|
||||
* Get the authenticator instance
|
||||
*
|
||||
|
@ -150,6 +150,10 @@ class MemberAuthenticator extends Authenticator {
|
||||
* @see Security::setDefaultAdmin()
|
||||
*/
|
||||
public static function authenticate($data, Form $form = null) {
|
||||
// minimum execution time for authenticating a member
|
||||
$minExecTime = LoginForm::config()->min_auth_time / 1000;
|
||||
$startTime = microtime(true);
|
||||
|
||||
// Find authenticated member
|
||||
$member = static::authenticate_member($data, $form, $success);
|
||||
|
||||
@ -170,6 +174,11 @@ class MemberAuthenticator extends Authenticator {
|
||||
|
||||
if($success) Session::clear('BackURL');
|
||||
|
||||
$waitFor = $minExecTime - (microtime(true) - $startTime);
|
||||
if ($waitFor > 0) {
|
||||
usleep($waitFor * 1000000);
|
||||
}
|
||||
|
||||
return $success ? $member : null;
|
||||
}
|
||||
|
||||
|
@ -294,6 +294,10 @@ JS;
|
||||
* @param array $data Submitted data
|
||||
*/
|
||||
public function forgotPassword($data) {
|
||||
// minimum execution time for authenticating a member
|
||||
$minExecTime = self::config()->min_auth_time / 1000;
|
||||
$startTime = microtime(true);
|
||||
|
||||
// Ensure password is given
|
||||
if(empty($data['Email'])) {
|
||||
$this->sessionMessage(
|
||||
@ -311,10 +315,8 @@ JS;
|
||||
// Allow vetoing forgot password requests
|
||||
$results = $this->extend('forgotPassword', $member);
|
||||
if($results && is_array($results) && in_array(false, $results, true)) {
|
||||
return $this->controller->redirect('Security/lostpassword');
|
||||
}
|
||||
|
||||
if($member) {
|
||||
$this->controller->redirect('Security/lostpassword');
|
||||
} elseif ($member) {
|
||||
$token = $member->generateAutologinTokenAndStoreHash();
|
||||
|
||||
$e = Member_ForgotPasswordEmail::create();
|
||||
@ -338,6 +340,10 @@ JS;
|
||||
|
||||
$this->controller->redirect('Security/lostpassword');
|
||||
}
|
||||
$waitFor = $minExecTime - (microtime(true) - $startTime);
|
||||
if ($waitFor > 0) {
|
||||
usleep($waitFor * 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user