Dear WikiMedia Security Team,
We are researchers from CISPA, and as a part of one of our projects, we found that the wiki pages in wikibooks.org could be affected by DOM Clobbering. Our current understanding is that the posed risk is small. However, we would like to support you to mitigate the issue.
DOM Clobbering
DOM Clobbering is a type of attack where attackers confuse a web application by injecting HTML elements whose named properties (e.g., id/name) collide with the name of JavaScript variables and overshadow their value. For example, a p tag with id=x can clobber the variable x when injected to the DOM tree (e.g., see here for more details).
Security Risk in WikiBooks
Description: We found that the text editor used in wikibooks.org which allows users to create wiki pages and posts does not sanitize the named properties, particularly id and data-* when creating posts for several HTML tags. The complete list of tags follows, but we start with one example.
Example URL: https://en.wikibooks.org/w/index.php?title=User:XYZ&action=submit
Example Payload: The payload test<sup id=QUnit> clobbers the variable window.QUnit, which is used in multiple locations in the code as a part of a conditional check if(window.QUnit){ [...] }. This can result in client-side DoS, or simply breakage of other client-side functionalities due to triggering JS parsing issues.
Steps to Reproduce:
1- Acting as the attacker, open the example URL above.
2- insert the example payload
3- Click the Show Preview button (An attacker would click publish here to persistent the payload to the DOM tree).
4- Now you are viewing the preview page; open the browser console and see that the markup triggered JS breakage (In an attack, the victim would be affected when visiting the published wiki)
Suggested Patch:
- To mitigate the risk of DOM Clobbering, named attributes, particularly id and data-* attributes for the case of WikiBooks should be prefixed with a constant string to ensure namespace isolation. For example, <p id=x> should be changed to <p id=user-content-x>.
- A similar patch has been deployed in other HTML sanitizers, see, e.g, DOMPurify.
Complete List of Unsanitized Tags: The following tags allow an attacker to clobber a variable x or window.x, and x.dataset.y or window.x.dataset.y if an attacker creates a wiki post using them.
- <div id=x data-y=z>
- <p id=x data-y=z>
- <span id=x data-y=z>
- <b id=x data-y=z>
- <i id=x data-y=z>
- <s id=x data-y=z>
- <br id=x data-y=z>
- <data id=x data-y=z>
- <dd id=x data-y=z>
- <del id=x data-y=z>
- <dfn id=x data-y=z>
- <dl id=x data-y=z>
- <dt id=x data-y=z>
- <em id=x data-y=z>
- <font id=x data-y=z>
- <h1 id=x data-y=z>
- <hr id=x data-y=z>
- <li id=x data-y=z>
- <mark id=x data-y=z>
- <ol id=x data-y=z>
- <pre id=x data-y=z>
- <q id=x data-y=z>
- <rb id=x data-y=z>
- <rp id=x data-y=z>
- <kbd id=x data-y=z>
- <bdi id=x data-y=z>
- <bdo id=x data-y=z>
- <big id=x data-y=z>
- <blockquote id=x data-y=z>
- <center id=x data-y=z>
- <cite id=x data-y=z>
- <code id=x data-y=z>
- <rtc id=x data-y=z>
- <ruby id=x data-y=z>
- <s id=x data-y=z>
- <samp id=x data-y=z>
- <strike id=x data-y=z>
- <sup id=x data-y=z>
Notes for Your Reference: We found several sensitive sinks/instructions that we initially assumed to be exploitable for XSS, but further manual checks showed that they are not, because the text editor correctly prevents multi-level DOM Clobbering through the name property (i.e., it deletes that attribute). However, for your reference, we listed them here:
Case 1:
- script: https://en.wikibooks.org/w/extensions/TemplateWizard/resources/ext.TemplateWizard.Dialog.js
- code: window.open( mw.TemplateWizard.Dialog.static.helpUrl );
- an attacker clobbering mv may be able to achieve XSS by setting the parameter of window.open() to javascript:alert(1). However, this is currently not possible.
Case 2:
- script: https://en.wikibooks.org/w/resources/lib/ooui/oojs-ui-windows.js
- code: $( OO.ui.getTeleportTarget() ).append( OO.ui.windowManager.$element )
- Similarly, to example above, clobbering OO introduces the risk of XSS. However, this is currently not possible.
Case 3:
- script: link
- code: $(OO.ui.getTeleportTarget()).append(OO.ui.$defaultOverlay);
- Similarly to previous examples. Exploitation not currently possible.
Complete list of DOM Clobbering sources: We found that the way the code defines the following variables could introduce the risk of DOM Clobbering (e.g., x = window.x || {}) However, these should not be exploitable assuming proper sanitization by the text editor. However, we listed them here for future reference.
- Example Webpage: https://meta.wikimedia.org/wiki/Main_Page/en-gb
- "window.QUnit",
- "window.pg",
- "window.NORLQ",
- "window.RLCONF",
- "window.RLSTATE",
- "window.RLPAGEMODULES",
- "window.RLQ",
- "mw.uls",
- "OO.Registry",
- "OO.ui.PopupWidget",
- "mw.Api",
- "Geo.country",
- "Geo.country_code",
- "OO.ui.DropdownInputWidget",
- "OO.ui.CheckboxInputWidget",
- "OO.ui.FieldLayout",
- "window.ve",
- "window.ve.init.editingSessionId",
- "OO.ui.WindowManager",
- "OO.ui.ToolFactory",
- "OO.ui.ToolGroupFactory",
- "OO.ui.Toolbar",
- "OO.EmitterList",
- "window.WebKitMutationObserver",
- "window.MozMutationObserver",
- "mw.language.getFallbackLanguageChain",
- "mw.msg",
- "window.wpAvailableLanguages",
- "wpAvailableLanguages.lang",
- "OO.ui.ButtonWidget",
- "OO.ui.mixin.PendingElement",
- "OO.ui.Keys.ESCAPE",
- "OO.ui.Keys.ENTER",
- "OO.ui.LabelWidget",
- "OO.ui.PanelLayout",
- "OO.ui.windowManager",
- "OO.ui.TextInputWidget",
- "OO.ui.mixin.GroupElement",
- "OO.ui.Widget",
- "OO.ui.mixin.IconElement",
- "OO.ui.mixin.FlaggedElement",
- "OO.ui.mixin.TabIndexedElement",
- "OO.Factory",
- "OO.ui.mixin.PopupElement",
- "OO.ui.mixin.IndicatorElement",
- "OO.ui.mixin.LabelElement",
- "OO.ui.mixin.TitledElement",
- "OO.ui.mixin.ClippableElement",
- "OO.ui.mixin.FloatableElement",
- "OO.ui.IconWidget"
If you have any further questions, please do not hesitate to contact me (soheil.khodayari@cispa.de).
Best,
Soheil