VYPR
Low severityNVD Advisory· Published May 20, 2025· Updated May 20, 2025

TYPO3 Vulnerable to Unverified Password Change for Backend Users

CVE-2025-47938

Description

TYPO3 is an open source, PHP based web content management system. Starting in version 9.0.0 and prior to versions 9.5.51 ELTS, 10.4.50 ELTS, 11.5.44 ELTS, 12.4.31 LTS, and 13.4.12 LTS, the backend user management interface allows password changes without requiring the current password. When an administrator updates their own account or modifies other user accounts via the admin interface, the current password is not requested for verification. This behavior may lower the protection against unauthorized access in scenarios where an admin session is hijacked or left unattended, as it enables password changes without additional authentication. Users should update to TYPO3 version 9.5.51 ELTS, 10.4.50 ELTS, 11.5.44 ELTS, 12.4.31 LTS, or 13.4.12 LTS to fix the problem.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

An unverified password change vulnerability in TYPO3 backend allows password reset without current credential verification, enabling privilege escalation if an admin session is hijacked.

Vulnerability

Description

CVE-2025-47938 is a security misconfiguration in TYPO3 CMS that permits backend user password changes without requiring the current password. In affected versions (9.0.0 through 13.4.11), both the DataHandler component (ext:core) and the Setup module (ext:setup) allow administrators — when updating their own account or modifying other user accounts — to submit a new password without verifying their identity first [1][4]. The issue is tracked as CWE-620 (Unverified Password Change) [4].

Exploitation

The attack surface is limited to authenticated backend sessions, requiring an attacker to have already gained administrative access via session hijacking, an unattended session, or other means [1][4]. Because the interface does not request the current password, an attacker who controls an active admin session can immediately change the password for the admin account or any other backend user, locking out the legitimate owner [1][2].

Impact

This weakness significantly lowers the barrier for privilege escalation in scenarios where an admin session is compromised or left unattended [4]. An attacker who obtains temporary backend access can achieve persistent control by changing passwords, then maintaining access even after the original session expires [1].

Mitigation

