aboutsummaryrefslogtreecommitdiffstats
path: root/includes
diff options
context:
space:
mode:
authorsbassett <sbassett@wikimedia.org>2019-04-16 17:09:43 -0500
committerSBassett <sbassett@wikimedia.org>2019-04-24 15:38:40 +0000
commitd965b0b4652b566b1f53be756c13190b958dd7fa (patch)
treede99e7b22a38d0739ad3686a77b4b4d1de4f2f83 /includes
parentb6e3d8df08516906287015c6d826f36d47d85fe2 (diff)
downloadmediawikicore-d965b0b4652b566b1f53be756c13190b958dd7fa.tar.gz
mediawikicore-d965b0b4652b566b1f53be756c13190b958dd7fa.zip
[SECURITY] [API BREAKING CHANGE] Require logout token.
Special:Userlogout now requires a token Api action=logout requires a csrf token and the request to be POSTed Patch author: bawolff Bug: T25227 Change-Id: Icb674095956bb3f6c847c9553c53e404402ea774
Diffstat (limited to 'includes')
-rw-r--r--includes/api/ApiLogout.php10
-rw-r--r--includes/skins/SkinTemplate.php15
-rw-r--r--includes/specials/SpecialUserLogout.php22
3 files changed, 40 insertions, 7 deletions
diff --git a/includes/api/ApiLogout.php b/includes/api/ApiLogout.php
index c663d1e4bb23..39a96ac56308 100644
--- a/includes/api/ApiLogout.php
+++ b/includes/api/ApiLogout.php
@@ -59,13 +59,21 @@ class ApiLogout extends ApiBase {
Hooks::run( 'UserLogoutComplete', [ &$user, &$injected_html, $oldName ] );
}
+ public function mustBePosted() {
+ return true;
+ }
+
+ public function needsToken() {
+ return 'csrf';
+ }
+
public function isReadMode() {
return false;
}
protected function getExamplesMessages() {
return [
- 'action=logout'
+ 'action=logout&token=123ABC'
=> 'apihelp-logout-example-logout',
];
}
diff --git a/includes/skins/SkinTemplate.php b/includes/skins/SkinTemplate.php
index 8f45f281c231..25771bc95245 100644
--- a/includes/skins/SkinTemplate.php
+++ b/includes/skins/SkinTemplate.php
@@ -617,16 +617,18 @@ class SkinTemplate extends Skin {
$page = Title::newFromText( $request->getVal( 'title', '' ) );
}
$page = $request->getVal( 'returnto', $page );
- $a = [];
+ $returnto = [];
if ( strval( $page ) !== '' ) {
- $a['returnto'] = $page;
+ $returnto['returnto'] = $page;
$query = $request->getVal( 'returntoquery', $this->thisquery );
+ $paramsArray = wfCgiToArray( $query );
+ unset( $paramsArray['logoutToken'] );
+ $query = wfArrayToCgi( $paramsArray );
if ( $query != '' ) {
- $a['returntoquery'] = $query;
+ $returnto['returntoquery'] = $query;
}
}
- $returnto = wfArrayToCgi( $a );
if ( $this->loggedin ) {
$personal_urls['userpage'] = [
'text' => $this->username,
@@ -691,9 +693,10 @@ class SkinTemplate extends Skin {
$personal_urls['logout'] = [
'text' => $this->msg( 'pt-userlogout' )->text(),
'href' => self::makeSpecialUrl( 'Userlogout',
- // userlogout link must always contain an & character, otherwise we might not be able
+ // Note: userlogout link must always contain an & character, otherwise we might not be able
// to detect a buggy precaching proxy (T19790)
- $title->isSpecial( 'Preferences' ) ? 'noreturnto' : $returnto ),
+ ( $title->isSpecial( 'Preferences' ) ? [] : $returnto )
+ + [ 'logoutToken' => $this->getUser()->getEditToken( 'logoutToken', $this->getRequest() ) ] ),
'active' => false
];
}
diff --git a/includes/specials/SpecialUserLogout.php b/includes/specials/SpecialUserLogout.php
index a9b732efb120..568327d25b23 100644
--- a/includes/specials/SpecialUserLogout.php
+++ b/includes/specials/SpecialUserLogout.php
@@ -48,6 +48,28 @@ class SpecialUserLogout extends UnlistedSpecialPage {
$this->setHeaders();
$this->outputHeader();
+ $out = $this->getOutput();
+ $user = $this->getUser();
+ $request = $this->getRequest();
+
+ $logoutToken = $request->getVal( 'logoutToken' );
+ $urlParams = [
+ 'logoutToken' => $user->getEditToken( 'logoutToken', $request )
+ ] + $request->getValues();
+ unset( $urlParams['title'] );
+ $continueLink = $this->getFullTitle()->getFullUrl( $urlParams );
+
+ if ( $logoutToken === null ) {
+ $this->getOutput()->addWikiMsg( 'userlogout-continue', $continueLink );
+ return;
+ }
+ if ( !$this->getUser()->matchEditToken(
+ $logoutToken, 'logoutToken', $this->getRequest(), 24 * 60 * 60
+ ) ) {
+ $this->getOutput()->addWikiMsg( 'userlogout-sessionerror', $continueLink );
+ return;
+ }
+
// Make sure it's possible to log out
$session = MediaWiki\Session\SessionManager::getGlobalSession();
if ( !$session->canSetUser() ) {