Page MenuHomePhabricator

XSS issue in Extension:PageForms (CVE-2021-31551)
Closed, ResolvedPublicSecurity

Description

As the lead developer and security person of the Liquipedia wiki farm, I got a security report about an XSS issue in Extension:PageForms.

I have put a minified test case on the SemanticMediaWiki sandbox here https://sandbox.semantic-mediawiki.org/wiki/Spécial:RunQuery/Tokens, as this combination with Semantic MediaWiki is how it has been reported to me.
The issue can be seen by posting something like <img/src=="x onerror=alert(1)//"> into the input field, or by going to a url like https://sandbox.semantic-mediawiki.org/wiki/Sp%C3%A9cial:RunQuery/Tokens?title=Sp%C3%A9cial%3ARunQuery%2FTokens&pfRunQueryFormName=Tokens&Tokens+test[capital][]=%3Cimg/src==%22x%20onerror=alert(1)//%22%3E&Tokens+test[capital][is_list]=1&pf_free_text=&wpRunQuery=Run+query which provides the form parameter as a url GET parameter.

This bug has been reported to us by Gilang Romadon

If you need any more information, feel free to message me or post into the bug, I hope the example use-case will help.

Best Regards
Alex Winkler

Event Timeline

Yaron_Koren claimed this task.

Sorry about that problem! I just checked in a fix for it.

Thank you for working on this. The patch you merged seems to fix the issue with passing it in as a url parameter, it seems to leave open the option of self XSS-ing by putting the string into the search box though. I don't know if this is something that is important to fix, but it mightbe nice.

Can you give an example of how to replicate this?

When going to https://sandbox.semantic-mediawiki.org/wiki/Sp%C3%A9cial:RunQuery/Tokens and putting <img/src=="x onerror=alert(1)//"> into the box, the code also gets executed.

I am aware that this is essentially self harming as this is about similar to pasting things into the console of your developer tools, however there are good reasons why companies like facebook display huge warnings there not to do such things. In the interest of protecting non-technical users this might still be a nice thing to do.

2020-08-04 01-30-43.png (608×1 px, 46 KB)

Okay, I see... this one is less of a big deal, as you point out, and it might be harder to fix. But it's good to know about this problem - thanks.

I'm back, because I realized that your fix works in 1.34, but does not seem to work in 1.31.8.

In the older version I still run into this issue.

Are you sure about that? That doesn't make any sense.

So the above (T259433#6378990) was obnoxious to figure out, but I think I know what's going on. Basically, select2's default escapeMarkup function (which should work at least ok at sanitizing) is being overriden by an odd old/cached copy within ext.pf.select2.tokens.js. Note that the escapeMarkup function override in 4.9.5 is:

function (m) { return m; };

But if you go to the liquidpedia.net url above and open up a javascript debugger, you can see this version within ext.pf.select2.tokens.js loaded via RL:

opts.escapeMarkup = function(m) {
    return m.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;');
}

Playing around in Chrome's debugger:

Screen Shot 2020-08-19 at 5.01.15 PM.png (58×629 px, 20 KB)

or with the following snippet in Node:

var testStr = "<!--<img%20src=\"--><img%20src=x%20onerror=alert(1)//\">"
console.log( testStr.replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;') );

the same generated html (as produced by select2 during various DOM manipulations) occurs, as the chained replace functions only perform one round of replacement on the angle brackets, and thus do not sanitize any proceeding, arbitrary html. This is why the img tag is rendered and the resultant onerror handler fires. I had a quick look through PageForms' git history but couldn't find where this change was introduced, so I'm not entirely sure how or why it's there on liquidpedia.net.

I think substituting replaceAll with replace would probably work as well, which can take a regex or a string for the search.

However this isn't the problem on your dev server. The escapeMarkup override of function (m) { return m; }; present within both ext.pf.select2.tokens.js's and ext.pf.select2.comboboxjs's setOptions definition simply return the variable m, unsanitized. I still believe the culprit is the override within ext.pf.select2.tokens.js as it is present within ext.pf.select2.comboboxjs for the original sandbox.semantic-mediawiki.org example within the task description but not within ext.pf.select2.tokens.js, and that issue appears resolved. I think this makes sense given the presence of the pfTokens css class within the relevant rendered multi-selection form input. But this could be an issue for any select2 elements which are (perhaps unintentionally) referencing config from ext.pf.select2.tokens.js or ext.pf.select2.comboboxjs.

Is this still an issue in Page Forms? It's not clear to me from all the discussion what the actual problem is.

As far as I can see, there is still an issue here, as I can still create URL parameters that are XSS exploitable

@Yaron_Koren - yes, both ext.pf.select2.tokens.js and ext.pf.select2.combobox.js are JS libraries for the PageForms extension. Given the minimal doc/comments, these appear to be helper libs for form input autocompletion for the two respective select2 form input types. The problem is that both appear to be overriding select2's Utils.escapeMarkup function in certain scenarios with what is basically a noop function: function (m) { return m; }. This facilitates XSSes in certain cases. The liquipedia.net issue appears related to a fork of ext.pf.select2.tokens.js on their end, as it does not ever appear to be a part of PageForms' git history (that I could find). But the current versions of ext.pf.select2.tokens.js and ext.pf.select2.combobox.js found in PageViews 4.9.5 should likely be fixed to either remove the override of Utils.escapeMarkup within their setOptions functions (here and here) or find some other way for those not to override the essential security functionality of Utils.escapeMarkup.

The liquipedia.net issue appears related to a fork of ext.pf.select2.tokens.js on their end, as it does not ever appear to be a part of PageForms' git history

I also had the issue in a pristine version on my dev though. That one has the noop version function (m) { return m; } that you mentionned.

I also had the issue in a pristine version on my dev though. That one has the noop version function (m) { return m; } that you mentionned.

Correct. function (m) { return m; } doesn't effectively sanitize either. In fact it does nothing and I'm not sure why it exists within the token and combobox autocomplete helper libraries. Although there also seems to be an issue with the fix in rEPFM1b67fc6ced342237efe227af2ccab9a93272c88a. That seems to work on parameter values which have the is_list value defined and are of that type. That's what fixed the original sandbox.semantic-mediawiki.org issue within the task description. But within the other examples, Find+images[person] does not have an is_list value set, and is likely bypassing the relevant sanitization code within includes/PF_FormPrinter.php. That code is pretty convoluted and I'm not very familiar with it, but I believe the remaining issues could be addressed in two ways: 1) stop overriding Utils.escapeMarkup for the token and combobox select2 elements or 2) determine every parameter value's path through includes/PF_FormPrinter.php and ensure they are being sanitized by htmlentities (likely with the ENT_QUOTES flag enabled) or similar.

