Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <tsteur@users.noreply.github.com>2020-06-26 05:06:53 +0300
committerGitHub <noreply@github.com>2020-06-26 05:06:53 +0300
commitf59f2eaff60e4dce5d3fc7f350fdb55f830ce0a0 (patch)
tree2ef8286206eedc92e30851de824d5cefc8e0b629
parent69ced1716928b7ca47b43b726acc8ed8b3c1ca67 (diff)
Prevent phishing attack on reset your password (#16112)
-rw-r--r--plugins/Login/Controller.php44
-rw-r--r--plugins/Login/PasswordResetter.php46
-rw-r--r--plugins/Login/lang/en.json3
-rw-r--r--plugins/Login/templates/confirmResetPassword.twig45
-rw-r--r--plugins/Login/tests/Integration/PasswordResetterTest.php23
-rw-r--r--plugins/Login/tests/UI/Login_spec.js11
-rw-r--r--plugins/Login/tests/UI/expected-screenshots/Login_password_reset_confirm.png3
m---------plugins/TreemapVisualization0
-rw-r--r--plugins/UsersManager/API.php23
-rw-r--r--plugins/UsersManager/tests/Integration/APITest.php25
-rw-r--r--plugins/UsersManager/tests/Integration/UserPreferencesTest.php32
-rw-r--r--tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png4
-rw-r--r--tests/UI/expected-screenshots/OneClickUpdate_login.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_fatal_error_safemode.png4
14 files changed, 205 insertions, 62 deletions
diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php
index b5ce90908e..36bf6e1025 100644
--- a/plugins/Login/Controller.php
+++ b/plugins/Login/Controller.php
@@ -9,6 +9,8 @@
namespace Piwik\Plugins\Login;
use Exception;
+use Piwik\Access;
+use Piwik\Auth\Password;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
@@ -18,6 +20,7 @@ use Piwik\Nonce;
use Piwik\Piwik;
use Piwik\Plugins\Login\Security\BruteForceDetection;
use Piwik\Plugins\UsersManager\Model AS UsersModel;
+use Piwik\Plugins\UsersManager\UserUpdater;
use Piwik\QuickForm2;
use Piwik\Session;
use Piwik\Url;
@@ -30,6 +33,8 @@ use Piwik\View;
*/
class Controller extends \Piwik\Plugin\ControllerAdmin
{
+ const NONCE_CONFIRMRESETPASSWORD = 'loginConfirmResetPassword';
+
/**
* @var PasswordResetter
*/
@@ -425,25 +430,49 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
*/
public function confirmResetPassword()
{
+ if (!Url::isValidHost()) {
+ throw new Exception("Cannot confirm reset password with untrusted hostname!");
+ }
+
$errorMessage = null;
+ $passwordHash = null;
- $login = Common::getRequestVar('login', '');
- $resetToken = Common::getRequestVar('resetToken', '');
+ $login = Common::getRequestVar('login');
+ $resetToken = Common::getRequestVar('resetToken');
try {
- $this->passwordResetter->confirmNewPassword($login, $resetToken);
+ $passwordHash = $this->passwordResetter->checkValidConfirmPasswordToken($login, $resetToken);
} catch (Exception $ex) {
Log::debug($ex);
$errorMessage = $ex->getMessage();
}
- if (is_null($errorMessage)) { // if success, show login w/ success message
- return $this->resetPasswordSuccess();
- } else {
- // show login page w/ error. this will keep the token in the URL
+ if (!empty($errorMessage)) {
return $this->login($errorMessage);
}
+
+ if (!empty($_POST['nonce'])
+ && !empty($_POST['mtmpasswordconfirm'])
+ && !empty($resetToken)
+ && !empty($login)
+ && !empty($passwordHash)
+ && empty($errorMessage)) {
+ Nonce::checkNonce(self::NONCE_CONFIRMRESETPASSWORD, $_POST['nonce']);
+ if ($this->passwordResetter->doesResetPasswordHashMatchesPassword($_POST['mtmpasswordconfirm'], $passwordHash)) {
+ $this->passwordResetter->setHashedPasswordForLogin($login, $passwordHash);
+ return $this->resetPasswordSuccess();
+ } else {
+ $errorMessage = Piwik::translate('Login_ConfirmPasswordResetWrongPassword');
+ }
+ }
+
+ $nonce = Nonce::getNonce(self::NONCE_CONFIRMRESETPASSWORD);
+
+ return $this->renderTemplateAs('confirmResetPassword', array(
+ 'nonce' => $nonce,
+ 'errorMessage' => $errorMessage
+ ), 'basic');
}
/**
@@ -453,6 +482,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
*/
public function resetPasswordSuccess()
{
+ $_POST = array(); // prevent showing error message username and password is missing
return $this->login($errorMessage = null, $infoMessage = Piwik::translate('Login_PasswordChanged'));
}
diff --git a/plugins/Login/PasswordResetter.php b/plugins/Login/PasswordResetter.php
index f1e73cfeee..59812aee91 100644
--- a/plugins/Login/PasswordResetter.php
+++ b/plugins/Login/PasswordResetter.php
@@ -191,20 +191,7 @@ class PasswordResetter
}
}
- /**
- * Confirms a password reset. This should be called after {@link initiatePasswordResetProcess()}
- * is called.
- *
- * This method will get the new password associated with a reset token and set it
- * as the specified user's password.
- *
- * @param string $login The login of the user whose password is being reset.
- * @param string $resetToken The generated string token contained in the reset password
- * email.
- * @throws Exception If there is no user with login '$login', if $resetToken is not a
- * valid token or if the token has expired.
- */
- public function confirmNewPassword($login, $resetToken)
+ public function checkValidConfirmPasswordToken($login, $resetToken)
{
// get password reset info & user info
$user = self::getUserInformation($login);
@@ -224,13 +211,30 @@ class PasswordResetter
// check that the stored password hash is valid (sanity check)
$resetPassword = $resetInfo['hash'];
+
$this->checkPasswordHash($resetPassword);
- // reset password of user
- $usersManager = $this->usersManagerApi;
- Access::doAsSuperUser(function () use ($usersManager, $user, $resetPassword) {
+ return $resetPassword;
+ }
+
+ /**
+ * Confirms a password reset. This should be called after {@link initiatePasswordResetProcess()}
+ * is called.
+ *
+ * This method will get the new password associated with a reset token and set it
+ * as the specified user's password.
+ *
+ * @param string $login The login of the user whose password is being reset.
+ * @param string $passwordHash The generated string token contained in the reset password
+ * email.
+ * @throws Exception If there is no user with login '$login', if $resetToken is not a
+ * valid token or if the token has expired.
+ */
+ public function setHashedPasswordForLogin($login, $passwordHash)
+ {
+ Access::doAsSuperUser(function () use ($login, $passwordHash) {
$userUpdater = new UserUpdater();
- $userUpdater->updateUserWithoutCurrentPassword($user['login'], $resetPassword, $email = false, $alias = false, $isPasswordHashed = true);
+ $userUpdater->updateUserWithoutCurrentPassword($login, $passwordHash, $email = false, $alias = false, $isPasswordHashed = true);
});
}
@@ -288,6 +292,12 @@ class PasswordResetter
return $token;
}
+ public function doesResetPasswordHashMatchesPassword($passwordPlain, $passwordHash)
+ {
+ $passwordPlain = UsersManager::getPasswordHash($passwordPlain);
+ return $this->passwordHelper->verify($passwordPlain, $passwordHash);
+ }
+
/**
* Generates a hash using a hash "identifier" and some data to hash. The hash identifier is
* a string that differentiates the hash in some way.
diff --git a/plugins/Login/lang/en.json b/plugins/Login/lang/en.json
index d13dffbca8..8b72632048 100644
--- a/plugins/Login/lang/en.json
+++ b/plugins/Login/lang/en.json
@@ -20,6 +20,9 @@
"SettingBruteForceMaxFailedLoginsHelp": "If more than this number of failed logins are recorded within the time range configured below, block the IP.",
"SettingBruteForceTimeRange": "Count login retries within this time range in minutes",
"SettingBruteForceTimeRangeHelp": "Enter a number in minutes.",
+ "ConfirmPasswordReset": "Confirm password reset",
+ "ConfirmPasswordResetIntro": "To confirm it is really you who requested this password change, please enter your new password again.",
+ "ConfirmPasswordResetWrongPassword": "The entered password does not match your new password. If you don't remember your newly chosen password you can reset your password again. If you didn't request the password change, simply do nothing and your password won't be changed.",
"LoginNotAllowedBecauseBlocked": "You are currently not allowed to log in because you had too many failed logins, try again later.",
"CurrentlyBlockedIPs": "Currently blocked IPs",
"IPsAlwaysBlocked": "These IPs are always blocked",
diff --git a/plugins/Login/templates/confirmResetPassword.twig b/plugins/Login/templates/confirmResetPassword.twig
new file mode 100644
index 0000000000..4abb1b82dd
--- /dev/null
+++ b/plugins/Login/templates/confirmResetPassword.twig
@@ -0,0 +1,45 @@
+{% extends '@Login/loginLayout.twig' %}
+
+{% set title %}{{ 'Login_ConfirmPasswordToContinue'|translate }}{% endset %}
+
+{% block loginContent %}
+ <div class="contentForm loginForm confirmPasswordForm">
+ {% embed 'contentBlock.twig' with {'title': ('Login_ConfirmPasswordReset'|translate)} %}
+ {% block content %}
+ <p>{{ 'Login_ConfirmPasswordResetIntro'|translate }}</p>
+
+ <div class="message_container">
+ {% if errorMessage is not empty %}
+ <div piwik-notification
+ noclear="true"
+ context="error">
+ <strong>{{ 'General_Error'|translate }}</strong>: {{ errorMessage }}<br/>
+ </div>
+ {% endif %}
+ </div>
+ <br>
+
+ <form action="{{ linkTo({'module': 'Login', 'action': 'confirmResetPassword'}) }}" ng-non-bindable method="post">
+ <div class="row">
+ <div class="col s12 input-field">
+ <input type="hidden" name="nonce" value="{{ nonce }}"/>
+ <input type="password" placeholder="" name="mtmpasswordconfirm" id="mtmpasswordconfirm" class="input" value="" size="20"
+ autocorrect="off" autocapitalize="none"
+ tabindex="20" />
+ <label for="mtmpasswordconfirm"><i class="icon-locked icon"></i> {{ 'Login_NewPassword'|translate }}</label>
+ </div>
+ </div>
+
+ <div class="row actions">
+ <div class="col s12">
+ <input class="submit btn" id='login_reset_confirm' type="submit" value="{{ 'General_Confirm'|translate }}"
+ tabindex="100"/>
+ </div>
+ </div>
+
+ </form>
+ {% endblock %}
+ {% endembed %}
+ </div>
+
+{% endblock %} \ No newline at end of file
diff --git a/plugins/Login/tests/Integration/PasswordResetterTest.php b/plugins/Login/tests/Integration/PasswordResetterTest.php
index f3603c7aca..68cda80982 100644
--- a/plugins/Login/tests/Integration/PasswordResetterTest.php
+++ b/plugins/Login/tests/Integration/PasswordResetterTest.php
@@ -51,19 +51,7 @@ class PasswordResetterTest extends IntegrationTestCase
public function test_passwordReset_processWorksAsExpected()
{
- $user = $this->userModel->getUser('superUserLogin');
- $password = $user['password'];
- $passwordModified = $user['ts_password_modified'];
-
- $this->passwordResetter->initiatePasswordResetProcess('superUserLogin', self::NEWPASSWORD);
-
- $this->assertNotEmpty($this->capturedToken);
-
- $user = $this->userModel->getUser('superUserLogin');
- $this->assertEquals($password, $user['password']);
- $this->assertEquals($passwordModified, $user['ts_password_modified']);
-
- $this->passwordResetter->confirmNewPassword('superUserLogin', $this->capturedToken);
+ $this->passwordResetter->setHashedPasswordForLogin('superUserLogin', $this->capturedToken);
$this->checkPasswordIs(self::NEWPASSWORD);
}
@@ -116,6 +104,9 @@ class PasswordResetterTest extends IntegrationTestCase
Option::set($optionName, json_encode($data));
+ $this->assertTrue($this->passwordResetter->doesResetPasswordHashMatchesPassword(self::NEWPASSWORD, $data['hash']));
+ $this->assertFalse($this->passwordResetter->doesResetPasswordHashMatchesPassword('foobar', $data['hash']));
+
$this->passwordResetter->initiatePasswordResetProcess('superUserLogin', self::NEWPASSWORD);
$optionName = $this->passwordResetter->getPasswordResetInfoOptionName('superUserLogin');
@@ -133,7 +124,7 @@ class PasswordResetterTest extends IntegrationTestCase
$this->passwordResetter->initiatePasswordResetProcess('superUserLogin', self::NEWPASSWORD);
$this->assertNotEmpty($this->capturedToken);
- $this->passwordResetter->confirmNewPassword('superUserLogin', $this->capturedToken);
+ $this->passwordResetter->checkValidConfirmPasswordToken('superUserLogin', $this->capturedToken);
$this->checkPasswordIs(self::NEWPASSWORD);
sleep(1);
@@ -142,7 +133,7 @@ class PasswordResetterTest extends IntegrationTestCase
$this->passwordResetter->initiatePasswordResetProcess('superUserLogin', 'anotherpassword');
$this->assertNotEquals($oldCapturedToken, $this->capturedToken);
- $this->passwordResetter->confirmNewPassword('superUserLogin', $oldCapturedToken);
+ $this->passwordResetter->checkValidConfirmPasswordToken('superUserLogin', $oldCapturedToken);
}
public function test_passwordReset_shouldNeverGenerateTheSameToken()
@@ -172,7 +163,7 @@ class PasswordResetterTest extends IntegrationTestCase
$this->passwordResetter->initiatePasswordResetProcess('superUserLogin', self::NEWPASSWORD);
$this->assertNotEquals($oldCapturedToken, $this->capturedToken);
- $this->passwordResetter->confirmNewPassword('superUserLogin', $oldCapturedToken);
+ $this->passwordResetter->checkValidConfirmPasswordToken('superUserLogin', $oldCapturedToken);
}
/**
diff --git a/plugins/Login/tests/UI/Login_spec.js b/plugins/Login/tests/UI/Login_spec.js
index 855973dbc4..cf365b81d8 100644
--- a/plugins/Login/tests/UI/Login_spec.js
+++ b/plugins/Login/tests/UI/Login_spec.js
@@ -149,7 +149,7 @@ describe("Login", function () {
expect(await page.screenshot({ fullPage: true })).to.matchImage('password_reset');
});
- it("should reset password when password reset link is clicked", async function() {
+ it("should show reset password confirmation page when password reset link is clicked", async function() {
var expectedMailOutputFile = PIWIK_INCLUDE_PATH + '/tmp/Login.resetPassword.mail.json',
fileContents = require("fs").readFileSync(expectedMailOutputFile),
mailSent = JSON.parse(fileContents),
@@ -163,6 +163,15 @@ describe("Login", function () {
await page.goto(resetUrl);
await page.waitForNetworkIdle();
+ expect(await page.screenshot({ fullPage: true })).to.matchImage('password_reset_confirm');
+ });
+
+ it("should reset password when password reset link is clicked", async function() {
+
+ await page.type("#mtmpasswordconfirm", "superUserPass2");
+ await page.click("#login_reset_confirm");
+ await page.waitForNetworkIdle();
+
expect(await page.screenshot({ fullPage: true })).to.matchImage('password_reset_complete');
});
diff --git a/plugins/Login/tests/UI/expected-screenshots/Login_password_reset_confirm.png b/plugins/Login/tests/UI/expected-screenshots/Login_password_reset_confirm.png
new file mode 100644
index 0000000000..62dd3d5bb8
--- /dev/null
+++ b/plugins/Login/tests/UI/expected-screenshots/Login_password_reset_confirm.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1eb721537020989bfe95ddb9174311d86c608e37c4f6789cc7e34bcdfe333364
+size 34570
diff --git a/plugins/TreemapVisualization b/plugins/TreemapVisualization
-Subproject 9bcf17033ca4da490a3f459cdc52bb76c8eee5d
+Subproject f71593cc303b2b15d8f96cb222cc6c54c6412c1
diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php
index 51f09107a6..7898e589e6 100644
--- a/plugins/UsersManager/API.php
+++ b/plugins/UsersManager/API.php
@@ -188,7 +188,17 @@ class API extends \Piwik\Plugin\API
public function setUserPreference($userLogin, $preferenceName, $preferenceValue)
{
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
- Option::set($this->getPreferenceId($userLogin, $preferenceName), $preferenceValue);
+
+ if (!$this->model->userExists($userLogin)) {
+ throw new Exception('User does not exist: ' . $userLogin);
+ }
+
+ if ($userLogin === 'anonymous') {
+ Piwik::checkUserHasSuperUserAccess();
+ }
+
+ $nameIfSupported = $this->getPreferenceId($userLogin, $preferenceName);
+ Option::set($nameIfSupported, $preferenceValue);
}
/**
@@ -267,6 +277,17 @@ class API extends \Piwik\Plugin\API
if(false !== strpos($preference, self::OPTION_NAME_PREFERENCE_SEPARATOR)) {
throw new Exception("Preference name cannot contain underscores.");
}
+ $names = array(
+ self::PREFERENCE_DEFAULT_REPORT,
+ self::PREFERENCE_DEFAULT_REPORT_DATE,
+ 'hideSegmentDefinitionChangeMessage',// used in JS
+ 'randomDoesNotExist',// for tests
+ 'RandomNOTREQUESTED',// for tests
+ 'preferenceName'// for tests
+ );
+ if (!in_array($preference, $names, true)) {
+ throw new Exception('Not supported preference name: ' . $preference);
+ }
return $login . self::OPTION_NAME_PREFERENCE_SEPARATOR . $preference;
}
diff --git a/plugins/UsersManager/tests/Integration/APITest.php b/plugins/UsersManager/tests/Integration/APITest.php
index 7605335e88..db110571e8 100644
--- a/plugins/UsersManager/tests/Integration/APITest.php
+++ b/plugins/UsersManager/tests/Integration/APITest.php
@@ -12,7 +12,6 @@ use Piwik\Access\Role\View;
use Piwik\Access\Role\Write;
use Piwik\Auth\Password;
use Piwik\Config;
-use Piwik\Container\StaticContainer;
use Piwik\Mail;
use Piwik\Option;
use Piwik\Piwik;
@@ -203,7 +202,7 @@ class APITest extends IntegrationTestCase
public function test_getAllUsersPreferences_isEmpty_whenNoPreferenceAndMultipleRequested()
{
- $preferences = $this->api->getAllUsersPreferences(array('preferenceName', 'otherOne'));
+ $preferences = $this->api->getAllUsersPreferences(array('preferenceName', 'randomDoesNotExist'));
$this->assertEmpty($preferences);
}
@@ -254,24 +253,24 @@ class APITest extends IntegrationTestCase
$user2 = 'userLogin2';
$user3 = 'userLogin3';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
- $this->api->setUserPreference($user2, 'myPreferenceName', 'valueForUser2');
+ $this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser2');
$this->api->setUserPreference($user2, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED');
$this->api->addUser($user3, 'password', 'userlogin3@password.de');
- $this->api->setUserPreference($user3, 'myPreferenceName', 'valueForUser3');
- $this->api->setUserPreference($user3, 'otherPreferenceHere', 'otherPreferenceVALUE');
+ $this->api->setUserPreference($user3, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser3');
+ $this->api->setUserPreference($user3, API::PREFERENCE_DEFAULT_REPORT_DATE, 'otherPreferenceVALUE');
$this->api->setUserPreference($user3, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED');
$expected = array(
$user2 => array(
- 'myPreferenceName' => 'valueForUser2'
+ API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2'
),
$user3 => array(
- 'myPreferenceName' => 'valueForUser3',
- 'otherPreferenceHere' => 'otherPreferenceVALUE',
+ API::PREFERENCE_DEFAULT_REPORT => 'valueForUser3',
+ API::PREFERENCE_DEFAULT_REPORT_DATE => 'otherPreferenceVALUE',
),
);
- $result = $this->api->getAllUsersPreferences(array('myPreferenceName', 'otherPreferenceHere', 'randomDoesNotExist'));
+ $result = $this->api->getAllUsersPreferences(array(API::PREFERENCE_DEFAULT_REPORT, API::PREFERENCE_DEFAULT_REPORT_DATE, 'randomDoesNotExist'));
$this->assertSame($expected, $result);
}
@@ -280,15 +279,15 @@ class APITest extends IntegrationTestCase
{
$user2 = 'user_Login2';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
- $this->api->setUserPreference($user2, 'myPreferenceName', 'valueForUser2');
- $this->api->setUserPreference($user2, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED');
+ $this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser2');
+ $this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT_DATE, 'RandomNOTREQUESTED');
$expected = array(
$user2 => array(
- 'myPreferenceName' => 'valueForUser2'
+ API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2'
),
);
- $result = $this->api->getAllUsersPreferences(array('myPreferenceName', 'otherPreferenceHere', 'randomDoesNotExist'));
+ $result = $this->api->getAllUsersPreferences(array(API::PREFERENCE_DEFAULT_REPORT, 'randomDoesNotExist'));
$this->assertSame($expected, $result);
}
diff --git a/plugins/UsersManager/tests/Integration/UserPreferencesTest.php b/plugins/UsersManager/tests/Integration/UserPreferencesTest.php
index b584541442..ee0bc28b26 100644
--- a/plugins/UsersManager/tests/Integration/UserPreferencesTest.php
+++ b/plugins/UsersManager/tests/Integration/UserPreferencesTest.php
@@ -36,6 +36,38 @@ class UserPreferencesTest extends IntegrationTestCase
$this->userPreferences = new UserPreferences();
$this->setSuperUser();
+
+ $identity = FakeAccess::$identity;
+ FakeAccess::$identity = 'foo'; // avoids error user already exists when it doesn't
+ APIUsersManager::getInstance()->addUser($identity, '22111214k4,mdw<L', 'foo@example.com');
+ FakeAccess::$identity = $identity;
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage User does not exist
+ */
+ public function test_getDefaultReport_WhenLoginNotExists()
+ {
+ APIUsersManager::getInstance()->setUserPreference(
+ 'foo',
+ APIUsersManager::PREFERENCE_DEFAULT_REPORT,
+ '1'
+ );
+ }
+
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Not supported preference name
+ */
+ public function test_getDefaultReport_WhenWrongPreference()
+ {
+ APIUsersManager::getInstance()->setUserPreference(
+ Piwik::getCurrentUserLogin(),
+ 'foo',
+ '1'
+ );
}
public function test_getDefaultReport_ShouldReturnFalseByDefault()
diff --git a/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png b/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png
index 364c635978..36f625300a 100644
--- a/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png
+++ b/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:955f729afa61f6602b09e45da4535de8e64608cc7a4f14229a1fd4992f88e88f
-size 300129
+oid sha256:de697c64644277ab5881df9ef5f61e6b1b11b1354dedd8e269283a5a0b440491
+size 301464
diff --git a/tests/UI/expected-screenshots/OneClickUpdate_login.png b/tests/UI/expected-screenshots/OneClickUpdate_login.png
index c0f41534c3..d80c5a30f7 100644
--- a/tests/UI/expected-screenshots/OneClickUpdate_login.png
+++ b/tests/UI/expected-screenshots/OneClickUpdate_login.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1053964b638aff9107e69cd0d465a0a72799f3ea9db8884df3117c6d42efc830
-size 268010
+oid sha256:dc51c04af8628082dc40b503a91a2b3abbb25dacc173afdb286017b86d053f71
+size 268939
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_fatal_error_safemode.png b/tests/UI/expected-screenshots/UIIntegrationTest_fatal_error_safemode.png
index 38ba20c78f..5c25fda325 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_fatal_error_safemode.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_fatal_error_safemode.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:84920bd97bb2dab3b76ba599cb1465f78c56a1901b017805b558917bdcea33ca
-size 171185
+oid sha256:da06087b21b29b1046e6c0c5c7172b88ed4855b2b05a7873452c7820c23aaed3
+size 171256