Skip to content

Commit b9a8bcb

Browse files
bnfohader
authored andcommitted
[SECURITY] Require step-up authentication for password change
Require a password confirmation for every password change of backend users via FormEngine (applies to own passwords and passwords of other users). Also require a recent user verification (step-up) for any change to backend user details. Resolves: #103252 Releases: main, 13.4, 12.4 Change-Id: I2a74b15dd3d7e7bded8b59b5df5af1097d5e7b59 Security-Bulletin: TYPO3-CORE-SA-2025-013 Security-References: CVE-2025-47938 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/89467 Tested-by: Oliver Hader <[email protected]> Reviewed-by: Oliver Hader <[email protected]>
1 parent fd0be9f commit b9a8bcb

File tree

7 files changed

+147
-1
lines changed

7 files changed

+147
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
defined('TYPO3') or die();
4+
5+
$GLOBALS['TCA']['be_groups']['columns']['hidden']['authenticationContext']['group'] = 'be.userManagement';

Configuration/TCA/Overrides/be_users.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
// New be_users are disabled by default and can not disable themselves
66
$GLOBALS['TCA']['be_users']['columns']['disable']['displayCond'] = 'USER:' . \TYPO3\CMS\Core\Hooks\TcaDisplayConditions::class . '->isRecordCurrentUser:false';
77
$GLOBALS['TCA']['be_users']['columns']['disable']['config']['default'] = 1;
8+
9+
$GLOBALS['TCA']['be_users']['columns']['disable']['authenticationContext']['group'] = 'be.userManagement';
10+
$GLOBALS['TCA']['be_users']['columns']['starttime']['authenticationContext']['group'] = 'be.userManagement';
11+
$GLOBALS['TCA']['be_users']['columns']['endtime']['authenticationContext']['group'] = 'be.userManagement';