The fix introduces step-up authentication (sudo mode) before password changes, implemented through an authentication context configuration in the TYPO3 TCA forms and corresponding logic in the Setup module [2][3]. Patched versions are 9.5.51 ELTS, 10.4.50 ELTS, 11.5.44 ELTS, 12.4.31 LTS, and 13.4.12 LTS [1][4]. The advisory notes that administrators using remote SSO may need to handle new PSR-14 events (SudoModeRequiredEvent and SudoModeVerifyEvent) to integrate step-up authentication [4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
typo3/cms-corePackagist
>= 9.0.0, < 9.5.519.5.51
typo3/cms-setupPackagist
>= 9.0.0, < 9.5.519.5.51
typo3/cms-corePackagist
>= 10.0.0, < 10.4.5010.4.50
typo3/cms-corePackagist
>= 11.0.0, < 11.5.4411.5.44
typo3/cms-corePackagist
>= 12.0.0, < 12.4.3112.4.31
typo3/cms-corePackagist
>= 13.0.0, < 13.4.1213.4.12
typo3/cms-setupPackagist
>= 10.0.0, < 10.4.5010.4.50
typo3/cms-setupPackagist
>= 11.0.0, < 11.5.4411.5.44
typo3/cms-setupPackagist
>= 12.0.0, < 12.4.3112.4.31
typo3/cms-setupPackagist
>= 13.0.0, < 13.4.1213.4.12

Affected products

4
  • TYPO3/Typo3llm-fuzzy2 versions
    >=9.0.0, <9.5.51 ELTS or <10.4.50 ELTS or <11.5.44 ELTS or <12.4.31 LTS or <13.4.12 LTS+ 1 more
    • (no CPE)range: >=9.0.0, <9.5.51 ELTS or <10.4.50 ELTS or <11.5.44 ELTS or <12.4.31 LTS or <13.4.12 LTS
    • (no CPE)range: >= 9.0.0, < 9.5.51
  • ghsa-coords2 versions
    >= 9.0.0, < 9.5.51+ 1 more
    • (no CPE)range: >= 9.0.0, < 9.5.51
    • (no CPE)range: >= 9.0.0, < 9.5.51

Patches

2
b9a8bcb614ec

[SECURITY] Require step-up authentication for password change

https://github.com/TYPO3-CMS/coreBenjamin FranzkeMay 20, 2025via ghsa
7 files changed · +147 1
  • Configuration/TCA/be_groups.php+42 0 modified
    @@ -43,6 +43,9 @@
                     'size' => 3,
                     'autoSizeMax' => 10,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'file_mountpoints' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:file_mountpoints',
    @@ -75,6 +78,9 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'file_permissions' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.fileoper_perms',
    @@ -105,6 +111,9 @@
                     'maxitems' => 17,
                     'default' => 'readFolder,writeFolder,addFolder,renameFolder,moveFolder,deleteFolder,readFile,writeFile,addFile,renameFile,replaceFile,moveFile,copyFile,deleteFile',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'workspace_perms' => [
                 'displayCond' => 'USER:TYPO3\CMS\Core\Hooks\TcaDisplayConditions->isExtensionInstalled:workspaces',
    @@ -118,6 +127,9 @@
                         ['label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:workspace_perms_live'],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'pagetypes_select' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.pagetypes_select',
    @@ -128,6 +140,9 @@
                     'size' => 5,
                     'autoSizeMax' => 50,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'tables_modify' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.tables_modify',
    @@ -138,12 +153,18 @@
                     'selectFieldName' => 'tables_select',
                     'itemsProcFunc' => \TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions::class . '->populateAvailableTables',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'tables_select' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.tables_select',
                 'config' => [
                     'type' => 'passthrough',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'non_exclude_fields' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.non_exclude_fields',
    @@ -155,6 +176,9 @@
                     'size' => 25,
                     'autoSizeMax' => 50,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'explicit_allowdeny' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.explicit_allowdeny',
    @@ -163,6 +187,9 @@
                     'renderType' => 'selectCheckBox',
                     'itemsProcFunc' => \TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions::class . '->populateExplicitAuthValues',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'allowed_languages' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:allowed_languages',
    @@ -173,6 +200,9 @@
                     'itemsProcFunc' => \TYPO3\CMS\Core\Localization\TcaSystemLanguageCollector::class . '->populateAvailableSiteLanguages',
                     'dbFieldLength' => 255,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'custom_options' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_groups.custom_options',
    @@ -191,6 +221,9 @@
                     'size' => 5,
                     'autoSizeMax' => 50,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'mfa_providers' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:mfa_providers',
    @@ -201,6 +234,9 @@
                     'size' => 5,
                     'autoSizeMax' => 50,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'TSconfig' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig',
    @@ -222,6 +258,9 @@
                     'size' => 5,
                     'autoSizeMax' => 50,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'category_perms' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:category_perms',
    @@ -235,6 +274,9 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
         ],
         'types' => [
    
  • Configuration/TCA/be_users.php+40 0 modified
    @@ -39,6 +39,9 @@
                     'eval' => 'nospace,trim,lower,unique',
                     'autocomplete' => false,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'password' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.password',
    @@ -48,6 +51,10 @@
                     'size' => 20,
                     'required' => true,
                 ],
    +            'authenticationContext' => [
    +                //'group' => 'be.userManagement',
    +                'once' => true,
    +            ],
             ],
             'mfa' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.mfa',
    @@ -56,6 +63,9 @@
                     'type' => 'none',
                     'renderType' => 'mfaInfo',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'usergroup' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.usergroup',
    @@ -87,6 +97,9 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'avatar' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.avatar',
    @@ -106,6 +119,9 @@
                     'maxitems' => 100,
                     'autoSizeMax' => 10,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'file_mountpoints' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.options_file_mounts',
    @@ -139,13 +155,19 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'email' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.email',
                 'config' => [
                     'type' => 'email',
                     'size' => 20,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'realName' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.name',
    @@ -168,6 +190,9 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'options' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.options',
    @@ -209,6 +234,9 @@
                     'maxitems' => 17,
                     'default' => 'readFolder,writeFolder,addFolder,renameFolder,moveFolder,deleteFolder,readFile,writeFile,addFile,renameFile,replaceFile,moveFile,copyFile,deleteFile',
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'workspace_perms' => [
                 'displayCond' => 'USER:TYPO3\CMS\Core\Hooks\TcaDisplayConditions->isExtensionInstalled:workspaces',
    @@ -222,6 +250,9 @@
                         ['label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:workspace_perms_live'],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'lang' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.lang',
    @@ -248,6 +279,9 @@
                     'autoSizeMax' => 50,
                     'maxitems' => 100,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'allowed_languages' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:allowed_languages',
    @@ -258,6 +292,9 @@
                     'itemsProcFunc' => \TYPO3\CMS\Core\Localization\TcaSystemLanguageCollector::class . '->populateAvailableSiteLanguages',
                     'dbFieldLength' => 255,
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
             'TSconfig' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:TSconfig',
    @@ -289,6 +326,9 @@
                         ],
                     ],
                 ],
    +            'authenticationContext' => [
    +                'group' => 'be.userManagement',
    +            ],
             ],
         ],
         'types' => [
    
  • Configuration/TCA/Overrides/be_groups.php+5 0 added
    @@ -0,0 +1,5 @@
    +<?php
    +
    +defined('TYPO3') or die();
    +
    +$GLOBALS['TCA']['be_groups']['columns']['hidden']['authenticationContext']['group'] = 'be.userManagement';
    
  • Configuration/TCA/Overrides/be_users.php+4 0 modified
    @@ -5,3 +5,7 @@
     // New be_users are disabled by default and can not disable themselves
     $GLOBALS['TCA']['be_users']['columns']['disable']['displayCond'] = 'USER:' . \TYPO3\CMS\Core\Hooks\TcaDisplayConditions::class . '->isRecordCurrentUser:false';
     $GLOBALS['TCA']['be_users']['columns']['disable']['config']['default'] = 1;
    +
    +$GLOBALS['TCA']['be_users']['columns']['disable']['authenticationContext']['group'] = 'be.userManagement';
    +$GLOBALS['TCA']['be_users']['columns']['starttime']['authenticationContext']['group'] = 'be.userManagement';
    +$GLOBALS['TCA']['be_users']['columns']['endtime']['authenticationContext']['group'] = 'be.userManagement';
    
  • Resources/Public/JavaScript/ajax/ajax-request.js+1 1 modified
    @@ -10,4 +10,4 @@
      *
      * The TYPO3 project - inspiring people to share!
      */
    -import{AjaxResponse as s}from"@typo3/core/ajax/ajax-response.js";import{InputTransformer as r}from"@typo3/core/ajax/input-transformer.js";class c{static{this.defaultOptions={credentials:"same-origin"}}constructor(e){this.url=e instanceof URL?e:new URL(e,window.location.origin+window.location.pathname),this.abortController=new AbortController}withQueryArguments(e){const t=this.clone();e instanceof URLSearchParams||(e=new URLSearchParams(r.toSearchParams(e)));for(const[o,n]of e.entries())this.url.searchParams.append(o,n);return t}async get(e={}){const t={method:"GET"},o=await this.send({...t,...e});return new s(o)}async post(e,t={}){const o={body:typeof e=="string"||e instanceof FormData?e:Object.keys(e).length?r.byHeader(e,t?.headers):"",cache:"no-cache",method:"POST"},n=await this.send({...o,...t});return new s(n)}async put(e,t={}){const o={body:typeof e=="string"||e instanceof FormData?e:r.byHeader(e,t?.headers),cache:"no-cache",method:"PUT"},n=await this.send({...o,...t});return new s(n)}async delete(e={},t={}){const o={cache:"no-cache",method:"DELETE"};typeof e=="string"&&e.length>0||e instanceof FormData?o.body=e:typeof e=="object"&&Object.keys(e).length>0&&(o.body=r.byHeader(e,t?.headers));const n=await this.send({...o,...t});return new s(n)}abort(){this.abortController.abort()}clone(){return Object.assign(Object.create(this),this)}async send(e={}){const t=await fetch(this.url,this.getMergedOptions(e));if(!t.ok)throw new s(t);return t}getMergedOptions(e){const{signal:t,...o}=e;return t?.addEventListener("abort",()=>this.abortController.abort()),{...c.defaultOptions,...o,signal:this.abortController.signal}}}export{c as default};
    +import{AjaxResponse as o}from"@typo3/core/ajax/ajax-response.js";import{InputTransformer as r}from"@typo3/core/ajax/input-transformer.js";class i{static{this.defaultOptions={credentials:"same-origin"}}constructor(e){this.url=e instanceof URL?e:new URL(e,window.location.origin+window.location.pathname),this.abortController=new AbortController,this.fetch=t=>fetch(t)}withQueryArguments(e){const t=this.clone();e instanceof URLSearchParams||(e=new URLSearchParams(r.toSearchParams(e)));for(const[s,n]of e.entries())this.url.searchParams.append(s,n);return t}async get(e={}){const t={method:"GET"},s=await this.send({...t,...e});return new o(s)}async post(e,t={}){const s={body:typeof e=="string"||e instanceof FormData?e:Object.keys(e).length?r.byHeader(e,t?.headers):"",cache:"no-cache",method:"POST"},n=await this.send({...s,...t});return new o(n)}async put(e,t={}){const s={body:typeof e=="string"||e instanceof FormData?e:r.byHeader(e,t?.headers),cache:"no-cache",method:"PUT"},n=await this.send({...s,...t});return new o(n)}async delete(e={},t={}){const s={cache:"no-cache",method:"DELETE"};typeof e=="string"&&e.length>0||e instanceof FormData?s.body=e:typeof e=="object"&&Object.keys(e).length>0&&(s.body=r.byHeader(e,t?.headers));const n=await this.send({...s,...t});return new o(n)}abort(){this.abortController.abort()}addMiddleware(e){if(Array.isArray(e))return e.forEach(s=>this.addMiddleware(s)),this;const t=this.fetch;return this.fetch=s=>e(s,t),this}clone(){return Object.assign(Object.create(this),this)}async send(e={}){const t=await this.fetch(new Request(this.url,this.getMergedOptions(e)));if(!t.ok)throw new o(t);return t}getMergedOptions(e){const{signal:t,...s}=e;return t?.addEventListener("abort",()=>this.abortController.abort()),{...i.defaultOptions,...s,signal:this.abortController.signal}}}export{i as default};
    
  • Tests/Acceptance/Application/Impexp/UsersCest.php+41 0 modified
    @@ -17,6 +17,7 @@
     
     namespace TYPO3\CMS\Core\Tests\Acceptance\Application\Impexp;
     
    +use Codeception\Exception\MalformedLocatorException;
     use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester;
     use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree;
     
    @@ -194,6 +195,20 @@ private function setPageAccess(ApplicationTester $I, PageTree $pageTree, array $
             $recursionLevelOption = $I->grabTextFrom('//select[@id="recursionLevel"]/option[' . $recursionLevel . ']');
             $I->selectOption('//select[@id="recursionLevel"]', ['value' => $recursionLevelOption]);
             $I->click($this->inModuleHeader . ' .btn[title="Save and close"]');
    +        $I->wait(0.5);
    +        $I->switchToMainFrame();
    +        try {
    +            $needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
    +        } catch (MalformedLocatorException) {
    +            $needsStepUp = false;
    +        }
    +        if ($needsStepUp) {
    +            $I->see('Verify with user password');
    +            $I->fillField('//input[@name="password"]', 'password');
    +            $I->click('//button[@name="verify"]');
    +        }
    +        $I->switchToContentFrame();
    +        $I->wait(0.5);
         }
     
         private function setModAccess(ApplicationTester $I, int $userGroupId, array $modAccessByName): void
    @@ -219,6 +234,19 @@ private function setModAccess(ApplicationTester $I, int $userGroupId, array $mod
     
             $I->click($this->inModuleHeader . ' .btn[title="Save"]');
             $I->wait(0.5);
    +        $I->switchToMainFrame();
    +        try {
    +            $needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
    +        } catch (MalformedLocatorException) {
    +            $needsStepUp = false;
    +        }
    +        if ($needsStepUp) {
    +            $I->see('Verify with user password');
    +            $I->fillField('//input[@name="password"]', 'password');
    +            $I->click('//button[@name="verify"]');
    +        }
    +        $I->switchToContentFrame();
    +        $I->wait(0.5);
             $I->click($this->inModuleHeader . ' .btn[title="Close"]');
             $I->waitForText('Backend user groups');
         }
    @@ -245,6 +273,19 @@ private function setUserTsConfig(ApplicationTester $I, int $userId, string $user
             $I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('" . $userTsConfig . "')");
             $I->click($this->inModuleHeader . ' .btn[title="Save"]');
             $I->wait(0.5);
    +        $I->switchToMainFrame();
    +        try {
    +            $needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
    +        } catch (MalformedLocatorException) {
    +            $needsStepUp = false;
    +        }
    +        if ($needsStepUp) {
    +            $I->see('Verify with user password');
    +            $I->fillField('//input[@name="password"]', 'password');
    +            $I->click('//button[@name="verify"]');
    +        }
    +        $I->switchToContentFrame();
    +        $I->wait(0.5);
             $I->click($this->inModuleHeader . ' .btn[title="Close"]');
             $I->waitForElement('#typo3-backend-user-list');
         }
    
  • Tests/Acceptance/Application/RecordList/RecordDownloadWithPresetCest.php+14 0 modified
    @@ -17,6 +17,7 @@
     
     namespace TYPO3\CMS\Core\Tests\Acceptance\Application\RecordList;
     
    +use Codeception\Exception\MalformedLocatorException;
     use TYPO3\CMS\Core\Tests\Acceptance\Support\ApplicationTester;
     use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\ModalDialog;
     use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree;
    @@ -102,6 +103,19 @@ private function setUserTsConfig(ApplicationTester $I, int $userId, string $user
             $I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('" . $userTsConfig . "')");
             $I->click($this->inModuleHeader . ' .btn[title="Save"]');
             $I->wait(0.5);
    +        $I->switchToMainFrame();
    +        try {
    +            $needsStepUp = count($I->grabMultiple('.modal-sudo-mode-verification')) > 0;
    +        } catch (MalformedLocatorException) {
    +            $needsStepUp = false;
    +        }
    +        if ($needsStepUp) {
    +            $I->see('Verify with user password');
    +            $I->fillField('//input[@name="password"]', 'password');
    +            $I->click('//button[@name="verify"]');
    +        }
    +        $I->switchToContentFrame();
    +        $I->wait(0.5);
             $I->click($this->inModuleHeader . ' .btn[title="Close"]');
             $I->waitForElement('#typo3-backend-user-list');
         }
    
60572dd050d8

[SECURITY] Require step-up authentication for password change

https://github.com/TYPO3-CMS/setupBenjamin FranzkeMay 20, 2025via ghsa
3 files changed · +4 44
  • Classes/Controller/SetupModuleController.php+3 35 modified
    @@ -30,8 +30,6 @@
     use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
     use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry;
     use TYPO3\CMS\Core\Core\Environment;
    -use TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException;
    -use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
     use TYPO3\CMS\Core\Database\Connection;
     use TYPO3\CMS\Core\Database\ConnectionPool;
     use TYPO3\CMS\Core\DataHandling\DataHandler;
    @@ -177,7 +175,6 @@ protected function initialize(ServerRequestInterface $request): ModuleTemplate
             // if password is disabled, disable repeat of password too (password2)
             if ($this->tsFieldConf['password.']['disabled'] ?? false) {
                 $this->tsFieldConf['password2.']['disabled'] = 1;
    -            $this->tsFieldConf['passwordCurrent.']['disabled'] = 1;
             }
             return $view;
         }
    @@ -242,7 +239,7 @@ protected function storeIncomingData(ServerRequestInterface $request): void
                         if (!in_array($field, $fieldList, true)) {
                             continue;
                         }
    -                    if (($config['table']  ?? '') === 'be_users' && !in_array($field, ['password', 'password2', 'passwordCurrent', 'email', 'realName', 'admin', 'avatar'], true)) {
    +                    if (($config['table']  ?? '') === 'be_users' && !in_array($field, ['password', 'password2', 'email', 'realName', 'admin', 'avatar'], true)) {
                             if (!isset($config['access']) || $this->checkAccess($config) && ($backendUser->user[$field] !== $d['be_users'][$field])) {
                                 if (($config['type'] ?? false) === 'check') {
                                     $fieldValue = isset($d['be_users'][$field]) ? 1 : 0;
    @@ -304,26 +301,8 @@ protected function storeIncomingData(ServerRequestInterface $request): void
                     }
                     // Update the password:
                     if ($passwordIsConfirmed && $passwordValid) {
    -                    if ($backendUser->isAdmin()) {
    -                        $passwordOk = true;
    -                    } else {
    -                        $currentPasswordHashed = $backendUser->user['password'];
    -                        $passwordOk = false;
    -                        $saltFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
    -                        try {
    -                            $hashInstance = $saltFactory->get($currentPasswordHashed, 'BE');
    -                            $passwordOk = $hashInstance->checkPassword($be_user_data['passwordCurrent'], $currentPasswordHashed);
    -                        } catch (InvalidPasswordHashException $e) {
    -                            // Could not find hash class responsible for existing password. This is a
    -                            // misconfiguration and user can not change its password.
    -                        }
    -                    }
    -                    if ($passwordOk) {
    -                        $this->passwordIsUpdated = self::PASSWORD_UPDATED;
    -                        $storeRec['be_users'][$beUserId]['password'] = $be_user_data['password'];
    -                    } else {
    -                        $this->passwordIsUpdated = self::PASSWORD_OLD_WRONG;
    -                    }
    +                    $this->passwordIsUpdated = self::PASSWORD_UPDATED;
    +                    $storeRec['be_users'][$beUserId]['password'] = $be_user_data['password'];
                     } elseif ($passwordIsConfirmed) {
                         $this->passwordIsUpdated = self::PASSWORD_POLICY_FAILED;
                     } else {
    @@ -806,14 +785,6 @@ protected function getLabel($str, $key = '', $addLabelTag = true)
         protected function getFieldsFromShowItem()
         {
             $allowedFields = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_USER_SETTINGS']['showitem'], true);
    -        if ($this->getBackendUser()->isAdmin()) {
    -            // Do not ask for current password if admin (unknown for other users and no security gain)
    -            $key = array_search('passwordCurrent', $allowedFields);
    -            if ($key !== false) {
    -                unset($allowedFields[$key]);
    -            }
    -        }
    -
             $backendUser = $this->getBackendUser();
             if ($backendUser->getOriginalUserIdWhenInSwitchUserMode() && $backendUser->isSystemMaintainer(true)) {
                 // DataHandler denies changing the password of system maintainer users in switch user mode.
    @@ -957,9 +928,6 @@ protected function addFlashMessages(ModuleTemplate $view): void
             }
             if ($this->passwordIsSubmitted) {
                 switch ($this->passwordIsUpdated) {
    -                case self::PASSWORD_OLD_WRONG:
    -                    $view->addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:oldPassword_failed'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'), ContextualFeedbackSeverity::ERROR);
    -                    break;
                     case self::PASSWORD_NOT_THE_SAME:
                         $view->addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword_failed'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'), ContextualFeedbackSeverity::ERROR);
                         break;
    
  • ext_tables.php+1 6 modified
    @@ -35,11 +35,6 @@
                 'label' => 'LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPasswordAgain',
                 'table' => 'be_users',
             ],
    -        'passwordCurrent' => [
    -            'type' => 'password',
    -            'label' => 'LLL:EXT:setup/Resources/Private/Language/locallang.xlf:passwordCurrent',
    -            'table' => 'be_users',
    -        ],
             'avatar' => [
                 'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:be_users.avatar',
                 'type' => 'avatar',
    @@ -110,7 +105,7 @@
             ],
         ],
         'showitem' => '--div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:personal_data,realName,email,emailMeAtLogin,avatar,lang,
    -            --div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:accountSecurity,passwordCurrent,password,password2,mfaProviders,
    +            --div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:accountSecurity,password,password2,mfaProviders,
                 --div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:opening,colorScheme,theme,startModule,backendTitleFormat,
                 --div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:editFunctionsTab,titleLen,edit_docModuleUpload,showHiddenFilesAndFolders,copyLevels,
                 --div--;LLL:EXT:setup/Resources/Private/Language/locallang.xlf:resetTab,resetConfiguration',
    
  • Resources/Private/Language/locallang.xlf+0 3 modified
    @@ -93,9 +93,6 @@
     			<trans-unit id="newPassword_ok">
     				<source>Password was updated.</source>
     			</trans-unit>
    -			<trans-unit id="passwordCurrent">
    -				<source>Current password</source>
    -			</trans-unit>
     			<trans-unit id="passwordPolicyFailed">
     				<source>The password was NOT updated, since it does not meet the password policy requirements.</source>
     			</trans-unit>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.