diff --git a/phpBB/admin/admin_board.php b/phpBB/admin/admin_board.php index df8a5404e3..721b2f5b97 100644 --- a/phpBB/admin/admin_board.php +++ b/phpBB/admin/admin_board.php @@ -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'], diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index f4a3592ddf..42ffb42968 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -75,8 +75,11 @@ p,ul,td {font-size:10pt;}
  • [Fix] change truncation of username length in usercp_register.php - BFUK
  • [Fix] incorrect path to avatars in admin_users.php (Bug #667)
  • [Fix] fixed get_userdata to support correct sql escaping (non-mysql dbs) - jarnaez
  • +
  • [Fix] fixed captcha for those not having the zlib extension enabled
  • +
  • [Change] Placed version information above who is online in admin panel for better visual presence
  • [Sec] fixed XSS issue (only valid for Internet Explorer) within the url bbcode
  • [Sec] fixed XSS issue (only valid for Internet Explorer) if html tags are allowed and enabled
  • +
  • [Sec] added configurable maximum login attempts to prevent dictionary attacks
  • diff --git a/phpBB/includes/usercp_confirm.php b/phpBB/includes/usercp_confirm.php index fec308c9f9..24a94d728d 100644 --- a/phpBB/includes/usercp_confirm.php +++ b/phpBB/includes/usercp_confirm.php @@ -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; diff --git a/phpBB/includes/usercp_register.php b/phpBB/includes/usercp_register.php index f6c5a451a0..591af76ad3 100644 --- a/phpBB/includes/usercp_register.php +++ b/phpBB/includes/usercp_register.php @@ -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; diff --git a/phpBB/install/install.php b/phpBB/install/install.php index 7db904f7b8..35b99804a2 100644 --- a/phpBB/install/install.php +++ b/phpBB/install/install.php @@ -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' => ';', diff --git a/phpBB/install/schemas/ms_access_primer.zip b/phpBB/install/schemas/ms_access_primer.zip index 7b66a0fb47..7da212ca37 100644 Binary files a/phpBB/install/schemas/ms_access_primer.zip and b/phpBB/install/schemas/ms_access_primer.zip differ diff --git a/phpBB/install/schemas/mssql_basic.sql b/phpBB/install/schemas/mssql_basic.sql index 94fd6c515f..42193efea5 100644 --- a/phpBB/install/schemas/mssql_basic.sql +++ b/phpBB/install/schemas/mssql_basic.sql @@ -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'); diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 06649eefbc..c4f92fa8af 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -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], diff --git a/phpBB/install/schemas/mysql_basic.sql b/phpBB/install/schemas/mysql_basic.sql index 247af3f2ab..2d1b4a5142 100644 --- a/phpBB/install/schemas/mysql_basic.sql +++ b/phpBB/install/schemas/mysql_basic.sql @@ -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'); diff --git a/phpBB/install/schemas/mysql_schema.sql b/phpBB/install/schemas/mysql_schema.sql index a914764fca..6944a3d8a5 100644 --- a/phpBB/install/schemas/mysql_schema.sql +++ b/phpBB/install/schemas/mysql_schema.sql @@ -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), diff --git a/phpBB/install/schemas/postgres_basic.sql b/phpBB/install/schemas/postgres_basic.sql index d530a85317..0e1c84dfd7 100644 --- a/phpBB/install/schemas/postgres_basic.sql +++ b/phpBB/install/schemas/postgres_basic.sql @@ -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'); diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 737f2f1f8b..ac24cff312 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -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, diff --git a/phpBB/install/update_to_latest.php b/phpBB/install/update_to_latest.php index eeb282545e..6fc4d50f50 100644 --- a/phpBB/install/update_to_latest.php +++ b/phpBB/install/update_to_latest.php @@ -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: diff --git a/phpBB/language/lang_english/lang_admin.php b/phpBB/language/lang_english/lang_admin.php index 17436a3342..915c6648ea 100644 --- a/phpBB/language/lang_english/lang_admin.php +++ b/phpBB/language/lang_english/lang_admin.php @@ -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 subscribe to our mailing list.'; $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! // ------------------------------------------------- diff --git a/phpBB/language/lang_english/lang_main.php b/phpBB/language/lang_english/lang_main.php index defc3d36d8..d104025d32 100644 --- a/phpBB/language/lang_english/lang_main.php +++ b/phpBB/language/lang_english/lang_main.php @@ -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! diff --git a/phpBB/login.php b/phpBB/login.php index 4844be3c2e..c8a572d7a9 100644 --- a/phpBB/login.php +++ b/phpBB/login.php @@ -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('&', '&', 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('&', '&', htmlspecialchars($HTTP_POST_VARS['redirect'])) : ''; $redirect = str_replace('?', '&', $redirect); diff --git a/phpBB/templates/subSilver/admin/board_config_body.tpl b/phpBB/templates/subSilver/admin/board_config_body.tpl index 83b9bb320c..12d7bc6a87 100644 --- a/phpBB/templates/subSilver/admin/board_config_body.tpl +++ b/phpBB/templates/subSilver/admin/board_config_body.tpl @@ -55,6 +55,14 @@ {L_FLOOD_INTERVAL}
    {L_FLOOD_INTERVAL_EXPLAIN} + + {L_MAX_LOGIN_ATTEMPTS}
    {L_MAX_LOGIN_ATTEMPTS_EXPLAIN} + + + + {L_LOGIN_RESET_TIME}
    {L_LOGIN_RESET_TIME_EXPLAIN} + + {L_TOPICS_PER_PAGE} diff --git a/phpBB/templates/subSilver/admin/index_body.tpl b/phpBB/templates/subSilver/admin/index_body.tpl index f8fe7c3c88..6e9f8d3862 100644 --- a/phpBB/templates/subSilver/admin/index_body.tpl +++ b/phpBB/templates/subSilver/admin/index_body.tpl @@ -43,6 +43,13 @@ {GZIP_COMPRESSION} + +

    {L_VERSION_INFORMATION}

    + +{VERSION_INFO} + +
    +

    {L_WHO_IS_ONLINE}

    @@ -77,9 +84,3 @@

    - -

    {L_VERSION_INFORMATION}

    - -{VERSION_INFO} - -