Page MenuHomePhabricator

CVE-2024-34500: XSS through interface message in UnlinkedWikibase
Closed, ResolvedPublicSecurity

Description

This is a very minor issue since it requires elevated permission but error messages (in the $err var) are not escaped before being passed to Html::rawElement() in the getError() function in the Hooks class.

Affiliation: Miraheze/WikiTide Security reviewer

Details

Risk Rating
Low
Author Affiliation
Other (Please specify in description)

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

Thanks for raising this.

I'm not sure I'm understanding the data that will lead to raw HTML being inserted. The code in question is this:

$label = wfMessage( 'unlinkedwikibase-error-label' )->text();
$labelHtml = Html::element( 'strong', [], $label );
$err = wfMessage( $msg, $params )->text();
$out = Html::rawElement( 'span', [ 'class' => 'error' ], "$labelHtml $err" );
return [ 0 => $out, 'isHTML' => true ];

(The reason the next line is using rawElement() is that it's adding the strong label before the error message.)

When I test with $wgLanguageCode = 'x-xss'; there is no JS alert raised (but the alert() is shown in escaped HTML).

Anyway, I've updated ->text() to ->escaped(), so all should be fine once that patch is merged.

Mstyles changed the visibility from "Custom Policy" to "Public (No Login Required)".Feb 12 2024, 5:30 PM
Mstyles changed the edit policy from "Custom Policy" to "All Users".
Mstyles changed Risk Rating from N/A to Low.

When I test with $wgLanguageCode = 'x-xss'; there is no JS alert raised (but the alert() is shown in escaped HTML).

I don't think that tests parser output. In my testing, JS I inserted was rendered as given (but not executed due to the way in which it was inserted into the page). Anyway, thanks for the quick patch.

In my testing, JS I inserted was rendered as given (but not executed due to the way in which it was inserted into the page). Anyway, thanks for the quick patch.

Oh, I see: so you're saying that with the way that the messages are used now (in the parser function) there's no way to end up with any script inserted, but that if things were to change then they could? That makes sense.

Where were you inserting the JS to test? I've tried adding <script>alert('foo')</script> to the message, and the parameters, as well as with $wgLanguageCode = 'x-xss'; and ?uselang=x-xss, and can never get it to run any script. Which makes sense, because the output is always being returned to the parser and so it's just like adding <script> to a wiki page isn't it?

Not a security thing, but as an aside, you should probably be using ->inContentLanguage() if it ends up in the parser output (Or on newer mediawiki use $parser->msg() ). Otherwise the language of the error message might be random, as it will use the language of the user who viewed it last time the cache expired instead of the current user. [inContentLanguage of course prevents testing with ?uselang=x-xss]

Oh, I see: so you're saying that with the way that the messages are used now (in the parser function) there's no way to end up with any script inserted, but that if things were to change then they could? That makes sense.

Most likely what is happening is that due to parser cache, the request where you are including ?uselang=x-xss is different then the one where the page is being rendered. Often you would need to include that parameter in the POST request of the form submission, and not simply when viewing the page.

One way to test this sort of thing without fiddling with form parameters is going to a url like: https://mywebsite.com/wiki/index.php?action=edit&section=new&preview=yes&uselang=x-xss&preloadtitle=Put%20Wikitext%20here [However This will not work for any messages in the content language]

In my testing, JS I inserted was rendered as given (but not executed due to the way in which it was inserted into the page). Anyway, thanks for the quick patch.

Yeah, the script tag should be rendered but not executed. However, if you were to use <svg onload=alert('XSS')>, for example, it would work.

Where were you inserting the JS to test?

Through the en.json file.

because the output is always being returned to the parser and so it's just like adding <script> to a wiki page isn't it?

Unfortunately, no, parser output is still treated as raw HTML.

Regarding why it's not visible with uselang=x-xss, it should be because that doesn't actually mess with the messages in parser output unless there is something wrong with my MW config.

Samwilson claimed this task.

Thanks for the info, both of you.

Closing; I think there's nothing more to do here, and the bug is fixed.

Mstyles renamed this task from XSS through interface message in UnlinkedWikibase to CVE-2024-34500: XSS through interface message in UnlinkedWikibase.May 6 2024, 8:57 AM