1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-04-21 16:22:22 +02:00

[ticket/security/276] Add test for expiration timer

SECURITY-276
This commit is contained in:
Marc Alexander 2024-04-28 20:10:24 +02:00
parent 24dd47adcf
commit 7c661746cf
No known key found for this signature in database
GPG Key ID: 50E0D2423696F995
3 changed files with 67 additions and 20 deletions

View File

@ -45,7 +45,7 @@ class ucp_resend
trigger_error('FORM_INVALID');
}
$sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey, user_inactive_reason
$sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey, user_actkey_expiration, user_inactive_reason
FROM ' . USERS_TABLE . "
WHERE user_email = '" . $db->sql_escape($email) . "'
AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";

View File

@ -162,6 +162,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case
'user_sig_bbcode_bitfield' => '',
'user_jabber' => '',
'user_actkey' => '',
'user_actkey_expiration' => 0,
'user_newpasswd' => '',
'user_form_salt' => '',
'user_new' => 1,

View File

@ -18,10 +18,14 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
{
protected $user_data;
protected const TEST_USER = 'reset-password-test-user';
protected const TEST_EMAIL = 'reset-password-test-user@test.com';
public function test_password_reset()
{
$this->add_lang('ucp');
$user_id = $this->create_user('reset-password-test-user', 'reset-password-test-user@test.com');
$user_id = $this->create_user(self::TEST_USER, self::TEST_EMAIL);
// test without email
$crawler = self::request('GET', "ucp.php?mode=sendpassword&sid={$this->sid}");
@ -41,13 +45,13 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
// test with correct email
$crawler = self::request('GET', "app.php/user/forgot_password?sid={$this->sid}");
$form = $crawler->selectButton('submit')->form(array(
'email' => 'reset-password-test-user@test.com',
'email' => self::TEST_EMAIL,
));
$crawler = self::submit($form);
$this->assertContainsLang('PASSWORD_RESET_LINK_SENT', $crawler->text());
// Check if columns in database were updated for password reset
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$this->assertNotEmpty($this->user_data['reset_token']);
$this->assertNotEmpty($this->user_data['reset_token_expiration']);
$reset_token = $this->user_data['reset_token'];
@ -56,31 +60,31 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
// Check that reset token is only created once per day
$crawler = self::request('GET', "app.php/user/forgot_password?sid={$this->sid}");
$form = $crawler->selectButton('submit')->form(array(
'email' => 'reset-password-test-user@test.com',
'email' => self::TEST_EMAIL,
));
$crawler = self::submit($form);
$this->assertContainsLang('PASSWORD_RESET_LINK_SENT', $crawler->text());
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$this->assertNotEmpty($this->user_data['reset_token']);
$this->assertNotEmpty($this->user_data['reset_token_expiration']);
$this->assertEquals($reset_token, $this->user_data['reset_token']);
$this->assertEquals($reset_token_expiration, $this->user_data['reset_token_expiration']);
// Create another user with the same email
$this->create_user('reset-password-test-user1', 'reset-password-test-user@test.com');
$this->create_user('reset-password-test-user1', self::TEST_EMAIL);
// Test that username is now also required
$crawler = self::request('GET', "app.php/user/forgot_password?sid={$this->sid}");
$form = $crawler->selectButton('submit')->form(array(
'email' => 'reset-password-test-user@test.com',
'email' => self::TEST_EMAIL,
));
$crawler = self::submit($form);
$this->assertContainsLang('EMAIL_NOT_UNIQUE', $crawler->text());
// Provide both username and email
$form = $crawler->selectButton('submit')->form(array(
'email' => 'reset-password-test-user@test.com',
'email' => self::TEST_EMAIL,
'username' => 'reset-password-test-user1',
));
$crawler = self::submit($form);
@ -95,7 +99,7 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
public function test_login_after_reset()
{
$this->login('reset-password-test-user');
$this->login(self::TEST_USER);
}
public function data_reset_user_password()
@ -117,7 +121,7 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
public function test_reset_user_password($expected, $user_id, $token)
{
$this->add_lang('ucp');
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$user_id = !$user_id ? $this->user_data['user_id'] : $user_id;
$token = !$token ? $this->user_data['reset_token'] : $token;
@ -131,8 +135,8 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
{
$form = $crawler->filter('input[type=submit]')->form();
$values = array_merge($form->getValues(), [
'new_password' => 'reset-password-test-user',
'new_password_confirm' => 'reset-password-test-user',
'new_password' => self::TEST_USER,
'new_password_confirm' => self::TEST_USER,
]);
$crawler = self::submit($form, $values);
$this->assertContainsLang('PASSWORD_RESET', $crawler->text());
@ -146,7 +150,7 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
$this->assertStringContainsString($this->lang('LOGIN_EXPLAIN_UCP'), $crawler->filter('html')->text());
$form = $crawler->selectButton($this->lang('LOGIN'))->form();
$crawler = self::submit($form, array('username' => 'reset-password-test-user', 'password' => 'reset-password-test-user'));
$crawler = self::submit($form, array('username' => self::TEST_USER, 'password' => self::TEST_USER));
$this->assertStringNotContainsString($this->lang('LOGIN'), $crawler->filter('.navbar')->text());
$cookies = self::$cookieJar->all();
@ -167,17 +171,17 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
$form = $crawler->selectButton($this->lang('LOGIN'))->form();
// Try logging in with the old password
$crawler = self::submit($form, array('username' => 'reset-password-test-user', 'password' => 'reset-password-test-userreset-password-test-user'));
$crawler = self::submit($form, array('username' => self::TEST_USER, 'password' => 'reset-password-test-userreset-password-test-user'));
$this->assertStringContainsString($this->lang('LOGIN_ERROR_PASSWORD', '', ''), $crawler->filter('html')->text());
}
/**
* @depends test_login
*/
public function test_acivateAfterDeactivate()
public function test_activateAfterDeactivate()
{
// User is active, actkey should not exist
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$this->assertEmpty($this->user_data['user_actkey']);
$this->login();
@ -189,7 +193,7 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
$this->assertContainsLang('FIND_USERNAME', $crawler->filter('html')->text());
$form = $crawler->selectButton('Submit')->form();
$crawler = self::submit($form, array('username' => 'reset-password-test-user'));
$crawler = self::submit($form, array('username' => self::TEST_USER));
// Deactivate account and go back to overview of current user
$this->assertContainsLang('USER_TOOLS', $crawler->filter('html')->text());
@ -201,7 +205,7 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
$crawler = self::request('GET', preg_replace('#(.+)(adm/index.php.+)#', '$2', $link->getUri()));
// Ensure again that actkey is empty after deactivation
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$this->assertEmpty($this->user_data['user_actkey']);
// Force reactivation of account and check that act key is not empty anymore
@ -210,8 +214,50 @@ class phpbb_functional_user_password_reset_test extends phpbb_functional_test_ca
$crawler = self::submit($form, array('action' => 'reactivate'));
$this->assertContainsLang('FORCE_REACTIVATION_SUCCESS', $crawler->filter('html')->text());
$this->get_user_data('reset-password-test-user');
$this->get_user_data(self::TEST_USER);
$this->assertNotEmpty($this->user_data['user_actkey']);
// Logout and try resending activation email, account is deactivated though
$this->logout();
$this->add_lang('ucp');
$crawler = self::request('GET', 'ucp.php?mode=resend_act');
$this->assertContainsLang('UCP_RESEND', $crawler->filter('html')->text());
$form = $crawler->filter('input[name=submit]')->selectButton('Submit')->form();
$crawler = self::submit($form, [
'username' => self::TEST_USER,
'email' => self::TEST_EMAIL,
]);
$this->assertContainsLang('ACCOUNT_DEACTIVATED', $crawler->filter('html')->text());
}
/**
* @depends test_activateAfterDeactivate
*/
public function test_resendActivation()
{
// User is deactivated and should have actkey, actkey should not exist
$this->get_user_data(self::TEST_USER);
$this->assertNotEmpty($this->user_data['user_actkey']);
// Change reason for inactivity
$db = $this->get_db();
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_inactive_reason = ' . INACTIVE_REMIND . '
WHERE user_id = ' . (int) $this->user_data['user_id'];
$db->sql_query($sql);
$this->add_lang('ucp');
$crawler = self::request('GET', 'ucp.php?mode=resend_act');
$this->assertContainsLang('UCP_RESEND', $crawler->filter('html')->text());
$form = $crawler->filter('input[name=submit]')->selectButton('Submit')->form();
$crawler = self::submit($form, [
'username' => self::TEST_USER,
'email' => self::TEST_EMAIL,
]);
$this->assertContainsLang('ACTIVATION_ALREADY_SENT', $crawler->filter('html')->text());
}
protected function get_user_data($username)