aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarcus <marcus@36083f99-b078-4883-b0ff-0f9b5a30f544>2009-01-14 15:10:39 +0000
committermarcus <marcus@36083f99-b078-4883-b0ff-0f9b5a30f544>2009-01-14 15:10:39 +0000
commitf4d6c6567fb9c23a9654e704045f03dbf10e467e (patch)
tree159581f9d394008fdab542237c3650a0b5b5967d
parentf2ac90d450c5b6888bf6323466b2dc9c3275f4bd (diff)
downloadelgg-f4d6c6567fb9c23a9654e704045f03dbf10e467e.tar.gz
elgg-f4d6c6567fb9c23a9654e704045f03dbf10e467e.tar.bz2
Closes #669: Logins rate limited. Accounts are limited to 5 fails in a 5 minute period, meaning an attacker can try one password per minute.
git-svn-id: https://code.elgg.org/elgg/trunk@2568 36083f99-b078-4883-b0ff-0f9b5a30f544
-rw-r--r--engine/lib/sessions.php76
-rw-r--r--languages/en.php2
2 files changed, 75 insertions, 3 deletions
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index f3d828ca4..9336f0059 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -181,23 +181,93 @@
*/
function pam_auth_userpass($credentials = NULL)
{
+ $max_in_period = 3; // max 3 login attempts in
+ $period_length = 5; // 5 minutes
+ $periods = array();
+
if (is_array($credentials) && ($credentials['username']) && ($credentials['password']))
{
//$dbpassword = md5($credentials['password']);
if ($user = get_user_by_username($credentials['username'])) {
+
// Let admins log in without validating their email, but normal users must have validated their email
if ((!$user->admin) && (!$user->validated) && (!$user->admin_created) && (!$user->isBanned()))
return false;
- if ($user->password == generate_user_password($user, $credentials['password'])) {
+ if ($user->password == generate_user_password($user, $credentials['password']))
+
return true;
- }
+ else
+ // Password failed, log.
+ log_login_failure($user->guid);
+
}
}
return false;
+ }
+
+ function log_login_failure($user_guid)
+ {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ $fails++;
+
+ $user->setPrivateSetting("login_failures", $fails);
+ $user->setPrivateSetting("login_failure_$fails", time());
+ }
+ }
+
+ function reset_login_failure_count($user_guid)
+ {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+
+ if ($fails) {
+ for ($n=1; $n <= $fails; $n++)
+ $user->removePrivateSetting("login_failure_$n");
+
+ $user->removePrivateSetting("login_failures");
+ }
+ }
+ }
+
+ function check_rate_limit_exceeded($user_guid)
+ {
+ $limit = 5;
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser))
+ {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ if ($fails >= $limit)
+ {
+ $cnt = 0;
+ $time = time();
+ for ($n=$fails; $n>0; $n--)
+ {
+ $f = $user->getPrivateSetting("login_failure_$n");
+ if ($f > $time - (60*5))
+ $cnt++;
+
+ if ($cnt==$limit) return true; // Limit reached
+ }
+ }
+
+ }
+
+ return false;
}
/**
@@ -214,6 +284,7 @@
global $CONFIG;
if ($user->isBanned()) return false; // User is banned, return false.
+ if (check_rate_limit_exceeded($user->guid)) return false; // Check rate limit
$_SESSION['user'] = $user;
$_SESSION['guid'] = $user->getGUID();
@@ -246,6 +317,7 @@
// Update statistics
set_last_login($_SESSION['guid']);
+ reset_login_failure_count($user->guid); // Reset any previous failed login attempts
return true;
diff --git a/languages/en.php b/languages/en.php
index e08c07ece..3ab22dc5b 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -14,7 +14,7 @@
'login' => "Log in",
'loginok' => "You have been logged in.",
- 'loginerror' => "We couldn't log you in. This may be because you haven't validated your account yet, or the details you supplied were incorrect. Make sure your details are correct and please try again.",
+ 'loginerror' => "We couldn't log you in. This may be because you haven't validated your account yet, the details you supplied were incorrect, or you have made too many incorrect login attempts. Make sure your details are correct and please try again.",
'logout' => "Log out",
'logoutok' => "You have been logged out.",