Majr has uploaded a new change for review.

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

Change subject: Fix possibility for arbitrary HTML output
......................................................................

Fix possibility for arbitrary HTML output

Trusting the page content is inherently insecure. Instead, store the
parsed content in an array and output an index to retrieve it later.

Bug: T88964
Change-Id: I00ede9c7f333f32f2cc7722781b06f97a544927f
---
M WidgetRenderer.php
M Widgets.php
2 files changed, 23 insertions(+), 22 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Widgets 
refs/changes/49/189449/1

diff --git a/WidgetRenderer.php b/WidgetRenderer.php
index 3ef961a..9682b59 100644
--- a/WidgetRenderer.php
+++ b/WidgetRenderer.php
@@ -4,15 +4,16 @@
  */
 
 class WidgetRenderer {
-
-       // A randomly-generated string, used to prevent malicious users from
-       // spoofing the output of #widget in order to have arbitrary
-       // JavaScript show up in the page's output.
-       static $mRandomString;
-
+       // The prefix and suffix for the widget strip marker.
+       private static $markerPrefix = "START_WIDGET";
+       private static $markerSuffix = "END_WIDGET";
+       
+       // Stores the compiled widgets for after the parser has run.
+       private static $widgets = array();
+       
        public static function initRandomString() {
-               // Set the random string, used in both encoding and decoding.
-               self::$mRandomString = substr( base64_encode( rand() ), 0, 7 );
+               // Add a random string to the prefix to ensure no conflicts 
with normal content.
+               self::$markerPrefix .= wfRandomString( 16 );
        }
 
        public static function renderWidget( &$parser, $widgetName ) {
@@ -127,20 +128,20 @@
                try {
                        $output = $smarty->fetch( "wiki:$widgetName" );
                } catch ( Exception $e ) {
-                       return '<div class=\"error\">' . wfMessage( 
'widgets-error', htmlentities( $widgetName ) )->text() . '</div>';
+                       return '<strong class="error">' . wfMessage( 
'widgets-error', htmlentities( $widgetName ) )->text() . '</strong>';
                }
-
-               // Hide the widget from the parser.
-               $output = 'ENCODED_CONTENT ' . self::$mRandomString . 
base64_encode($output) . ' END_ENCODED_CONTENT';
-               return array( $output, 'noparse' => true, 'isHTML' => true );
+               
+               // To prevent the widget output from being tampered with, the 
compiled HTML
+               // is stored and a strip marker with an index to retrieve it 
later is returned.
+               $index = array_push( self::$widgets, $output ) - 1;
+               return self::$markerPrefix . '-' . $index . self::$markerSuffix;
        }
 
-       public static function processEncodedWidgetOutput( &$out, &$text ) {
-               // Find all hidden content and restore to normal
+       public static function outputCompiledWidget( &$out, &$text ) {
                $text = preg_replace_callback(
-                       '/ENCODED_CONTENT ' . self::$mRandomString . 
'([0-9a-zA-Z\/+]+=*)* END_ENCODED_CONTENT/',
+                       '/' . self::$markerPrefix . '-(\d+)' . 
self::$markerSuffix . '/S',
                        function( $matches ) {
-                               return base64_decode( $matches[1]);
+                               return self::$widgets[$matches[1]];
                        },
                        $text
                );
diff --git a/Widgets.php b/Widgets.php
index 6c52c5a..887ca43 100644
--- a/Widgets.php
+++ b/Widgets.php
@@ -17,7 +17,7 @@
        'name' => 'Widgets',
        'descriptionmsg' => 'widgets-desc',
        'version' => '1.1',
-       'author' => '[http://www.sergeychernyshev.com Sergey Chernyshev]',
+       'author' => array( '[http://www.sergeychernyshev.com Sergey 
Chernyshev]', '...' ),
        'url' => 'https://www.mediawiki.org/wiki/Extension:Widgets'
 );
 
@@ -50,11 +50,11 @@
 // Set a default directory for storage of compiled templates
 $wgWidgetsCompileDir = "$IP/extensions/Widgets/compiled_templates/";
 
-$dir = dirname( __FILE__ ) . '/';
+$dir = __DIR__ . '/';
 
 // Initialize Smarty
 require_once( $dir . 'smarty/libs/Smarty.class.php' );
-$wgMessagesDirs['Widgets'] = __DIR__ . '/i18n';
+$wgMessagesDirs['Widgets'] = $dir . 'i18n';
 $wgExtensionMessagesFiles['Widgets'] = $dir . 'Widgets.i18n.php';
 $wgExtensionMessagesFiles['WidgetsNamespaces'] = $dir . 
'Widgets.i18n.namespaces.php';
 $wgAutoloadClasses['WidgetRenderer'] = $dir . 'WidgetRenderer.php';
@@ -65,7 +65,7 @@
 $wgExtensionFunctions[] = 'widgetNamespacesInit';
 $wgExtensionFunctions[] = 'WidgetRenderer::initRandomString';
 $wgHooks['ParserFirstCallInit'][] = 'widgetParserFunctions';
-$wgHooks['ParserAfterTidy'][] = 'WidgetRenderer::processEncodedWidgetOutput';
+$wgHooks['ParserAfterTidy'][] = 'WidgetRenderer::outputCompiledWidget';
 $wgHooks['CanonicalNamespaces'][] = 'widgetsAddNamespaces';
 
 /**
@@ -73,7 +73,7 @@
  * @return bool
  */
 function widgetParserFunctions( &$parser ) {
-       $parser->setFunctionHook( 'widget', array( 'WidgetRenderer', 
'renderWidget' ) );
+       $parser->setFunctionHook( 'widget', 'WidgetRenderer::renderWidget' );
 
        return true;
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I00ede9c7f333f32f2cc7722781b06f97a544927f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Widgets
Gerrit-Branch: master
Gerrit-Owner: Majr <[email protected]>

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

Reply via email to