Page MenuHomePhabricator

BlockLogFormatter can output raw html (CVE-2020-35478, CVE-2020-35479)
Closed, ResolvedPublicSecurity

Description

CVE-2020-35478 - Potential XSS via MediaWiki:blanknamespace outputting Block Logs
CVE-2020-35479 - Potential XSS via the "month messages" such as MediaWiki:january through MediaWiki:december outputting Block Logs


While working on T216348 I have found issues with the BlockLogFormatter

First issue is about the message blanknamespace. it is used with Message::text

				$namespaces = $params[6]['namespaces'] ?? [];
				$namespaces = array_map( function ( $ns ) {
					$text = (int)$ns === NS_MAIN
						? $this->msg( 'blanknamespace' )->text()
						: $this->context->getLanguage()->getFormattedNsText( $ns );
					$params = [ 'namespace' => $ns ];

					return $this->makePageLink( SpecialPage::getTitleFor( 'Allpages' ), $params, $text );
				}, $namespaces );

But LogFormatter::makePageLink is documented to get html as third parameter. even in plaintext mode from LogFormatter.

Through that message it is possible to output raw html including script tags.

The second issue is with Language::translateBlockExpiry. The return value is included as raw param in the output without escaping.

			$durationTooltip = '‎' . htmlspecialchars( $params[4] );
			$blockExpiry = $this->context->getLanguage()->translateBlockExpiry(
				$params[4],
				$this->context->getUser(),
				wfTimestamp( TS_UNIX, $this->entry->getTimestamp() )
			);
			if ( $this->plaintext ) {
				$params[4] = Message::rawParam( $blockExpiry );
			} else {
				$params[4] = Message::rawParam(
					"<span class=\"blockExpiry\" title=\"$durationTooltip\">" .
					$blockExpiry .
					'</span>'
				);
			}

Language::translateBlockExpiry itself does not escape all code path, for example the return of Language::userTimeAndDate, which is always unsafe for html.
Through the month messages it is possible to output raw html including script tags.

Taint-check found other places to check, but that looks like false positives to me:

13:49:09 includes/logging/BlockLogFormatter.php:98 SecurityCheck-XSS Calling method \Message::rawParams() in \BlockLogFormatter::getMessageParameters that outputs using tainted argument $[arg #1]. (Caused by: Builtin-\Message::rawParams) (Caused by: includes/logging/BlockLogFormatter.php +82) (Param is raw)
13:49:09 includes/logging/BlockLogFormatter.php:104 SecurityCheck-XSS Calling method \Message::rawParams() in \BlockLogFormatter::getMessageParameters that outputs using tainted argument $[arg #1]. (Caused by: Builtin-\Message::rawParams) (Caused by: includes/logging/BlockLogFormatter.php +87) (Param is raw)

LogFormatter has a plaintext mode and a normal mode and that confused taint-check

Event Timeline

Reedy triaged this task as High priority.Nov 30 2020, 4:24 PM
Reedy moved this task from Incoming to Watching on the Security-Team board.

We'll keep an eye on this, but looks like there's nothing for Anti-Harassment to do, thanks to @Umherirrender, @DannyS712 and @Jdforrester-WMF sorting it quickly!

Change 649521 had a related patch set uploaded (by Reedy; owner: Umherirrender):
[mediawiki/core@REL1_35] Pass escaped html to LogFormatter::makePageLink for sanity

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

Change 649522 had a related patch set uploaded (by Reedy; owner: Umherirrender):
[mediawiki/core@REL1_31] Pass escaped html to LogFormatter::makePageLink for sanity

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

Change 649522 abandoned by Reedy:
[mediawiki/core@REL1_31] Pass escaped html to LogFormatter::makePageLink for sanity

Reason:

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

Change 649523 had a related patch set uploaded (by Reedy; owner: Umherirrender):
[mediawiki/core@REL1_35] Fixed mixed escaping in Language::translateBlockExpiry

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

Change 649524 had a related patch set uploaded (by Reedy; owner: Umherirrender):
[mediawiki/core@REL1_31] Fixed mixed escaping in Language::translateBlockExpiry

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

Change 649524 abandoned by Reedy:
[mediawiki/core@REL1_31] Fixed mixed escaping in Language::translateBlockExpiry

Reason:

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

Looks like the first patch (https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646684) isn't relevant for REL1_31, or code has been moved around/refactored (ie it needs patching elsewhere)...

And for https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646689, at least for BlockLogFormatter.php, again, the same? What about the two trim() calls in Language? They seem a bit superfluous by themselves

At least some of the touched code is from 1.33.0+ in rMW31ba7a3e5c6f: Fix malformed output of block logs... And then various supporting changes from before that

Thoughts?

Change 649521 merged by jenkins-bot:
[mediawiki/core@REL1_35] Pass escaped html to LogFormatter::makePageLink for sanity

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

Change 649523 merged by jenkins-bot:
[mediawiki/core@REL1_35] Fixed mixed escaping in Language::translateBlockExpiry

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

Change 649524 restored by Reedy:
[mediawiki/core@REL1_31] Fixed mixed escaping in Language::translateBlockExpiry

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

Looks like the first patch (https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646684) isn't relevant for REL1_31, or code has been moved around/refactored (ie it needs patching elsewhere)...

And for https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646689, at least for BlockLogFormatter.php, again, the same? What about the two trim() calls in Language? They seem a bit superfluous by themselves

At least some of the touched code is from 1.33.0+ in rMW31ba7a3e5c6f: Fix malformed output of block logs... And then various supporting changes from before that

Thoughts?

Ok. So the first patch, ala https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646684 was not added till 1.33 in rMW85c91cfbf09d: Add namespace restrictions to block's log messages for T204985: Update block logs with namespace block details. I'm declaring that as not applicable for 1.31.

https://gerrit.wikimedia.org/r/c/mediawiki/core/+/646689 goes ontop of rMW31ba7a3e5c6f: Fix malformed output of block logs for T208523: Blocks log entries display as malformed on Special:CheckUser, also last changed in 1.33. But that only added "plaintext" support. The code being fixed is still there though

Will bring it in, with the refactoring to move the translateBlockExpiry call also into a variable to keep the code similar. Not doing a full backport of that patch (rMW31ba7a3e5c6f: Fix malformed output of block logs), as I don't think it's particularly warranted

Need to get a CVE for this one

Change 649524 merged by jenkins-bot:
[mediawiki/core@REL1_31] Fixed mixed escaping in Language::translateBlockExpiry

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

Reedy renamed this task from BlockLogFormatter can output raw html to BlockLogFormatter can output raw html (CVE-2020-35478, CVE-2020-35479).Dec 16 2020, 7:57 PM
Reedy updated the task description. (Show Details)

This needed two different CVE, because two different CVEs.

Might need to do some upstream tweaking post release.

Reedy changed the visibility from "Custom Policy" to "Public (No Login Required)".Dec 18 2020, 12:24 AM
Reedy changed the edit policy from "Custom Policy" to "All Users".