Configuration/TCA/be_groups.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
'size' => 3,
4444
'autoSizeMax' => 10,
4545
],
46+
'authenticationContext' => [
47+
'group' => 'be.userManagement',
48+
],
4649
],
4750
'file_mountpoints' => [
4851
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:file_mountpoints',
@@ -75,6 +78,9 @@
7578
],
7679
],
7780
],
81+
'authenticationContext' => [
82+
'group' => 'be.userManagement',
83+
],
7884
],
7985
'file_permissions' => [
8086
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.fileoper_perms',
@@ -105,6 +111,9 @@
105111
'maxitems' => 17,
106112
'default' => 'readFolder,writeFolder,addFolder,renameFolder,moveFolder,deleteFolder,readFile,writeFile,addFile,renameFile,replaceFile,moveFile,copyFile,deleteFile',
107113
],
114+
'authenticationContext' => [
115+
'group' => 'be.userManagement',
116+
],
108117
],
109118
'workspace_perms' => [
110119
'displayCond' => 'USER:TYPO3\CMS\Core\Hooks\TcaDisplayConditions->isExtensionInstalled:workspaces',
@@ -118,6 +127,9 @@
118127
['label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:workspace_perms_live'],
119128
],
120129
],
130+
'authenticationContext' => [
131+
'group' => 'be.userManagement',
132+
],
121133
],
122134
'pagetypes_select' => [
123135
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.pagetypes_select',
@@ -128,6 +140,9 @@
128140
'size' => 5,
129141
'autoSizeMax' => 50,
130142
],
143+
'authenticationContext' => [
144+
'group' => 'be.userManagement',
145+
],
131146
],
132147
'tables_modify' => [
133148
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.tables_modify',
@@ -138,12 +153,18 @@
138153
'selectFieldName' => 'tables_select',
139154
'itemsProcFunc' => \TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions::class . '->populateAvailableTables',
140155
],
156+
'authenticationContext' => [
157+
'group' => 'be.userManagement',
158+
],
141159
],
142160
'tables_select' => [
143161
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.tables_select',
144162
'config' => [
145163
'type' => 'passthrough',
146164
],
165+
'authenticationContext' => [
166+
'group' => 'be.userManagement',
167+
],
147168
],
148169
'non_exclude_fields' => [
149170
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.non_exclude_fields',
@@ -155,6 +176,9 @@
155176
'size' => 25,
156177
'autoSizeMax' => 50,
157178
],
179+
'authenticationContext' => [
180+
'group' => 'be.userManagement',
181+
],
158182
],
159183
'explicit_allowdeny' => [
160184
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.explicit_allowdeny',
@@ -163,6 +187,9 @@
163187
'renderType' => 'selectCheckBox',
164188
'itemsProcFunc' => \TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions::class . '->populateExplicitAuthValues',
165189
],
190+
'authenticationContext' => [
191+
'group' => 'be.userManagement',
192+
],
166193
],
167194
'allowed_languages' => [
168195
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:allowed_languages',
@@ -173,6 +200,9 @@
173200
'itemsProcFunc' => \TYPO3\CMS\Core\Localization\TcaSystemLanguageCollector::class . '->populateAvailableSiteLanguages',
174201
'dbFieldLength' => 255,
175202
],
203+
'authenticationContext' => [
204+
'group' => 'be.userManagement',
205+
],
176206
],
177207
'custom_options' => [
178208
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.custom_options',
@@ -191,6 +221,9 @@
191221
'size' => 5,
192222
'autoSizeMax' => 50,
193223
],
224+
'authenticationContext' => [
225+
'group' => 'be.userManagement',
226+
],
194227
],
195228
'mfa_providers' => [
196229
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:mfa_providers',
@@ -201,6 +234,9 @@
201234
'size' => 5,
202235
'autoSizeMax' => 50,
203236
],
237+
'authenticationContext' => [
238+
'group' => 'be.userManagement',
239+
],
204240
],
205241
'TSconfig' => [
206242
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig',
@@ -222,6 +258,9 @@
222258
'size' => 5,
223259
'autoSizeMax' => 50,
224260
],
261+
'authenticationContext' => [
262+
'group' => 'be.userManagement',
263+
],
225264
],
226265
'category_perms' => [
227266
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:category_perms',
@@ -235,6 +274,9 @@
235274
],
236275
],
237276
],
277+
'authenticationContext' => [
278+
'group' => 'be.userManagement',
279+
],
238280
],
239281
],
240282
'types' => [

Configuration/TCA/be_users.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
'eval' => 'nospace,trim,lower,unique',
4040
'autocomplete' => false,
4141
],
42+
'authenticationContext' => [
43+
'group' => 'be.userManagement',
44+
],
4245
],
4346
'password' => [
4447
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.password',
@@ -48,6 +51,10 @@
4851
'size' => 20,
4952
'required' => true,
5053
],
54+
'authenticationContext' => [
55+
//'group' => 'be.userManagement',
56+
'once' => true,
57+
],
5158
],
5259
'mfa' => [
5360
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.mfa',
@@ -56,6 +63,9 @@
5663
'type' => 'none',
5764
'renderType' => 'mfaInfo',
5865
],
66+
'authenticationContext' => [
67+
'group' => 'be.userManagement',
68+
],
5969
],
6070
'usergroup' => [
6171
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.usergroup',
@@ -87,6 +97,9 @@
8797
],
8898
],
8999
],
100+
'authenticationContext' => [
101+
'group' => 'be.userManagement',
102+
],
90103
],
91104
'avatar' => [
92105
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.avatar',
@@ -106,6 +119,9 @@
106119
'maxitems' => 100,
107120
'autoSizeMax' => 10,
108121
],
122+
'authenticationContext' => [
123+
'group' => 'be.userManagement',
124+
],
109125
],
110126
'file_mountpoints' => [
111127
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.options_file_mounts',
@@ -139,13 +155,19 @@
139155
],
140156
],
141157
],
158+
'authenticationContext' => [
159+
'group' => 'be.userManagement',
160+
],
142161
],
143162
'email' => [
144163
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.email',
145164
'config' => [
146165
'type' => 'email',
147166
'size' => 20,
148167
],
168+
'authenticationContext' => [
169+
'group' => 'be.userManagement',
170+
],
149171
],
150172
'realName' => [
151173
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.name',
@@ -168,6 +190,9 @@
168190
],
169191
],
170192
],
193+
'authenticationContext' => [
194+
'group' => 'be.userManagement',
195+
],
171196
],
172197
'options' => [
173198
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.options',
@@ -209,6 +234,9 @@
209234
'maxitems' => 17,
210235
'default' => 'readFolder,writeFolder,addFolder,renameFolder,moveFolder,deleteFolder,readFile,writeFile,addFile,renameFile,replaceFile,moveFile,copyFile,deleteFile',
211236
],
237+
'authenticationContext' => [
238+
'group' => 'be.userManagement',
239+
],
212240
],
213241
'workspace_perms' => [
214242
'displayCond' => 'USER:TYPO3\CMS\Core\Hooks\TcaDisplayConditions->isExtensionInstalled:workspaces',
@@ -222,6 +250,9 @@
222250
['label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:workspace_perms_live'],
223251
],
224252
],
253+
'authenticationContext' => [
254+
'group' => 'be.userManagement',
255+
],
225256
],
226257
'lang' => [
227258
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.lang',
@@ -248,6 +279,9 @@
248279
'autoSizeMax' => 50,
249280
'maxitems' => 100,
250281
],
282+
'authenticationContext' => [
283+
'group' => 'be.userManagement',
284+
],
251285
],
252286
'allowed_languages' => [
253287
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:allowed_languages',
@@ -258,6 +292,9 @@
258292
'itemsProcFunc' => \TYPO3\CMS\Core\Localization\TcaSystemLanguageCollector::class . '->populateAvailableSiteLanguages',
259293
'dbFieldLength' => 255,
260294
],
295+
'authenticationContext' => [
296+
'group' => 'be.userManagement',
297+
],
261298
],
262299
'TSconfig' => [
263300
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig',
@@ -289,6 +326,9 @@
289326
],
290327
],
291328
],
329+
'authenticationContext' => [
330+
'group' => 'be.userManagement',
331+
],
292332
],
293333
],
294334
'types' => [

Resources/Public/JavaScript/ajax/ajax-request.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tests/Acceptance/Application/Impexp/UsersCest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Impexp;
1919

20+
use Codeception\Exception\MalformedLocatorException;
2021
use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester;
2122
use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree;
2223

@@ -194,6 +195,20 @@ private function setPageAccess(ApplicationTester $I, PageTree $pageTree, array $
194195
$recursionLevelOption = $I->grabTextFrom('//select[@id="recursionLevel"]/option[' . $recursionLevel . ']');
195196
$I->selectOption('//select[@id="recursionLevel"]', ['value' => $recursionLevelOption]);
196197
$I->click($this->inModuleHeader . ' .btn[title="Save and close"]');
198+
$I->wait(0.5);
199+
$I->switchToMainFrame();
200+
try {
201+
$needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
202+
} catch (MalformedLocatorException) {
203+
$needsStepUp = false;
204+
}
205+
if ($needsStepUp) {
206+
$I->see('Verify with user password');
207+
$I->fillField('//input[@name="password"]', 'password');
208+
$I->click('//button[@name="verify"]');
209+
}
210+
$I->switchToContentFrame();
211+
$I->wait(0.5);
197212
}
198213

199214
private function setModAccess(ApplicationTester $I, int $userGroupId, array $modAccessByName): void
@@ -219,6 +234,19 @@ private function setModAccess(ApplicationTester $I, int $userGroupId, array $mod
219234

220235
$I->click($this->inModuleHeader . ' .btn[title="Save"]');
221236
$I->wait(0.5);
237+
$I->switchToMainFrame();
238+
try {
239+
$needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
240+
} catch (MalformedLocatorException) {
241+
$needsStepUp = false;
242+
}
243+
if ($needsStepUp) {
244+
$I->see('Verify with user password');
245+
$I->fillField('//input[@name="password"]', 'password');
246+
$I->click('//button[@name="verify"]');
247+
}
248+
$I->switchToContentFrame();
249+
$I->wait(0.5);
222250
$I->click($this->inModuleHeader . ' .btn[title="Close"]');
223251
$I->waitForText('Backend user groups');
224252
}
@@ -245,6 +273,19 @@ private function setUserTsConfig(ApplicationTester $I, int $userId, string $user
245273
$I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('" . $userTsConfig . "')");
246274
$I->click($this->inModuleHeader . ' .btn[title="Save"]');
247275
$I->wait(0.5);
276+
$I->switchToMainFrame();
277+
try {
278+
$needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
279+
} catch (MalformedLocatorException) {
280+
$needsStepUp = false;
281+
}
282+
if ($needsStepUp) {
283+
$I->see('Verify with user password');
284+
$I->fillField('//input[@name="password"]', 'password');
285+
$I->click('//button[@name="verify"]');
286+
}
287+
$I->switchToContentFrame();
288+
$I->wait(0.5);
248289
$I->click($this->inModuleHeader . ' .btn[title="Close"]');
249290
$I->waitForElement('#typo3-backend-user-list');
250291
}

Tests/Acceptance/Application/RecordList/RecordDownloadWithPresetCest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace TYPO3\CMS\Core\Tests\Acceptance\Application\RecordList;
1919

20+
use Codeception\Exception\MalformedLocatorException;
2021
use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester;
2122
use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog;
2223
use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree;
@@ -102,6 +103,19 @@ private function setUserTsConfig(ApplicationTester $I, int $userId, string $user
102103
$I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('" . $userTsConfig . "')");
103104
$I->click($this->inModuleHeader . ' .btn[title="Save"]');
104105
$I->wait(0.5);
106+
$I->switchToMainFrame();
107+
try {
108+
$needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
109+
} catch (MalformedLocatorException) {
110+
$needsStepUp = false;
111+
}
112+
if ($needsStepUp) {
113+
$I->see('Verify with user password');
114+
$I->fillField('//input[@name="password"]', 'password');
115+
$I->click('//button[@name="verify"]');
116+
}
117+
$I->switchToContentFrame();
118+
$I->wait(0.5);
105119
$I->click($this->inModuleHeader . ' .btn[title="Close"]');
106120
$I->waitForElement('#typo3-backend-user-list');
107121
}

0 commit comments

Comments
 (0)