SECURITY: Disable <html> tag on system messages despite $wgRawHtml = true;
System messages may take parameters from untrusted sources. This may include taking parameters from urls given by unauthenticated users even if the wiki is a read-only wiki. Allowing <html> tags in such a context seems like an accident waiting to happen. Bug: T156184 Change-Id: I661f482986d319cf41da1d3e7b20a0f028a42e90
This commit is contained in:
parent
19f844f7f0
commit
1c7889446d
7 changed files with 77 additions and 4 deletions
|
|
@ -1568,6 +1568,7 @@ class OutputPage extends ContextSource {
|
|||
// been changed somehow, and keep it if so.
|
||||
$anonPO = ParserOptions::newFromAnon();
|
||||
$anonPO->setEditSection( false );
|
||||
$anonPO->setAllowUnsafeRawHtml( false );
|
||||
if ( !$options->matches( $anonPO ) ) {
|
||||
wfLogWarning( __METHOD__ . ': Setting a changed bogus ParserOptions: ' . wfGetAllCallers( 5 ) );
|
||||
$options->isBogus = false;
|
||||
|
|
@ -1581,6 +1582,7 @@ class OutputPage extends ContextSource {
|
|||
// either.
|
||||
$po = ParserOptions::newFromAnon();
|
||||
$po->setEditSection( false );
|
||||
$po->setAllowUnsafeRawHtml( false );
|
||||
$po->isBogus = true;
|
||||
if ( $options !== null ) {
|
||||
$this->mParserOptions = empty( $options->isBogus ) ? $options : null;
|
||||
|
|
@ -1590,6 +1592,7 @@ class OutputPage extends ContextSource {
|
|||
|
||||
$this->mParserOptions = ParserOptions::newFromContext( $this->getContext() );
|
||||
$this->mParserOptions->setEditSection( false );
|
||||
$this->mParserOptions->setAllowUnsafeRawHtml( false );
|
||||
}
|
||||
|
||||
if ( $options !== null && !empty( $options->isBogus ) ) {
|
||||
|
|
|
|||
5
includes/cache/MessageCache.php
vendored
5
includes/cache/MessageCache.php
vendored
|
|
@ -191,11 +191,16 @@ class MessageCache {
|
|||
// either.
|
||||
$po = ParserOptions::newFromAnon();
|
||||
$po->setEditSection( false );
|
||||
$po->setAllowUnsafeRawHtml( false );
|
||||
return $po;
|
||||
}
|
||||
|
||||
$this->mParserOptions = new ParserOptions;
|
||||
$this->mParserOptions->setEditSection( false );
|
||||
// Messages may take parameters that could come
|
||||
// from malicious sources. As a precaution, disable
|
||||
// the <html> parser tag when parsing messages.
|
||||
$this->mParserOptions->setAllowUnsafeRawHtml( false );
|
||||
}
|
||||
|
||||
return $this->mParserOptions;
|
||||
|
|
|
|||
|
|
@ -79,12 +79,25 @@ class CoreTagHooks {
|
|||
* @param array $attributes
|
||||
* @param Parser $parser
|
||||
* @throws MWException
|
||||
* @return array
|
||||
* @return array|string Output of tag hook
|
||||
*/
|
||||
public static function html( $content, $attributes, $parser ) {
|
||||
global $wgRawHtml;
|
||||
if ( $wgRawHtml ) {
|
||||
return [ $content, 'markerType' => 'nowiki' ];
|
||||
if ( $parser->getOptions()->getAllowUnsafeRawHtml() ) {
|
||||
return [ $content, 'markerType' => 'nowiki' ];
|
||||
} else {
|
||||
// In a system message where raw html is
|
||||
// not allowed (but it is allowed in other
|
||||
// contexts).
|
||||
return Html::rawElement(
|
||||
'span',
|
||||
[ 'class' => 'error' ],
|
||||
// Using ->text() not ->parse() as
|
||||
// a paranoia measure against a loop.
|
||||
wfMessage( 'rawhtml-notallowed' )->escaped()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new MWException( '<html> extension tag encountered unexpectedly' );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,6 +243,21 @@ class ParserOptions {
|
|||
*/
|
||||
private $redirectTarget = null;
|
||||
|
||||
/**
|
||||
* If the wiki is configured to allow raw html ($wgRawHtml = true)
|
||||
* is it allowed in the specific case of parsing this page.
|
||||
*
|
||||
* This is meant to disable unsafe parser tags in cases where
|
||||
* a malicious user may control the input to the parser.
|
||||
*
|
||||
* @note This is expected to be true for normal pages even if the
|
||||
* wiki has $wgRawHtml disabled in general. The setting only
|
||||
* signifies that raw html would be unsafe in the current context
|
||||
* provided that raw html is allowed at all.
|
||||
* @var boolean
|
||||
*/
|
||||
private $allowUnsafeRawHtml = true;
|
||||
|
||||
public function getInterwikiMagic() {
|
||||
return $this->mInterwikiMagic;
|
||||
}
|
||||
|
|
@ -457,6 +472,15 @@ class ParserOptions {
|
|||
public function getMagicRFCLinks() {
|
||||
return $this->mMagicRFCLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.29
|
||||
* @return bool
|
||||
*/
|
||||
public function getAllowUnsafeRawHtml() {
|
||||
return $this->allowUnsafeRawHtml;
|
||||
}
|
||||
|
||||
public function setInterwikiMagic( $x ) {
|
||||
return wfSetVar( $this->mInterwikiMagic, $x );
|
||||
}
|
||||
|
|
@ -596,6 +620,15 @@ class ParserOptions {
|
|||
return wfSetVar( $this->mIsPrintable, $x );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|null Value to set or null to get current value
|
||||
* @return bool Current value for allowUnsafeRawHtml
|
||||
* @since 1.29
|
||||
*/
|
||||
public function setAllowUnsafeRawHtml( $x ) {
|
||||
return wfSetVar( $this->allowUnsafeRawHtml, $x );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redirect target.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4283,5 +4283,6 @@
|
|||
"restrictionsfield-label": "Allowed IP ranges:",
|
||||
"restrictionsfield-help": "One IP address or CIDR range per line. To enable everything, use:<pre>0.0.0.0/0\n::/0</pre>",
|
||||
"revid": "revision $1",
|
||||
"pageid": "page ID $1"
|
||||
"pageid": "page ID $1",
|
||||
"rawhtml-notallowed": "<html> tags cannot be used outside of normal pages."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4470,5 +4470,6 @@
|
|||
"restrictionsfield-label": "Field label shown for restriction fields (e.g. on Special:BotPassword).",
|
||||
"restrictionsfield-help": "Placeholder text displayed in restriction fields (e.g. on Special:BotPassword).",
|
||||
"revid": "Used to format a revision ID number in text. Parameters:\n* $1 - Revision ID number.\n{{Identical|Revision}}",
|
||||
"pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number."
|
||||
"pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number.",
|
||||
"rawhtml-notallowed": "Error message given when $wgRawHtml = true; is set and a user uses an <html> tag in a system message or somewhere other than a normal page."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
class MessageTest extends MediaWikiLangTestCase {
|
||||
|
||||
|
|
@ -394,6 +395,22 @@ class MessageTest extends MediaWikiLangTestCase {
|
|||
$this->assertSame( 'example &', $msg->escaped() );
|
||||
}
|
||||
|
||||
public function testRawHtmlInMsg() {
|
||||
global $wgParserConf;
|
||||
$this->setMwGlobals( 'wgRawHtml', true );
|
||||
// We have to reset the core hook registration.
|
||||
// to register the html hook
|
||||
MessageCache::destroyInstance();
|
||||
$this->setMwGlobals( 'wgParser',
|
||||
ObjectFactory::constructClassInstance( $wgParserConf['class'], [ $wgParserConf ] )
|
||||
);
|
||||
|
||||
$msg = new RawMessage( '<html><script>alert("xss")</script></html>' );
|
||||
$txt = '<span class="error"><html> tags cannot be' .
|
||||
' used outside of normal pages.</span>';
|
||||
$this->assertSame( $txt, $msg->parse() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Message::params
|
||||
* @covers Message::toString
|
||||
|
|
|
|||
Loading…
Reference in a new issue