jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/367632 )

Change subject: [SECURITY] Fix XSS in UserBoard on social profile pages and 
CSRF in API modules which do write actions
......................................................................


[SECURITY] Fix XSS in UserBoard on social profile pages and CSRF in API modules 
which do write actions

Bug: T171045
Change-Id: I50c1f0837f407489c555c49d3a83437c27a9ddee
---
M .jshintrc
M SocialProfile.php
M UserBoard/ApiDeleteUserBoardMessage.php
M UserBoard/ApiSendUserBoardMessage.php
M UserBoard/SpecialUserBoard.php
M UserBoard/UserBoard.js
M UserBoard/UserBoardClass.php
M UserProfile/ApiUserProfilePrivacy.php
M UserProfile/UpdateProfile.js
M UserProfile/UserProfile.php
M UserProfile/UserProfilePage.js
11 files changed, 97 insertions(+), 82 deletions(-)

Approvals:
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/.jshintrc b/.jshintrc
index 8a2a10c..a0ff444 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -18,6 +18,7 @@
        "jquery": true,
 
        "globals": {
-               "mediaWiki": false
+               "mediaWiki": false,
+               "mw": false
        }
 }
diff --git a/SocialProfile.php b/SocialProfile.php
index e47e4d5..d9ac323 100644
--- a/SocialProfile.php
+++ b/SocialProfile.php
@@ -150,7 +150,7 @@
        'path' => __FILE__,
        'name' => 'SocialProfile',
        'author' => array( 'Aaron Wright', 'David Pean', 'Jack Phoenix' ),
-       'version' => '1.12',
+       'version' => '1.13',
        'url' => 'https://www.mediawiki.org/wiki/Extension:SocialProfile',
        'descriptionmsg' => 'socialprofile-desc',
 );
@@ -301,6 +301,7 @@
 // UserBoard
 $wgResourceModules['ext.socialprofile.userboard.js'] = array(
        'scripts' => 'UserBoard.js',
+       'dependencies' => array( 'mediawiki.api' ),
        'messages' => array( 'userboard_confirmdelete' ),
        'localBasePath' => __DIR__ . '/UserBoard',
        'remoteExtPath' => 'SocialProfile/UserBoard',
diff --git a/UserBoard/ApiDeleteUserBoardMessage.php 
b/UserBoard/ApiDeleteUserBoardMessage.php
index b30d79c..85edd33 100644
--- a/UserBoard/ApiDeleteUserBoardMessage.php
+++ b/UserBoard/ApiDeleteUserBoardMessage.php
@@ -27,6 +27,14 @@
                return true;
        }
 
