In the GrowthExperiments extension, article extracts containing unsanitized user-provided content are inserted into the DOM as HTML, allowing for stored XSS by including a payload in an article.
Reproduction
Despite trying various methods for mocking suggested edits linked at https://www.mediawiki.org/wiki/Extension:GrowthExperiments/developer_setup#Suggested_Edits, I was unable to properly set up suggested edits in my development environment (partially due to aspects such as https://addlink-simple.toolforge.org being dead).
Therefore, the following POC requires modifying JS.
- Configure GrowthExperiments to pull data from enwiki:
$wgGENewcomerTasksConfigTitle = 'mw:Growth/Personalized_first_day/Newcomer_tasks/Prototype/templates/en.json'; $wgGENewcomerTasksRemoteApiUrl = 'https://en.wikipedia.org/w/api.php'; $wgGERestbaseUrl = 'https://en.wikipedia.org/api/rest_v1';
- Edit the modules/ext.growthExperiments.DataStore/GrowthTasksApi.js file (this line) and apply the following diff:
-const encodedTitle = formatTitle( title ); +const encodedTitle = 'Div_and_span';
This forces GrowthExperiments to always retrieve the extract from https://en.wikipedia.org/wiki/Div_and_span instead of the page shown in the edit suggestion.
- Make sure you have Special:Homepage enabled in your user preferences
- Go to Special:Homepage and make sure an edit suggestion is shown
The HTML tags in the extract in the edit suggestion cards are being interpreted as HTML by the browser:
Cause
GrowthExperiments retrieves an extract for the article from the Wikimedia REST API:
https://github.com/wikimedia/mediawiki-extensions-GrowthExperiments/blob/0bc0b3cd13aa4d6b46b051330289809b981e5e15/modules/ext.growthExperiments.DataStore/GrowthTasksApi.js#L298-L299
Later, the extract is inserted as HTML:
https://github.com/wikimedia/mediawiki-extensions-GrowthExperiments/blob/0bc0b3cd13aa4d6b46b051330289809b981e5e15/modules/ext.growthExperiments.Homepage.SuggestedEdits/EditCardWidget.js#L89
However, the "extract" field of the Wikimedia REST API does not return safe HTML (at least based on the fact that the POC works; I couldn't find documentation on the endpoint).
For the article I used as the example, the REST API returns the unescaped HTML tags from the article text:
https://en.wikipedia.org/api/rest_v1/page/summary/Div_and_span
