Page MenuHomePhabricator

It's possible to mangle HTML via raw message parameter expansion
Closed, ResolvedPublic

Description

@Bastenbas reported me this bug:
When a page is moved, the success message Movepage-moved is not displayed correctly. This bug happens on frwiki with its own Mediawiki:Movepage-moved. But this page was not changed since years, so the problem comes from elsewhere.

The rendered HTML of the bloc is, with another tested page :

<div id="aa-bloc-tete" class="plainlinks">
<div class="aa-fond-gris">
<h2 class="aa-titre-bleu"><span id="La_page_«_<a href=" w="" index.php?title="Mussola_pintada_test&amp;redirect=no&quot;" class="mw-redirect" title="Mussola pintada test">Mussola pintada test_»_a_été_renommée_en_«_<a href="/wiki/Mussola_pintada" title="" id="movepage-newlink">Mussola pintada</a>_»"&gt;</span><span class="mw-headline" id="La_page_.C2.AB_.241_.C2.BB_a_.C3.A9t.C3.A9_renomm.C3.A9e_en_.C2.AB_.242_.C2.BB">La page «&nbsp;<a href="/w/index.php?title=Mussola_pintada_test&amp;redirect=no" class="mw-redirect" title="Mussola pintada test" id="movepage-oldlink">Mussola pintada test</a>&nbsp;» a été renommée en «&nbsp;<a href="/wiki/Mussola_pintada" title="Mussola pintada" id="movepage-newlink">Mussola pintada</a>&nbsp;»</span></h2>
<p>Merci de vérifier les points suivants&nbsp;:</p>
<ul><li> si des <a href="/w/index.php?title=Aide:Cat%C3%A9gorie&amp;action=edit&amp;redlink=1" class="new" title="Aide:Catégorie (page does not exist)">clés de tri</a> ont été ajoutées aux catégories, elles peuvent nécessiter une mise à jour&nbsp;;</li>
<li> si vous transformez <a href="/w/index.php?title=Mussola_pintada_test&amp;redirect=no" class="mw-redirect" title="Mussola pintada test" id="movepage-oldlink">Mussola pintada test</a> en <a href="/w/index.php?title=Aide:Homonymie&amp;action=edit&amp;redlink=1" class="new" title="Aide:Homonymie (page does not exist)">page d’homonymie</a>, il faut corriger les pages qui avaient un lien vers «&nbsp;Mussola pintada test&nbsp;» pour que celui-ci pointe vers «&nbsp;Mussola pintada&nbsp;»&nbsp;;</li>
<li> si la page est listée dans des <a href="/w/index.php?title=Aide:Palette_de_navigation&amp;action=edit&amp;redlink=1" class="new" title="Aide:Palette de navigation (page does not exist)">palettes de navigation</a>, pensez à mettre à jour les liens pour qu’ils apparaissent en gras sur la page.</li></ul>
</div>
</div>
<p>A redirect has been created.
</p>

To be able to test this bug I changed Movepage-moved system message on testwiki https://test.wikipedia.org/w/index.php?title=MediaWiki:Movepage-moved&diff=325825&oldid=274510. Curently this bug can be reproctable by renaming any test.wikipedia.org page.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald TranscriptSep 19 2017, 6:56 PM
Framawiki renamed this task from `Movepage-moved` message incorrectly shows the parameters to Incorrect render for `Movepage-moved` message.Sep 19 2017, 9:20 PM
Framawiki updated the task description. (Show Details)

As I can see the problem comes from this span that is useless :

<span id="La_page_«_<a href=" w="" index.php?title="Mussola_pintada_test&amp;redirect=no&quot;" class="mw-redirect" title="Mussola pintada test">Mussola pintada test_»_a_été_renommée_en_«_<a href="/wiki/Mussola_pintada" title="" id="movepage-newlink">Mussola pintada</a>_»"&gt;</span>

Without this code the page is good.

matmarex set Security to Software security bug.Sep 22 2017, 8:51 PM
matmarex added a project: Security.
matmarex changed the visibility from "Public (No Login Required)" to "Custom Policy".
matmarex added a subscriber: matmarex.

There probably isn't a security issue here, but that misparsed HTML looks scary (similar to XSS issues I've seen), so let's make this private for now.

matmarex added subscribers: Krinkle, MaxSem.

This looks like it might be a problem with the new HTML5 ID encoding? T152540

Note this wikitext in the affected overridden message https://fr.wikipedia.org/w/index.php?title=MediaWiki:Movepage-moved&action=edit:

<h2 class="aa-titre-bleu">La page « $1 » a été renommée en « $2 »</h2>

($1 and $2 are apparently HTML links there)

The ID of the <span> inside <h2> is generated based on these contents and not escaped.

MaxSem claimed this task.Sep 23 2017, 10:25 PM

Confirmed, this is caused by HTML5 sections, currently in cache population mode in WMF production. What's happening is that although the attributes are getting properly escaped, in 'html5' fragment mode $ is getting inserted verbatim, so Message::rawParams() later replaces $1 and $2 with HTML in attributes.

A reactive solution would be to replace $ with an entity in Linker::makeHeadline(), however this just highlights the danger of combining user-supplied data with message parameter substitution, so a more proactive solution in general might be needed. What do our security people think?

Bawolff added a subscriber: Bawolff.

There probably isn't a security issue here, but that misparsed HTML looks scary (similar to XSS issues I've seen), so let's make this private for now.

While I wasn't able to find any way to exploit the specific instance of this issue presented here, in the past similar issues regarding marker replacement inside attributes have definitely been exploitable, so I agree this bug should be private until fixed just in case.

Confirmed, this is caused by HTML5 sections, currently in cache population mode in WMF production. What's happening is that although the attributes are getting properly escaped, in 'html5' fragment mode $ is getting inserted verbatim, so Message::rawParams() later replaces $1 and $2 with HTML in attributes.
A reactive solution would be to replace $ with an entity in Linker::makeHeadline(), however this just highlights the danger of combining user-supplied data with message parameter substitution, so a more proactive solution in general might be needed. What do our security people think?

This reminds me a lot of the parser strip marker issue (7e4a134f49). In that issue, we changed replacement markers to include quote characters, so that if any of them end up in attributes, the attribute escaping would prevent parameter substitution. I think a similar approach would be best here to handle the issue generically, so that we know the issue is fully fixed.

To that end, I suggest a patch like:

Framawiki updated the task description. (Show Details)Sep 24 2017, 8:05 AM

@Bawolff, this patch fixes this particular issue, however it completely breaks e.g. Special:Log.

Hmm, replacing $ with &#36; in the patch fixes logs, however I suspect it will still break in escaped() mode - probably worth trying \1 (binary one) as it'll get normalized garbled from input by MW and thus should be impossible for attacker to inject.

Hmm no - parser garbles it too :P

@Bawolff, this patch fixes this particular issue, however it completely breaks e.g. Special:Log.

Good catch. This sort of replacement doesn't work with ->escaped() messages, since the entire thing is escaped so it stops all replacements, which is not what we want. Luckily its not really needed for any of the formats other than ->parse() and ->parseAsBlock().

Try #2 where we don't do parameter mangaling for ->escaped():

There is starting to be user feedback on frwiki.
Maybe we can temporary modify the local Mediawiki:Movepage-moved page and replace the h2 tag by pure wikitext? Is it okay to publicly edit this page ? Should we hide this edit ?
Perhaps the best thing is that a Staff account does it directly.

Its fine to publically edit mediawiki:movepage-moved as a temporary work around until this bug is fixed.

Note that the == == syntax for heading won't work either.

@Framawiki I suggest you change the h2 tags to big.

This patch appears to not break anything, I'll deploy it tomorrow. @Bawolff, what should be the disclosure? Since it's not exploitable, is it safe to push to Gerrit and backport?

Thats a good question. Its kind of a borderline case - there could be some other place in mediawiki where it is exploitable. Id prefer to keep it redacted until the next security release just in case.

I think that the patch causing the issue (non-URL-encoded HTML5 IDs) was not in any stable release yet, though?

I think that the patch causing the issue (non-URL-encoded HTML5 IDs) was not in any stable release yet, though?

I assume it would also apply to old wgExpermintalHtml5Ids which was something like mediawiki 1.16. But im not so worried about this specific example as the general issue. Presumably extensions might do things that are actually vulnerable (admittedly you have to have a pretty specific situation to exploit. The attacker needs to have a normal parameter that they can inject wikitext to and a rawParameter where they either have control of the value of the first attribute or can inject a " character.

MaxSem triaged this task as Normal priority.Oct 18 2017, 7:40 PM
MaxSem moved this task from Patch pending review to Pending release on the Security board.

AIUI this is the last task blocking 1.30? If this bug is only present in unreleased versions of MediaWiki can the patch be published?

demon added a subscriber: demon.Oct 26 2017, 3:45 PM

AIUI this is the last task blocking 1.30? If this bug is only present in unreleased versions of MediaWiki can the patch be published?

I think so. Sooner we get this in the branch the better.

MaxSem renamed this task from Incorrect render for `Movepage-moved` message to It's possible to mangle HTML via raw message parameter expansion.Nov 2 2017, 11:06 PM
Reedy added a subscriber: Reedy.Nov 3 2017, 12:02 AM

Are we going ahead with the patch as is then?

The problem is solved on frwiki as I can see. Can we change the view of this task ?

Reedy added a comment.Nov 3 2017, 2:49 PM

The problem is solved on frwiki as I can see. Can we change the view of this task ?

No, because the patch hasn't been made public yet. That will happen after it's released in the next set of security releases and the patches made public into the git repos. The task will be opened up after

Cherry pick applies cleanly 1.29, 1.30 and master

Looks like https://github.com/wikimedia/mediawiki/commit/b0784a8e964c4ad435b5e9bc88393a89dbabcf75 being missing from 1.28 causes a conflict...

I don't think we should worry about backporting that...

Can someone sanity check the 1.27/1.28 patches?

Krinkle removed a subscriber: Krinkle.Nov 13 2017, 1:40 AM

1.28 and 1.27 had a minor issue with a constant that wasn't yet introduced (I checked 1.29 too and it was fine). New versions:

Bawolff closed this task as Resolved.Nov 13 2017, 5:26 PM

mark as resolve as patches are backported and release will be soon.

Reedy changed the visibility from "Custom Policy" to "Public (No Login Required)".Nov 15 2017, 12:02 AM

Change 391421 had a related patch set uploaded (by Reedy; owner: Brian Wolff):
[mediawiki/core@REL1_30] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391421 merged by Reedy:
[mediawiki/core@REL1_30] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391413 merged by Ejegg:
[mediawiki/core@fundraising/REL1_27] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391451 had a related patch set uploaded (by Reedy; owner: Brian Wolff):
[mediawiki/core@master] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391451 merged by Reedy:
[mediawiki/core@master] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391720 had a related patch set uploaded (by Chad; owner: Brian Wolff):
[mediawiki/core@wmf/1.31.0-wmf.8] SECURITY: Ensure Message::rawParams can't lead to XSS

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

Change 391720 merged by jenkins-bot:
[mediawiki/core@wmf/1.31.0-wmf.8] SECURITY: Ensure Message::rawParams can't lead to XSS

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