Page MenuHomePhabricator

`Sealed secret has been tampered with` causes `missing returntourl` fatal error.
Closed, ResolvedPublicBUG REPORT

Description

On an internal wiki of ours, every now and then we have a weird authentication failure, such as in this image:

image.png (164×544 px, 30 KB)

We did some digging, and found this in the logs:

[session] Sealed secret has been tampered with, aborting.
#0 /var/www/html/includes/auth/AuthManager.php(2276): MediaWiki\Session\Session->getSecret(string)
#1 /var/www/html/extensions/PluggableAuth/includes/PluggableAuthLogin.php(113): MediaWiki\Auth\AuthManager->setAuthenticationSessionData(string, string)
#2 /var/www/html/includes/specialpage/SpecialPage.php(600): MediaWiki\Extension\PluggableAuth\PluggableAuthLogin->execute(NULL)
#3 /var/www/html/includes/specialpage/SpecialPageFactory.php(635): SpecialPage->run(NULL)
#4 /var/www/html/includes/MediaWiki.php(307): MediaWiki\SpecialPage\SpecialPageFactory->executePath(Title, RequestContext)
#5 /var/www/html/includes/MediaWiki.php(947): MediaWiki->performRequest()
#6 /var/www/html/includes/MediaWiki.php(547): MediaWiki->main()
#7 /var/www/html/index.php(53): MediaWiki->run()
#8 /var/www/html/index.php(46): wfIndexMain()
#9 {main}
[...A lot of messages about saving sessions to objectcache...]
[PluggableAuth] ERROR: return to URL is null or empty

Steps to replicate the issue (include links if applicable):

  • Use a pluggableAuth workflow to sign up (We use WSOAuth )
  • Find a way to create the issue Sealed secret has been tampered with, aborting. during execution of $this->authManager->setAuthenticationSessionData( self::USERNAME_SESSION_KEY, $username ); in PluggableAuthLogin.php.

What happens?:
You get an error as described above

What should have happened instead?:
Authentication was successful, so you should not get an error.

Software version (skip for WMF-hosted wikis like Wikipedia):
Mediawiki 1.35

I could fix this issue as follows:

diff
diff --git a/includes/PluggableAuthLogin.php b/includes/PluggableAuthLogin.php
index 21ec13c..033f13a 100644
--- a/includes/PluggableAuthLogin.php
+++ b/includes/PluggableAuthLogin.php
@@ -79,7 +79,7 @@ class PluggableAuthLogin extends UnlistedSpecialPage {
                        $authManager->setAuthenticationSessionData( self::ERROR_SESSION_KEY,
                                $error );
                }
-               $returnToUrl = $authManager->getAuthenticationSessionData(
+               $returnToUrl = $authManager->getRequest()->getSession()->getSecret(
                        self::RETURNTOURL_SESSION_KEY );
                if ( $returnToUrl === null || strlen( $returnToUrl ) === 0 ) {
                        wfDebugLog( 'PluggableAuth', 'ERROR: return to URL is null or empty' );
diff --git a/includes/PluggableAuthPrimaryAuthenticationProvider.php b/includes/PluggableAuthPrimaryAuthenticationProvider.php
index 4fcccd7..55b35be 100644
--- a/includes/PluggableAuthPrimaryAuthenticationProvider.php
+++ b/includes/PluggableAuthPrimaryAuthenticationProvider.php
@@ -25,7 +25,7 @@ class PluggableAuthPrimaryAuthenticationProvider extends AbstractPrimaryAuthenti
                        }
                }
                $url = SpecialPage::getTitleFor( 'PluggableAuthLogin' )->getFullURL();
-               $this->manager->setAuthenticationSessionData(
+               $this->manager->getRequest()->getSession()->setSecret(
                        PluggableAuthLogin::RETURNTOURL_SESSION_KEY, $request->returnToUrl );
                $this->manager->setAuthenticationSessionData(
                        PluggableAuthLogin::EXTRALOGINFIELDS_SESSION_KEY, $extraLoginFields );

but I do not know if you want this to be done this way.

Any ideas on why Sealed secret has been tampered with is occurring are more than welcome!

Event Timeline

It means an encrypted value stored in the session couldn't be successfully decrypted (or more precisely, its checksum doesn't validate).
Session data is often stored in some relatively unsafe location (such as unauthenticated memcache) so things like the user's password are encrypted when stored in the session for the duration of the login process.

I assume PluggableAuth is not tampering with that data, so I can't really imagine how this would happen. Or why it would be fixed by that change. Some kinda session reset, that results in the loss of the encryption key (a piece of which is also stored in the session)? But then all session data should be lost, and getAuthenticationSessionData should just return null...

@Tgr Thank you for your reply!

I can give some more context on why this problem occurs and how my change "fixes" this:

Session data is often stored in some relatively unsafe location (such as unauthenticated memcache) so things like the user's password are encrypted when stored in the session for the duration of the login process.

Ah okay this makes sense.

I assume PluggableAuth is not tampering with that data, so I can't really imagine how this would happen.

I am equally surprised. This does however only happen occasionally, but so often that our wiki users are complaining. We use DB_CACHE for our sessions, so I suspect something is actually going wrong within some MediaWiki code (or its extensions), not some outer influence.

Or why it would be fixed by that change.

This change does not "fix" the problem with session corruption, but it does work around it: When your session has been corrupted, all authData in the session is removed (See this code), including PluggableAuthLoginReturnToUrl. Even when authentication was successful according to $pluggableauth->authenticate() and the PluggableAuthUserAuthorization-Hook. This also means the user is logged in (As far as I can tell from the code), and data such as username/realname are stored to the session.
However, the user does get an error because the return url is missing, and is presented with a login screen again.

This "fix" makes sure that when the secret is wiped by the session->setAuthenticationSessionData() code, the returntourl is not wiped too, and a logged in user is not redirected to a login screen. It makes our customers happy because they don't get error messages, but I am not sure if this is the correct thing to do.

I hope this makes sense, I don't understand everything about these sessions.

But then all session data should be lost, and getAuthenticationSessionData should just return null...

Indeed, which is why the returntourl is wiped. My patch uses other session storage for this reason, so returntourl is not wiped.

Change 926667 had a related patch set uploaded (by Cicalese; author: Cicalese):

[mediawiki/extensions/PluggableAuth@master] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926667

Change 926667 merged by jenkins-bot:

[mediawiki/extensions/PluggableAuth@master] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926667

cicalese claimed this task.
cicalese subscribed.

This should now be fixed in the upcoming 7.0 release of PluggableAuth. Thank you for reporting it and for the fix to retain the URL. The issue causing the root error is unclear, but the return to URL will no longer be lost.

Change 926765 had a related patch set uploaded (by Cicalese; author: Cicalese):

[mediawiki/extensions/PluggableAuth@REL1_39] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926765

Change 926766 had a related patch set uploaded (by Cicalese; author: Cicalese):

[mediawiki/extensions/PluggableAuth@REL1_40] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926766

Change 926765 merged by jenkins-bot:

[mediawiki/extensions/PluggableAuth@REL1_39] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926765

Change 926766 merged by jenkins-bot:

[mediawiki/extensions/PluggableAuth@REL1_40] Don't store return to URL as an auth/session secret

https://gerrit.wikimedia.org/r/926766