jenkins-bot has submitted this change and it was merged. Change subject: API: Insist authn parameters be in the POST body ......................................................................
API: Insist authn parameters be in the POST body Passwords should always be submitted in the POST body, not in the query string. Thus, a warning will now be returned if the password for action=login or any sensitive authentication request parameters for AuthManager actions are found in the query string. These warnings should be upgraded to errors in 1.29. Change-Id: Ifb2c684bb28c9acc004be2b0c2fef839eb7624aa --- M RELEASE-NOTES-1.28 M includes/api/ApiAuthManagerHelper.php M includes/api/ApiBase.php M includes/api/ApiLogin.php M includes/api/ApiMain.php 5 files changed, 66 insertions(+), 14 deletions(-) Approvals: Gergő Tisza: Looks good to me, approved jenkins-bot: Verified diff --git a/RELEASE-NOTES-1.28 b/RELEASE-NOTES-1.28 index f6c3530..eac4e2c 100644 --- a/RELEASE-NOTES-1.28 +++ b/RELEASE-NOTES-1.28 @@ -61,6 +61,13 @@ * The following response properties from action=login, deprecated in 1.27, are now removed: lgtoken, cookieprefix, sessionid. Clients should handle cookies to properly manage session state. +* Submitting the lgtoken and lgpassword parameters in the query string to + action=login is now deprecated and outputs a warning. They should be submitted + in the POST body instead. +* Submitting sensitive authentication request parameters to action=clientlogin, + action=createaccount, action=linkaccount, and action=changeauthenticationdata + in the query string is now deprecated and outputs a warning. They should be + submitted in the POST body instead. === Action API internal changes in 1.28 === * Added a new hook, 'ApiMakeParserOptions', to allow extensions to better diff --git a/includes/api/ApiAuthManagerHelper.php b/includes/api/ApiAuthManagerHelper.php index d330862..a4f54ee 100644 --- a/includes/api/ApiAuthManagerHelper.php +++ b/includes/api/ApiAuthManagerHelper.php @@ -157,8 +157,13 @@ // Collect the fields for all the requests $fields = []; + $sensitive = []; foreach ( $reqs as $req ) { - $fields += (array)$req->getFieldInfo(); + $info = (array)$req->getFieldInfo(); + $fields += $info; + $sensitive += array_filter( $info, function ( $opts ) { + return !empty( $opts['sensitive'] ); + } ); } // Extract the request data for the fields and mark those request @@ -166,6 +171,16 @@ $data = array_intersect_key( $this->module->getRequest()->getValues(), $fields ); $this->module->getMain()->markParamsUsed( array_keys( $data ) ); + if ( $sensitive ) { + try { + $this->module->requirePostedParameters( array_keys( $sensitive ), 'noprefix' ); + } catch ( UsageException $ex ) { + // Make this a warning for now, upgrade to an error in 1.29. + $this->module->setWarning( $ex->getMessage() ); + $this->module->logFeatureUsage( $this->module->getModuleName() . '-params-in-query-string' ); + } + } + return AuthenticationRequest::loadRequestsFromSubmission( $reqs, $data ); } diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 4a1a520..fcb748c 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -777,6 +777,39 @@ } /** + * Die if any of the specified parameters were found in the query part of + * the URL rather than the post body. + * @since 1.28 + * @param string[] $params Parameters to check + * @param string $prefix Set to 'noprefix' to skip calling $this->encodeParamName() + */ + public function requirePostedParameters( $params, $prefix = 'prefix' ) { + // Skip if $wgDebugAPI is set or we're in internal mode + if ( $this->getConfig()->get( 'DebugAPI' ) || $this->getMain()->isInternalMode() ) { + return; + } + + $queryValues = $this->getRequest()->getQueryValues(); + $badParams = []; + foreach ( $params as $param ) { + if ( $prefix !== 'noprefix' ) { + $param = $this->encodeParamName( $param ); + } + if ( array_key_exists( $param, $queryValues ) ) { + $badParams[] = $param; + } + } + + if ( $badParams ) { + $this->dieUsage( + 'The following parameters were found in the query string, but must be in the POST body: ' + . join( ', ', $badParams ), + 'mustpostparams' + ); + } + } + + /** * Callback function used in requireOnlyOneParameter to check whether required parameters are set * * @param object $x Parameter to check is not null/false @@ -2197,7 +2230,7 @@ * analysis. * @param string $feature Feature being used. */ - protected function logFeatureUsage( $feature ) { + public function logFeatureUsage( $feature ) { $request = $this->getRequest(); $s = '"' . addslashes( $feature ) . '"' . ' "' . wfUrlencode( str_replace( ' ', '_', $this->getUser()->getName() ) ) . '"' . diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index 28937f7..9bc0b3a 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -70,6 +70,14 @@ return; } + try { + $this->requirePostedParameters( [ 'password', 'token' ] ); + } catch ( UsageException $ex ) { + // Make this a warning for now, upgrade to an error in 1.29. + $this->setWarning( $ex->getMessage() ); + $this->logFeatureUsage( 'login-params-in-query-string' ); + } + $params = $this->extractRequestParams(); $result = []; diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 565e829..22b079d 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -1103,18 +1103,7 @@ $this->dieUsageMsg( [ 'missingparam', 'token' ] ); } - if ( !$this->getConfig()->get( 'DebugAPI' ) && - array_key_exists( - $module->encodeParamName( 'token' ), - $this->getRequest()->getQueryValues() - ) - ) { - $this->dieUsage( - "The '{$module->encodeParamName( 'token' )}' parameter was " . - 'found in the query string, but must be in the POST body', - 'mustposttoken' - ); - } + $module->requirePostedParameters( [ 'token' ] ); if ( !$module->validateToken( $moduleParams['token'], $moduleParams ) ) { $this->dieUsageMsg( 'sessionfailure' ); -- To view, visit https://gerrit.wikimedia.org/r/305545 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ifb2c684bb28c9acc004be2b0c2fef839eb7624aa Gerrit-PatchSet: 2 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Anomie <bjor...@wikimedia.org> Gerrit-Reviewer: Gergő Tisza <gti...@wikimedia.org> Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits