Page MenuHomePhabricator

Don’t use raw HTML messages in safe mode
Open, LowPublicSecurity

Description

As a MediaWiki power user, I expect that I can use safe mode (?safemode=1 in the URL, or user preference) to be protected from any potential malicious on-wiki content that’s under the control of the interface admins. However, raw HTML messages are currently not affected by safe mode, so they can still let an interface admin attack a user who is using safe mode. I propose that in safe mode we should try to make raw HTML messages safe, e.g. by running them through the sanitizer, or by not using the on-wiki messages at all (and falling back to the JSON files). This should probably be implemented in Message, checking whether the message key is in $wgRawHtmlMessages.

Steps to reproduce on your local wiki (preferably don’t try this out on any public wiki):

  • In LocalSettings.php, set $wgRightsPage, $wgRightsUrl and/or $wgRightsText to nonempty strings, so that a copyright message will be shown
  • Load a page with ?uselang=qqx to see which copyright message is being shown (default copyright, but may be e.g. wikimedia-copyright if WikimediaMessages is installed)
  • Override that message in the MediaWiki namespace to include something like <span onmouseover="alert('hi!')">Hover me for an alert!</span>
  • Load a page with ?safemode=1 and hover over that text in the copyright footer

Expected result: no effect. Actual result: alert is shown.

Event Timeline

I consider this more a feature request than a bug, but I’m filing it as a security issue out of caution. (Though it was motivated by a public discussion in #mediawiki-core.)

safemode is by no means a general security mechanism. Right now it is related to a single component: ResourceLoader, and exists to unload any user-generated CSS and JS. We intended this as a debugging tool, not a security tool. I.e. launch in safemode and see if a problem happens there, too. As a way to quickly determine whether something is caused by a site style or user script.

I'm neutral on expanding its definition, but I do want to point out that it might cause this connotation to spread and thus create a false sense of security.

If we decide to expand its meaning to do something with interface messages, I suggest we limit it specifically to disabling $wgAllowRawHtmlCopyrightMessages only.

Disabling the MediaWiki-namespace more generally, through a public query parameter in production, would likely have far-reaching consequences that would cause their own security problems, if not at least the basis for very deceptive or phishing-like permalinks.

Interface messages are one of the primary building blocks through which communities define what things are, and how important or risky concepts and parts of the site are in context. Consider e.g. "Don't use your prod password" notices on beta cluster's login form. I'm sure there are better examples that I can't think of right now. Then we have messages as configuration ther would actually affect server-side acceptence and validation of what a user is allowed to do, which, if disabled would reduce security instead of increase it:

  • Spam-blacklist
  • Titleblacklist
  • Domain denylist (MediaWiki:BlockedExternalDomains.json)
  • Bad image list
  • etc

If safemode were to e.g. set Message->useDatabase() = false by default, it would alter business logic and revert security restrictions back to the default for those requests.

Besides potential security risks, it would at the very least poison various caches because it globally and implicilty varies code behaviour in a way no caller anticipated or controlled. The wgAllowRawHtmlCopyrightMessages feature is new enough and limited enough in scope (it relates to 3 interface messages) that we can easily audit and make sure aren't cached.

mmartorana changed Risk Rating from N/A to Low.

IMHO this would be pointless if restricted to $wgAllowRawHtmlCopyrightMessages, as there are other raw messages. $wgRawHtmlMessages is still a small set of messages, but only about half of them are copyright-related.

lucaswerkmeister-wmde@deploy2002 ~ $ mw-debug-repl enwiki
Becoming root...
Finding a mw-debug pod in codfw...
Now running shell.php for enwiki inside pod/mw-debug.codfw.pinkunicorn-5f46bd87b8-h8rlb on release pinkunicorn...
Psy Shell v0.12.3 (PHP 7.4.33 — cli) by Justin Hileman
> $wgRawHtmlMessages
= [
    "gadgets-definition",
    "wikimedia-copyright",
    "mediawiki.org-copyright",
    "wikimedia-commons-copyright",
    "wikidata-copyright",
    "wikifunctions-site-footer-copyright",
    "mobile-frontend-categories-add-heading",
    "mobile-frontend-categories-add-wait",
    "mobile-frontend-categories-heading",
    "mobile-frontend-changeslist-nocomment",
    "mobile-frontend-copyright",
    "mobile-frontend-editor-editing-page",
    "mobile-frontend-editor-previewing-page",
    "mobile-frontend-editor-summary",
    "mobile-frontend-editor-summary-request",
    "mobile-frontend-editor-wait",
    "copyright",
    "history_copyright",
    "googlesearch",
  ]

(gadgets-definition is apparently only marked as raw to get the same protection level [“kind of abusing the raw HTML message feature”], but I’ll be very surprised if it’s actually ever shown to users as HTML. googlesearch is AFAICT unreachable in production because we don’t set $wgDisableTextSearch = true. I haven’t looked into the MobileFrontend messages yet.)

@Lucas_Werkmeister_WMDE - Is this more about the convenience of having a query param to disable certain messages or is it more about trying to expand the security posture of safemode as @Krinkle alluded to? The former would likely have a simple solution, but I'd probably agree that, if it were to be implemented, it should never be enabled in Wikimedia production.

@Lucas_Werkmeister_WMDE - Is this more about the convenience of having a query param to disable certain messages or is it more about trying to expand the security posture of safemode as @Krinkle alluded to? The former would likely have a simple solution, but I'd probably agree that, if it were to be implemented, it should never be enabled in Wikimedia production.

Can you clarify what you “agree … should never be enabled in Wikimedia production”? Because I feel like part of @Krinkle’s comment argues against something that I didn’t propose in the first place, and I’m worried that my proposal is being misunderstood. (It’s fine to point out that it would be a bad idea to disable e.g. spam-blacklist, but that’s just making a note of something we all agree on, not something we need to argue over.)

To answer your question, I guess it is about trying to expand the security posture of safemode, except that I wasn’t aware that it’s not considered a security feature. Honestly I still don’t find that totally convincing – the name “safe mode” doesn’t sound like a debugging feature at all, and “Users don't trust interface administrators (of a wiki on a wiki farm, etc.)” was also cited as a use case in T342347, when the persistent preference was introduced. Manual:Safemode documents a known “hole” in the mode, but that doesn’t apply in Wikimedia production as we don’t set $wgAllowSiteCSSOnRestrictedPages. So, while I can understand the concern about changing the connotation of the mode to some extent, I also feel like that ship might have sailed already.

I feel like safemode would be difficult to use as a security feature. Its not sticky, users would have to manually type in the url of every page. edit: appearently this is a user preference now, which maybe changes things with regards to how much it makes sense as a security feature.

the name “safe mode” doesn’t sound like a debugging feature at all,

"Safe mode" is a commonly used name for a debugging feature where user custom stuff is disabled. Most famously as a windows boot option.

Also this seems more like a feature request than a security issue. Maybe this should be made public so a broader group can comment on it.

Also this seems more like a feature request than a security issue. Maybe this should be made public so a broader group can comment on it.

Happy to make this public if @Lucas_Werkmeister_WMDE is fine with that.

In theory since T45646: "MediaWiki:Copyright" message allows raw HTML we haven't been using most of these messages in Wikimedia production. $wgAllowRawHtmlCopyrightMessages (already false) should disable all the copyright-related ones (in favor of wikimedia-copyright-footer etc) except the MobileFrontend one which is not raw HTML anymore (fe15e9c776). googlesearch is unreachable. gadgets-definition is irrelevant. That leaves the various non-copyright mobile-frontend-* messages. Probably we can just fix those?

A related thought I had today: do we disable raw HTML messages on Special:UserLogin and related pages? Because not loading user or site scripts on those special pages is a security feature, I believe (we don’t want to let interface admins steal user’s passwords).

As far as I can tell, this is currently only a theoretical issue (so I’m only leaving a comment here rather than filing a separate task). The copyright footer is not shown on Special:UserLogin, nor (as far as I can tell) on any other page that has JS disabled; the other raw messages also don’t look like they would appear on any such special page. Maybe we should still make some changes there (to protect against a hypothetical extension which calls both $outputPage->disallowUserJs() and $outputPage->setCopyright( true ), or shows some other raw HTML message on a disallowed-user-JS page), but it doesn’t sound like it’s urgent.

HTML in copyright messages is a legacy feature at this point. I don't think it makes sense to expend any effort on sanitizing it when security-conscious installations can just disable it.
(We should probably make it default to disabled in the next release, though.)

Raw HTML messages not listed in T377222#10241289 but found by codesearch:

  • stopforumspam-is-blocked (20bb7d1d - seems wrong? the message is not actually HTML)
  • donate_interface-otherways (it's a Wikimedia-specific extension, only used on a very locked down wiki, so probably fine? still, seems easy to replace)
  • wikibasemediainfo-time-timestamp-formatted (96e5a07e - no good reason for it to use raw HTML)

That leaves the various non-copyright mobile-frontend-* messages. Probably we can just fix those?

messages, usage.
Other than maybe a tiny performance impact, I don't think there is any benefit to these being raw HTML. The actual messages are either plain text or wikitext-compatible HTML.

The copyright footer is not shown on Special:UserLogin, nor (as far as I can tell) on any other page that has JS disabled;

Its not shown on special pages in genneral. The idea being that special pages are not user content so not copyright by the users.

The whole blocking js on just a single page is kind of a trying to stick toothpaste back in the tube sort of situation. Im not sure it would be effective except against very unsophisticated attackers.

  • stopforumspam-is-blocked (20bb7d1d - seems wrong? the message is not actually HTML)

It still has <strong> tags and is parsed due to the wikitext links. I guess one could argue that the <strong> tags are superfluous.

It still has <strong> tags and is parsed due to the wikitext links. I guess one could argue that the <strong> tags are superfluous.

But it's parsed so it's safe HTML, not raw HTML.

mmartorana changed the visibility from "Custom Policy" to "Public (No Login Required)".Oct 31 2024, 3:12 PM

It still has <strong> tags and is parsed due to the wikitext links. I guess one could argue that the <strong> tags are superfluous.

But it's parsed so it's safe HTML, not raw HTML.

Ok, then yes, it can be removed. Let me get a patch up.

Change #1085432 had a related patch set uploaded (by SBassett; author: SBassett):

[mediawiki/extensions/StopForumSpam@master] Remove stopforumspam-is-blocked message from RawHtmlMessages array

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

Change #1085432 merged by jenkins-bot:

[mediawiki/extensions/StopForumSpam@master] Remove stopforumspam-is-blocked message from RawHtmlMessages array

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

Change #1090551 had a related patch set uploaded (by Gergő Tisza; author: Gergő Tisza):

[mediawiki/extensions/WikibaseMediaInfo@master] Avoid unnecessary use of RawHtmlMessages

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

Change #1090551 merged by jenkins-bot:

[mediawiki/extensions/WikibaseMediaInfo@master] Avoid unnecessary use of RawHtmlMessages

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