It could be called a feature, but it can make problems and resulting in fatal or html injection:
Where it happens?
When starting to edit a new section on a wiki page or starting to create a new page, it is possible to use a preload= parameter in the url to fill in the text area with the content of that page. With the url parameter preloadparams it is possible to replace placeholder like $1 in that text. That is done using the Message::class. When providing an internal array structure of Message as parameter the replaced placeholder is formatted for that.
The text
*First parameter is $1 *Second parameter is $2 *Third parameter is $3
is processed to
*First parameter is 22:00, 19 October 2022 *Second parameter is 19,284 d 22 h 0 min 0 s *Third parameter is valid
It is possible to use everything message supports, even lists formatted with pipes
*First parameter is item1 | item2 *Second parameter is $2 *Third parameter is $3
The Problem
All the magic is done in Message::extractParam where the multi dim arrays from $_GET are given too. When looking there it also possible to produce type errors (Message::formatListParam needs an array as second argument) or fatals when $obj->__toString() is called with a string.
Examples to get type error:
To get exception
- https://www.mediawiki.org/w/index.php?title=Special:MyPage&action=edit&preload=Manual%3ACreating_pages_with_preloaded_text%2Fparam_demo&preloadparams%5Bobject%5D%5B0%5D=oncreatingsecuritybug§ion=new
- https://www.mediawiki.org/w/index.php?title=Special:MyPage&action=edit&preload=Manual%3ACreating_pages_with_preloaded_text%2Fparam_demo&preloadparams%5Bdatetime%5D%5B0%5D=oncreatingsecuritybug§ion=new
The security issue I found is when using the list with an invalid type, because Message::formatListParam calls a trigger_error with the unescaped message key. The message key in this case is the whole wikitext of the preloaded page. When the preloaded page contains some script-tags, the raw script tag is now part of the html when the php setting display_errors is on, which is not true for wmf wikis, but possible for third parties. Feel free to review this fact and possible make this public, if not an issue (Better safe than sorry from my point of view)
To see that:
- Create a Page "PreloadUnsafe" with content "Argument: $1 <script>alert('XSS');</script>"
- Put ini_set( 'display_errors', 1 ); into LocalSettings
- Open index.php?action=edit§ion=new&preload=PreloadUnsafe&preloadparams%5Blist%5D%5B0%5D=item1&preloadparams%5Blist%5D%5B1%5D=item2&preloadparams%5Btype%5D=invalid and enjoy
- Getting as raw html:
<b>Warning</b>: trigger: Invalid list type for message "Argument: $1 <script>alert('XSS');</script>": invalid (params are a:2:{i:0;s:5:"item1";i:1;s:5:"item2";}) in <b>includes\language\Message.php</b> on line <b>1529</b>
A solution would be to reject multi-dim arrays in WebRequest::getArray/getIntArray, that would fix all pages with possible problems using arrays, it should fix T321133 as well. I was reviewing the patch set there and found the issue reported here. But that would also break the "feature" of formatted arguments on preload, but that sounds acceptable.