I just checked in the following change to Page Forms, which hopefully takes care of the URL query string vulnerability:

https://phabricator.wikimedia.org/rEPFM4ac1f9d4371974c823225da7273ddf2ce9b89dfd

I'm not aware of any more XSS issues with "combobox" or "tokens", but if there still are any, please let me know.

That page shows up fine for me, with the query string value properly escaped. Are you still seeing the problem?

At least in Firefox I am still seeing it. I've been wondering if I had a cached version of some script, but I've tried this on multiple PCs now

Yes, I see that same problem with Firefox. Which is very strange. Do you know if that new code I added to PF_FormField.php is getting called, on your wiki?

I added a call to error_log() like so

if ( !$form_submitted && $field_query_val != '' ) {
        error_log ("PageForms Test");
        if ( is_array( $field_query_val ) ) {
                $str = PFFormPrinter::getStringFromPassedInArray( $field_query_val, $delimiter );
        } else {
                $str = $field_query_val;
        }
        return htmlspecialchars( $str, ENT_QUOTES );

}

but to no avail. The error log stays empty when calling the URL as shown above.

@FO-nTTaX - I believe I've now checked in a fix for this problem; it escapes any HTML while still doing bolding on the results:

https://phabricator.wikimedia.org/rEPFM3d9d2fc601fdf690ef1b685b59448cc3ce32bfb4

Sorry that it took this long to fix... hopefully this fix works.

No worries, sometimes things take time, and that's ok. Thank you for your work on this :)

@FO-nTTaX - if you can confirm that the recent commit addresses the remaining issues on the wikis you've been testing, I think we can resolve this task, make it public and track it for the next supplemental security announcement (T270466). Thanks.

I've pulled this onto our wiki and as far as I can see it, it should be fine now. Again thank you for working on this :)

sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".
sbassett changed the edit policy from "Custom Policy" to "All Users".

I've pulled this onto our wiki and as far as I can see it, it should be fine now. Again thank you for working on this :)

Great, thanks. I've now made this task public and will include this issue within the next supplemental security announcement.

Change 658612 had a related patch set uploaded (by RhinosF1; owner: Yaron Koren):
[mediawiki/extensions/PageForms@REL1_35] Improve HTML-escaping in combobox and tokens inputs

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

Change 658613 had a related patch set uploaded (by RhinosF1; owner: Yaron Koren):
[mediawiki/extensions/PageForms@REL1_35] Add escaping of array query string params

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

Change 658613 merged by jenkins-bot:
[mediawiki/extensions/PageForms@REL1_35] Add escaping of array query string params

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

Change 658612 merged by jenkins-bot:
[mediawiki/extensions/PageForms@REL1_35] Improve HTML-escaping in combobox and tokens inputs

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

sbassett renamed this task from XSS issue in Extension:PageForms to XSS issue in Extension:PageForms (CVE-2021-31551).Apr 23 2021, 6:55 PM