Page MenuHomePhabricator

PHP error "hash_equals(): Expected known_string to be a string, null given" from OAuth ClientEntity.php
Closed, ResolvedPublicPRODUCTION ERROR

Description

Error message
PHP Warning: hash_equals(): Expected known_string to be a string, null given
Stack Trace
#1 /srv/mediawiki/php-1.35.0-wmf.39/extensions/OAuth/src/Entity/ClientEntity.php(111): hash_equals(NULL, string)
#2 /srv/mediawiki/php-1.35.0-wmf.39/extensions/OAuth/src/Entity/ClientEntity.php(92): MediaWiki\Extensions\OAuth\Entity\ClientEntity->isSecretValid(NULL)
#3 /srv/mediawiki/php-1.35.0-wmf.39/extensions/OAuth/src/Repository/ClientRepository.php(62): MediaWiki\Extensions\OAuth\Entity\ClientEntity->validate(NULL, string)
#4 /srv/mediawiki/php-1.35.0-wmf.39/vendor/league/oauth2-server/src/Grant/AbstractGrant.php(182): MediaWiki\Extensions\OAuth\Repository\ClientRepository->validateClient(string, NULL, string)
#5 /srv/mediawiki/php-1.35.0-wmf.39/vendor/league/oauth2-server/src/Grant/AuthCodeGrant.php(104): League\OAuth2\Server\Grant\AbstractGrant->validateClient(GuzzleHttp\Psr7\ServerRequest)
#6 /srv/mediawiki/php-1.35.0-wmf.39/vendor/league/oauth2-server/src/AuthorizationServer.php(198): League\OAuth2\Server\Grant\AuthCodeGrant->respondToAccessTokenRequest(GuzzleHttp\Psr7\ServerRequest, League\OAuth2\Server\ResponseTypes\BearerTokenResponse, DateInterval)
#7 /srv/mediawiki/php-1.35.0-wmf.39/extensions/OAuth/src/AuthorizationProvider/AccessToken.php(22): League\OAuth2\Server\AuthorizationServer->respondToAccessTokenRequest(GuzzleHttp\Psr7\ServerRequest, MediaWiki\Extensions\OAuth\Response)
#8 /srv/mediawiki/php-1.35.0-wmf.39/extensions/OAuth/src/Rest/Handler/AccessToken.php(40): MediaWiki\Extensions\OAuth\AuthorizationProvider\AccessToken->getAccessTokens(GuzzleHttp\Psr7\ServerRequest, MediaWiki\Extensions\OAuth\Response)
#9 /srv/mediawiki/php-1.35.0-wmf.39/includes/Rest/Router.php(362): MediaWiki\Extensions\OAuth\Rest\Handler\AccessToken->execute()
#10 /srv/mediawiki/php-1.35.0-wmf.39/includes/Rest/Router.php(317): MediaWiki\Rest\Router->executeHandler(MediaWiki\Extensions\OAuth\Rest\Handler\AccessToken)
#11 /srv/mediawiki/php-1.35.0-wmf.39/includes/Rest/EntryPoint.php(139): MediaWiki\Rest\Router->execute(MediaWiki\Rest\RequestFromGlobals)
#12 /srv/mediawiki/php-1.35.0-wmf.39/includes/Rest/EntryPoint.php(106): MediaWiki\Rest\EntryPoint->execute()
#13 /srv/mediawiki/php-1.35.0-wmf.39/rest.php(31): MediaWiki\Rest\EntryPoint::main()
Impact

TDB/Unknown.

Notes

Seen mainly on wikidata.org, and commons.wikimedia.org. Affects multiple app servers and PHP updates so not likely to be a fluke, but rather a bug in the code.

Details

Request ID
4cc9cc10-6ef7-4591-a839-5d4dc324a05b
Request URL
/w/rest.php/oauth2/access_token

Event Timeline

ClientEntity::validate explicitly allows $secret to be null:
https://gerrit.wikimedia.org/g/mediawiki/extensions/OAuth/+/8067500eca681907e368ba6e33798a18a030fbda/src/Entity/ClientEntity.php#87

However, it is not checked before being passed to hash_equals in the isSecretValidCall:
https://gerrit.wikimedia.org/g/mediawiki/extensions/OAuth/+/8067500eca681907e368ba6e33798a18a030fbda/src/Entity/ClientEntity.php#111

If we assume that whomever listed null|string as valid types for $secret had good reason to do so, then the simple solution is to check $secret before passing it to hash_equals.

Change 623462 had a related patch set uploaded (by BPirkle; owner: BPirkle):
[mediawiki/extensions/OAuth@master] Confirm $secret is a string before passing it to hash_equals

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

Change 623462 merged by jenkins-bot:
[mediawiki/extensions/OAuth@master] Confirm $secret is a string before passing it to hash_equals

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