+       public function needsToken() {
+               return 'csrf';
+       }
+
+       public function isWriteMode() {
+               return true;
+       }
+
        public function getAllowedParams() {
                return array_merge( parent::getAllowedParams(), array(
                        'id' => array(
diff --git a/UserBoard/ApiSendUserBoardMessage.php 
b/UserBoard/ApiSendUserBoardMessage.php
index 6c311e6..b8853ec 100644
--- a/UserBoard/ApiSendUserBoardMessage.php
+++ b/UserBoard/ApiSendUserBoardMessage.php
@@ -36,6 +36,14 @@
                return true;
        }
 
+       public function needsToken() {
+               return 'csrf';
+       }
+
+       public function isWriteMode() {
+               return true;
+       }
+
        public function getAllowedParams() {
                return array_merge( parent::getAllowedParams(), array(
                        'username' => array(
diff --git a/UserBoard/SpecialUserBoard.php b/UserBoard/SpecialUserBoard.php
index d957fa6..438379b 100644
--- a/UserBoard/SpecialUserBoard.php
+++ b/UserBoard/SpecialUserBoard.php
@@ -282,6 +282,9 @@
                }
                $output .= '<div id="user-page-board">';
 
+               // @todo FIXME: This if-else loop *massively* duplicates
+               // UserBoard::displayMessages(). We should refactor that and 
this into
+               // one sane & sensible method. --ashley, 19 July 2017
                if ( $ub_messages ) {
                        foreach ( $ub_messages as $ub_message ) {
                                $user = Title::makeTitle( NS_USER, 
$ub_message['user_name_from'] );
@@ -325,16 +328,17 @@
                                $ub_message_text = $ub_message['message_text'];
 
                                $userPageURL = htmlspecialchars( 
$user->getFullURL() );
+                               $senderTitle = htmlspecialchars( 
$ub_message['user_name_from'] );
                                $output .= "<div class=\"user-board-message\">
                                        <div class=\"user-board-message-from\">
-                                                       <a 
href=\"{$userPageURL}\" 
title=\"{$ub_message['user_name_from']}\">{$ub_message['user_name_from']} </a> 
{$ub_message_type_label}
+                                               <a href=\"{$userPageURL}\" 
title=\"{$senderTitle}\">{$ub_message['user_name_from']} </a> 
{$ub_message_type_label}
                                        </div>
                                        <div class=\"user-board-message-time\">"
                                                . $this->msg( 
'userboard_posted_ago', $b->getTimeAgo( $ub_message['timestamp'] ) )->parse() .
                                        "</div>
                                        <div 
class=\"user-board-message-content\">
                                                <div 
class=\"user-board-message-image\">
-                                                       <a 
href=\"{$userPageURL}\" 
title=\"{$ub_message['user_name_from']}\">{$avatar->getAvatarURL()}</a>
+                                                       <a 
href=\"{$userPageURL}\" title=\"{$senderTitle}\">{$avatar->getAvatarURL()}</a>
                                                </div>
                                                <div 
class=\"user-board-message-body\">
                                                        {$ub_message_text}
diff --git a/UserBoard/UserBoard.js b/UserBoard/UserBoard.js
index f672814..80b2452 100644
--- a/UserBoard/UserBoard.js
+++ b/UserBoard/UserBoard.js
@@ -13,48 +13,42 @@
                        var encodedName = encodeURIComponent( recipient ),
                                encodedMsg = encodeURIComponent( message ),
                                messageType = document.getElementById( 
'message_type' ).value;
-                       jQuery.post(
-                               mediaWiki.util.wikiScript( 'api' ), {
-                                       action: 'socialprofile-send-message',
-                                       format: 'json',
-                                       username: encodedName,
-                                       message: encodedMsg,
-                                       type: messageType
-                               },
-                               function() {
-                                       UserBoard.posted = 0;
-                                       var user_1, user_2;
-                                       if ( sender ) { // it's a board to board
-                                               user_1 = sender;
-                                               user_2 = recipient;
-                                       } else {
-                                               user_1 = recipient;
-                                               user_2 = '';
-                                       }
-                                       var params = ( user_2 ) ? '&conv=' + 
user_2 : '';
-                                       var url = mediaWiki.config.get( 
'wgScriptPath' ) + '/index.php?title=Special:UserBoard&user=' + user_1 + params;
-                                       window.location = url;
+                       ( new mw.Api() ).postWithToken( 'edit', {
+                               action: 'socialprofile-send-message',
+                               format: 'json',
+                               username: encodedName,
+                               message: encodedMsg,
+                               type: messageType
+                       } ).done( function() {
+                               UserBoard.posted = 0;
+                               var user_1, user_2;
+                               if ( sender ) { // it's a board to board
+                                       user_1 = sender;
+                                       user_2 = recipient;
+                               } else {
+                                       user_1 = recipient;
+                                       user_2 = '';
                                }
-                       );
+                               var params = ( user_2 ) ? '&conv=' + user_2 : 
'';
+                               var url = mediaWiki.config.get( 'wgScriptPath' 
) + '/index.php?title=Special:UserBoard&user=' + user_1 + params;
+                               window.location = url;
+                       } );
                }
        },
 
        deleteMessage: function( id ) {
                if ( window.confirm( mediaWiki.msg( 'userboard_confirmdelete' ) 
) ) {
-                       jQuery.post(
-                               mediaWiki.util.wikiScript( 'api' ), {
-                                       action: 'socialprofile-delete-message',
-                                       format: 'json',
-                                       'id': id
-                               },
-                               function() {
-                                       //window.location.reload();
-                                       // 1st parent = span.user-board-red
-                                       // 2nd parent = 
div.user-board-message-links
-                                       // 3rd parent = div.user-board-message 
= the container of a msg
-                                       jQuery( '[data-message-id="' + id + 
'"]' ).parent().parent().parent().hide( 100 );
-                               }
-                       );
+                       ( new mw.Api() ).postWithToken( 'edit', {
+                               action: 'socialprofile-delete-message',
+                               format: 'json',
+                               'id': id
+                       } ).done( function() {
+                               //window.location.reload();
+                               // 1st parent = span.user-board-red
+                               // 2nd parent = div.user-board-message-links
+                               // 3rd parent = div.user-board-message = the 
container of a msg
+                               jQuery( '[data-message-id="' + id + '"]' 
).parent().parent().parent().hide( 100 );
+                       } );
                }
        }
 };
diff --git a/UserBoard/UserBoardClass.php b/UserBoard/UserBoardClass.php
index 3fa9367..cfd6175 100644
--- a/UserBoard/UserBoardClass.php
+++ b/UserBoard/UserBoardClass.php
@@ -407,16 +407,17 @@
                                # $message_text = preg_replace_callback( 
"/(<a[^>]*>)(.*?)(<\/a>)/i", 'cut_link_text', $message['message_text'] );
 
                                $sender = htmlspecialchars( $user->getFullURL() 
);
+                               $senderTitle = htmlspecialchars( 
$message['user_name_from'] );
                                $output .= "<div class=\"user-board-message\">
                                        <div class=\"user-board-message-from\">
-                                       <a href=\"{$sender}\" 
title=\"{$message['user_name_from']}\">{$message['user_name_from']}</a> 
{$message_type_label}
+                                       <a href=\"{$sender}\" 
title=\"{$senderTitle}\">{$message['user_name_from']}</a> {$message_type_label}
                                        </div>
                                        <div 
class=\"user-board-message-time\">" .
                                                wfMessage( 
'userboard_posted_ago', $this->getTimeAgo( $message['timestamp'] ) )->parse() .
                                        "</div>
                                        <div 
class=\"user-board-message-content\">
                                                <div 
class=\"user-board-message-image\">
-                                                       <a href=\"{$sender}\" 
title=\"{$message['user_name_from']}\">{$avatar->getAvatarURL()}</a>
+                                                       <a href=\"{$sender}\" 
title=\"{$senderTitle}\">{$avatar->getAvatarURL()}</a>
                                                </div>
                                                <div 
class=\"user-board-message-body\">
                                                        {$message_text}
diff --git a/UserProfile/ApiUserProfilePrivacy.php 
b/UserProfile/ApiUserProfilePrivacy.php
index d6be9de..7b7bfc2 100644
--- a/UserProfile/ApiUserProfilePrivacy.php
+++ b/UserProfile/ApiUserProfilePrivacy.php
@@ -60,6 +60,14 @@
                $result->addValue( null, $this->getModuleName(), $data );
        }
 
+       public function needsToken() {
+               return 'csrf';
+       }
+
+       public function isWriteMode() {
+               return true;
+       }
+
        /**
         * @return array
         */
diff --git a/UserProfile/UpdateProfile.js b/UserProfile/UpdateProfile.js
index d9fab41..c99bf05 100644
--- a/UserProfile/UpdateProfile.js
+++ b/UserProfile/UpdateProfile.js
@@ -105,16 +105,12 @@
 
                $( this_element ).find( 'div.title' ).html( '...' );
 
-               $.ajax( {
-                       type: 'GET',
-                       url: mediaWiki.util.wikiScript( 'api' ),
-                       data: {
-                               action: 'smpuserprivacy',
-                               format: 'json',
-                               method: 'set',
-                               'field_key': field_key,
-                               privacy: encodeURIComponent( priv )
-                       }
+               ( new mw.Api() ).postWithToken( 'edit', {
+                       action: 'smpuserprivacy',
+                       format: 'json',
+                       method: 'set',
+                       'field_key': field_key,
+                       privacy: encodeURIComponent( priv )
                } ).done( function( data ) {
                        var offset = $( this_element ).offset();
                        $( this_element ).remove();
diff --git a/UserProfile/UserProfile.php b/UserProfile/UserProfile.php
index a6dc033..181f86c 100644
--- a/UserProfile/UserProfile.php
+++ b/UserProfile/UserProfile.php
@@ -81,7 +81,7 @@
 $wgResourceModules['ext.socialprofile.userprofile.js'] = array(
        'scripts' => 'UserProfilePage.js',
        'messages' => array( 'user-board-confirm-delete' ),
-       'dependencies' => 'mediawiki.util',
+       'dependencies' => array( 'mediawiki.api', 'mediawiki.util' ),
        'localBasePath' => __DIR__,
        'remoteExtPath' => 'SocialProfile/UserProfile',
 );
@@ -89,7 +89,7 @@
 // Modules for Special:EditProfile/Special:UpdateProfile
 $wgResourceModules['ext.userProfile.updateProfile'] = array(
        'scripts' => 'UpdateProfile.js',
-       'dependencies' => array( 'mediawiki.util', 'jquery.ui.datepicker' ),
+       'dependencies' => array( 'mediawiki.api', 'mediawiki.util', 
'jquery.ui.datepicker' ),
        'localBasePath' => __DIR__,
        'remoteExtPath' => 'SocialProfile/UserProfile',
        'position' => 'top'
diff --git a/UserProfile/UserProfilePage.js b/UserProfile/UserProfilePage.js
index 6ae9fa5..3452ef3 100644
--- a/UserProfile/UserProfilePage.js
+++ b/UserProfile/UserProfilePage.js
@@ -14,39 +14,33 @@
                        msgType = document.getElementById( 'message_type' 
).value;
                if ( document.getElementById( 'message' ).value && 
!UserProfilePage.posted ) {
                        UserProfilePage.posted = 1;
-                       jQuery.post(
-                               mediaWiki.util.wikiScript( 'api' ), {
-                                       action: 'socialprofile-send-message',
-                                       format: 'json',
-                                       username: userTo,
-                                       message: encMsg,
-                                       type: msgType
-                               },
-                               function( data ) {
-                                       jQuery( data.result ).prependTo( 
'#user-page-board' );
-                                       UserProfilePage.posted = 0;
-                                       jQuery( '#message' ).val( '' );
-                               }
-                       );
+                       ( new mw.Api() ).postWithToken( 'edit', {
+                               action: 'socialprofile-send-message',
+                               format: 'json',
+                               username: userTo,
+                               message: encMsg,
+                               type: msgType
+                       } ).done( function( data ) {
+                               jQuery( data.result ).prependTo( 
'#user-page-board' );
+                               UserProfilePage.posted = 0;
+                               jQuery( '#message' ).val( '' );
+                       } );
                }
        },
 
        deleteMessage: function( id ) {
                if ( window.confirm( mediaWiki.msg( 'user-board-confirm-delete' 
) ) ) {
-                       jQuery.post(
-                               mediaWiki.util.wikiScript( 'api' ), {
-                                       action: 'socialprofile-delete-message',
-                                       format: 'json',
-                                       'id': id
-                               },
-                               function() {
-                                       //window.location.reload();
-                                       // 1st parent = span.user-board-red
-                                       // 2nd parent = 
div.user-board-message-links
-                                       // 3rd parent = div.user-board-message 
= the container of a msg
-                                       jQuery( '[data-message-id="' + id + 
'"]' ).parent().parent().parent().hide( 100 );
-                               }
-                       );
+                       ( new mw.Api() ).postWithToken( 'edit', {
+                               action: 'socialprofile-delete-message',
+                               format: 'json',
+                               'id': id
+                       } ).done( function() {
+                               //window.location.reload();
+                               // 1st parent = span.user-board-red
+                               // 2nd parent = div.user-board-message-links
+                               // 3rd parent = div.user-board-message = the 
container of a msg
+                               jQuery( '[data-message-id="' + id + '"]' 
).parent().parent().parent().hide( 100 );
+                       } );
                }
        },
 

-- 
To view, visit https://gerrit.wikimedia.org/r/367632
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I50c1f0837f407489c555c49d3a83437c27a9ddee
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/extensions/SocialProfile
Gerrit-Branch: master
Gerrit-Owner: Jack Phoenix <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Lewis Cawte <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to