1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-05-02 05:37:56 +02:00

implemented maximum login attempts feature to prevent dictionary attacks

git-svn-id: file:///svn/phpbb/branches/phpBB-2_0_0@5392 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
Meik Sievertsen 2005-12-29 11:51:13 +00:00
parent d63c1ddf2b
commit aa3bcbaccf
18 changed files with 143 additions and 18 deletions

@ -191,6 +191,14 @@ $template->assign_vars(array(
"L_MAX_POLL_OPTIONS" => $lang['Max_poll_options'],
"L_FLOOD_INTERVAL" => $lang['Flood_Interval'],
"L_FLOOD_INTERVAL_EXPLAIN" => $lang['Flood_Interval_explain'],
'L_MAX_LOGIN_ATTEMPTS' => $lang['Max_login_attempts'],
'L_MAX_LOGIN_ATTEMPTS_EXPLAIN' => $lang['Max_login_attempts_explain'],
'L_LOGIN_RESET_TIME' => $lang['Login_reset_time'],
'L_LOGIN_RESET_TIME_EXPLAIN' => $lang['Login_reset_time_explain'],
'MAX_LOGIN_ATTEMPTS' => $new['max_login_attempts'],
'LOGIN_RESET_TIME' => $new['login_reset_time'],
"L_BOARD_EMAIL_FORM" => $lang['Board_email_form'],
"L_BOARD_EMAIL_FORM_EXPLAIN" => $lang['Board_email_form_explain'],
"L_TOPICS_PER_PAGE" => $lang['Topics_per_page'],

@ -75,8 +75,11 @@ p,ul,td {font-size:10pt;}
<li>[Fix] change truncation of username length in usercp_register.php - BFUK</li>
<li>[Fix] incorrect path to avatars in admin_users.php (Bug #667)</li>
<li>[Fix] fixed get_userdata to support correct sql escaping (non-mysql dbs) - jarnaez</li>
<li>[Fix] fixed captcha for those not having the zlib extension enabled</li>
<li>[Change] Placed version information above who is online in admin panel for better visual presence</li>
<li>[Sec] fixed XSS issue (only valid for Internet Explorer) within the url bbcode</li>
<li>[Sec] fixed XSS issue (only valid for Internet Explorer) if html tags are allowed and enabled</li>
<li>[Sec] added configurable maximum login attempts to prevent dictionary attacks</li>
</ul>

@ -153,18 +153,15 @@ if (@extension_loaded('zlib'))
}
else
{
if (!empty($HTTP_GET_VARS['c']))
{
$_png = define_raw_pngs();
$_png = define_raw_pngs();
$char = substr($code, intval($HTTP_GET_VARS['c']) - 1, 1);
header('Content-Type: image/png');
header('Cache-control: no-cache, no-store');
echo base64_decode($_png[$char]);
$char = substr($code, -1);
header('Content-Type: image/png');
header('Cache-control: no-cache, no-store');
echo base64_decode($_png[$char]);
unset($_png);
exit;
}
unset($_png);
exit;
}
exit;

@ -296,6 +296,12 @@ if ( isset($HTTP_POST_VARS['submit']) )
if ($row = $db->sql_fetchrow($result))
{
// Only compare one char if the zlib-extension is not loaded
if (!@extension_loaded('zlib'))
{
$row['code'] = substr($row['code'], -1);
}
if ($row['code'] != $confirm_code)
{
$error = TRUE;

@ -333,7 +333,7 @@ $available_dbms = array(
'COMMENTS' => 'remove_remarks'
),
'mysql4' => array(
'LABEL' => 'MySQL 4.x',
'LABEL' => 'MySQL 4.x/5.x',
'SCHEMA' => 'mysql',
'DELIM' => ';',
'DELIM_BASIC' => ';',

Binary file not shown.

@ -51,6 +51,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');

@ -342,6 +342,8 @@ CREATE TABLE [phpbb_users] (
[user_new_privmsg] [smallint] NOT NULL ,
[user_unread_privmsg] [smallint] NOT NULL ,
[user_last_privmsg] [int] NOT NULL ,
[user_login_tries] [smallint] NOT NULL ,
[user_last_login_try] [int] NOT NULL ,
[user_emailtime] [int] NOT NULL ,
[user_viewemail] [smallint] NULL ,
[user_attachsig] [smallint] NULL ,
@ -613,6 +615,8 @@ ALTER TABLE [phpbb_users] WITH NOCHECK ADD
CONSTRAINT [DF_phpbb_users_user_new_privmsg] DEFAULT (0) FOR [user_new_privmsg],
CONSTRAINT [DF_phpbb_users_user_unread_privmsg] DEFAULT (0) FOR [user_unread_privmsg],
CONSTRAINT [DF_phpbb_users_user_last_privmsg] DEFAULT (0) FOR [user_last_privmsg],
CONSTRAINT [DF_phpbb_users_user_login_tries] DEFAULT (0) FOR [user_login_tries],
CONSTRAINT [DF_phpbb_users_user_last_login_try] DEFAULT (0) FOR [user_last_login_try],
CONSTRAINT [DF_phpbb_users_user_emailtime] DEFAULT (0) FOR [user_emailtime],
CONSTRAINT [DF_phpbb_users_user_viewemail] DEFAULT (1) FOR [user_viewemail],
CONSTRAINT [DF_phpbb_users_user_attachsig] DEFAULT (1) FOR [user_attachsig],

@ -44,6 +44,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');

@ -492,6 +492,8 @@ CREATE TABLE phpbb_users (
user_new_privmsg smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
user_unread_privmsg smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
user_last_privmsg int(11) DEFAULT '0' NOT NULL,
user_login_tries smallint(5) UNSIGNED DEFAULT '0' NOT NULL,
user_last_login_try int(11) DEFAULT '0' NOT NULL,
user_emailtime int(11),
user_viewemail tinyint(1),
user_attachsig tinyint(1),

@ -45,6 +45,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password','')
INSERT INTO phpbb_config (config_name, config_value) VALUES ('sendmail_fix','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval','15');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '5');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('login_reset_time', '30');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form','0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize','6144');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width','80');

@ -488,6 +488,8 @@ CREATE TABLE phpbb_users (
user_new_privmsg int2 DEFAULT '0' NOT NULL,
user_unread_privmsg int2 DEFAULT '0' NOT NULL,
user_last_privmsg int4 DEFAULT '0' NOT NULL,
user_login_tries int2 DEFAULT '0' NOT NULL,
user_last_login_try int4 DEFAULT '0' NOT NULL,
user_emailtime int4,
user_viewemail int2,
user_attachsig int2,

@ -584,6 +584,48 @@ switch ($row['config_value'])
break;
}
case '.0.18':
// Add login columns to user table
switch (SQL_LAYER)
{
case 'mysql':
case 'mysql4':
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ADD COLUMN user_login_tries smallint(5) UNSIGNED DEFAULT '0' NOT NULL";
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ADD COLUMN user_last_login_try int(11) DEFAULT '0' NOT NULL";
break;
case 'postgresql':
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ADD COLUMN user_login_tries int2";
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ALTER COLUMN user_login_tries SET DEFAULT '0'";
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ADD COLUMN user_last_login_try int4";
$sql[] = "ALTER TABLE " . USERS_TABLE . "
ALTER COLUMN user_last_login_try SET DEFAULT '0'";
break;
case 'mssql-odbc':
case 'mssql':
$sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
user_login_tries smallint NOT NULL,
CONSTRAINT [DF_" . $table_prefix . "users_user_login_tries] DEFAULT (0) FOR [user_login_tries]";
$sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
user_last_login_try int NOT NULL,
CONSTRAINT [DF_" . $table_prefix . "users_user_last_login_try] DEFAULT (0) FOR [user_last_login_try]";
break;
case 'msaccess':
$sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
user_login_tries smallint NOT NULL";
$sql[] = "ALTER TABLE " . USERS_TABLE . " ADD
user_last_login_try int NOT NULL";
break;
}
break;
}
@ -1002,6 +1044,17 @@ switch ($row['config_value'])
// We reset those having autologin enabled and forcing the re-assignment of a session id
$sql = 'DELETE FROM ' . SESSIONS_TABLE;
_sql($sql, $errored, $error_ary);
case '.0.18':
$sql = 'INSERT INTO ' . CONFIG_TABLE . " (config_name, config_value)
VALUES ('max_login_attempts', '5')";
_sql($sql, $errored, $error_ary);
$sql = 'INSERT INTO ' . CONFIG_TABLE . " (config_name, config_value)
VALUES ('login_reset_time', '30')";
_sql($sql, $errored, $error_ary);
break;
default:

@ -743,6 +743,14 @@ $lang['Socket_functions_disabled'] = 'Unable to use socket functions.';
$lang['Mailing_list_subscribe_reminder'] = 'For the latest information on updates to phpBB, why not <a href="http://www.phpbb.com/support/" target="_new">subscribe to our mailing list</a>.';
$lang['Version_information'] = 'Version Information';
//
// Login attempts configuration
//
$lang['Max_login_attempts'] = 'Allowed login attempts';
$lang['Max_login_attempts_explain'] = 'The number of allowed board login attempts.';
$lang['Login_reset_time'] = 'Login lock time';
$lang['Login_reset_time_explain'] = 'Time in minutes the user have to wait until he is allowed to login again after exceeding the number of allowed login attempts.';
//
// That's all Folks!
// -------------------------------------------------

@ -1014,6 +1014,7 @@ $lang['An_error_occured'] = 'An Error Occurred';
$lang['A_critical_error'] = 'A Critical Error Occurred';
$lang['Admin_reauthenticate'] = 'To administer the board you must re-authenticate yourself.';
$lang['Login_attempts_exceeded'] = 'The maximum number of %s login attempts has been exceeded. You are not allowed to login for the next %s minutes.';
//
// That's all, Folks!

@ -57,7 +57,7 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
$username = isset($HTTP_POST_VARS['username']) ? phpbb_clean_username($HTTP_POST_VARS['username']) : '';
$password = isset($HTTP_POST_VARS['password']) ? $HTTP_POST_VARS['password'] : '';
$sql = "SELECT user_id, username, user_password, user_active, user_level
$sql = "SELECT user_id, username, user_password, user_active, user_level, user_login_tries, user_last_login_try
FROM " . USERS_TABLE . "
WHERE username = '" . str_replace("\\'", "''", $username) . "'";
if ( !($result = $db->sql_query($sql)) )
@ -73,6 +73,20 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
}
else
{
// If the last login is more than x minutes ago, then reset the login tries/time
if ($row['user_last_login_try'] && $board_config['login_reset_time'] && $row['user_last_login_try'] < (time() - ($board_config['login_reset_time'] * 60)))
{
$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_login_tries = 0, user_last_login_try = 0 WHERE user_id = ' . $row['user_id']);
$row['user_last_login_try'] = $row['user_login_tries'] = 0;
}
// Check to see if user is allowed to login again... if his tries are exceeded
if ($row['user_last_login_try'] && $board_config['login_reset_time'] && $board_config['max_login_attempts'] &&
$row['user_last_login_try'] >= (time() - ($board_config['login_reset_time'] * 60)) && $row['user_login_tries'] >= $board_config['max_login_attempts'])
{
message_die(GENERAL_MESSAGE, sprintf($lang['Login_attempts_exceeded'], $board_config['max_login_attempts'], $board_config['login_reset_time']));
}
if( md5($password) == $row['user_password'] && $row['user_active'] )
{
$autologin = ( isset($HTTP_POST_VARS['autologin']) ) ? TRUE : 0;
@ -80,6 +94,9 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
$admin = (isset($HTTP_POST_VARS['admin'])) ? 1 : 0;
$session_id = session_begin($row['user_id'], $user_ip, PAGE_INDEX, FALSE, $autologin, $admin);
// Reset login tries
$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_login_tries = 0, user_last_login_try = 0 WHERE user_id = ' . $row['user_id']);
if( $session_id )
{
$url = ( !empty($HTTP_POST_VARS['redirect']) ) ? str_replace('&amp;', '&', htmlspecialchars($HTTP_POST_VARS['redirect'])) : "index.$phpEx";
@ -92,6 +109,15 @@ if( isset($HTTP_POST_VARS['login']) || isset($HTTP_GET_VARS['login']) || isset($
}
else
{
// Save login tries and last login
if ($row['user_id'] != ANONYMOUS)
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_login_tries = user_login_tries + 1, user_last_login_try = ' . time() . '
WHERE user_id = ' . $row['user_id'];
$db->sql_query($sql);
}
$redirect = ( !empty($HTTP_POST_VARS['redirect']) ) ? str_replace('&amp;', '&', htmlspecialchars($HTTP_POST_VARS['redirect'])) : '';
$redirect = str_replace('?', '&', $redirect);

@ -55,6 +55,14 @@
<td class="row1">{L_FLOOD_INTERVAL} <br /><span class="gensmall">{L_FLOOD_INTERVAL_EXPLAIN}</span></td>
<td class="row2"><input class="post" type="text" size="3" maxlength="4" name="flood_interval" value="{FLOOD_INTERVAL}" /></td>
</tr>
<tr>
<td class="row1">{L_MAX_LOGIN_ATTEMPTS}<br /><span class="gensmall">{L_MAX_LOGIN_ATTEMPTS_EXPLAIN}</span></td>
<td class="row2"><input class="post" type="text" size="3" maxlength="4" name="max_login_attempts" value="{MAX_LOGIN_ATTEMPTS}" /></td>
</tr>
<tr>
<td class="row1">{L_LOGIN_RESET_TIME}<br /><span class="gensmall">{L_LOGIN_RESET_TIME_EXPLAIN}</span></td>
<td class="row2"><input class="post" type="text" size="3" maxlength="4" name="login_reset_time" value="{LOGIN_RESET_TIME}" /></td>
</tr>
<tr>
<td class="row1">{L_TOPICS_PER_PAGE}</td>
<td class="row2"><input class="post" type="text" name="topics_per_page" size="3" maxlength="4" value="{TOPICS_PER_PAGE}" /></td>

@ -43,6 +43,13 @@
<td class="row2"><b>{GZIP_COMPRESSION}</b></td>
</tr>
</table>
<h1>{L_VERSION_INFORMATION}</h1>
{VERSION_INFO}
<br />
<h1>{L_WHO_IS_ONLINE}</h1>
<table width="100%" cellpadding="4" cellspacing="1" border="0" class="forumline">
@ -77,9 +84,3 @@
</table>
<br />
<h1>{L_VERSION_INFORMATION}</h1>
{VERSION_INFO}
<br />