Aim
===
To see if it's possible to execute arbitrary client-side JavaScript,
using MediaWiki as the delivery system.
Background
==========
To execute arbitrary JavaScript, we mostly need to find a way to get
MediaWiki to allow us to open a tag ("<script"), and to close a tag
(">"). In particular, we need some form of wiki input text that will
produce this as the rendered HTML output.
The MediaWiki parser seems to try to prevent both of these things, by
escaping "<" and ">" characters. For example, if you give it wiki
input like this:
---------------------------------------------------------
<"hello world">
---------------------------------------------------------
Then you get back this HTML:
---------------------------------------------------------
<"hello world">
---------------------------------------------------------
However, the parser is not perfect. There are some inputs that will
give unescaped ">" or "<" back.
The trick is probably to combine these omissions together, in such a
way so as to produce a working exploit. I don't have such a thing yet,
but I suspect it might be possible.
Unescaped Closing tags
======================
Getting the parser to give unescaped closing tags is much easier than
finding unescaped opening tags.
For example, a wiki input of just this:
---------------------------------------------------------
>>>>>>>
---------------------------------------------------------
Will give this HTML output:
---------------------------------------------------------
>>>>>>>
---------------------------------------------------------
(i.e. no escaping).
However, if we try to open one or more tags beforehand, then that
changes. So this wiki input:
---------------------------------------------------------
<
>>>>>>>
---------------------------------------------------------
Gives this HTML output:
---------------------------------------------------------
<
>>>>>>>
---------------------------------------------------------
So in other words, we can do this (close a tag and provide some
JavaScript to be executed), provided we don't use the "<" character:
---------------------------------------------------------
onmouseover="alert(document.cookie)">test
---------------------------------------------------------
... and we will get that literal text back in the HTML.
So to sum up: Any time after we use a "<" character, we lose this
privilege of having unescaped ">" characters.
To me, this feels like it might perhaps be a mistake, because it
allows an attacker an opening that they probably don't need to be
given (i.e. it's a free kick).
Unescaped Opening tags
======================
Almost all uses of "<" in the wiki input will result in "<" in the
HTML output.
However there are some uses that do not. In particular, I've found
that table properties are very weakly restricted, and we can get the
Parser to produce unescaped "<" characters with each of the following
3 inputs:
---------------------------------------------------------
{| WIDTH=[[image:ftp://~
{| ALIGN='''~~~</math>
{| BGCOLOR=<span style="font-weight: bold;">
---------------------------------------------------------
Which will give this HTML output:
---------------------------------------------------------
<table width="[[image:<a" class="external free" title="ftp://~">
<table align="<b><!--LINK">
<table bgcolor="<span">
---------------------------------------------------------
Some observations / problems here:
1) The unescaped "<" characters are in attribute strings. We need
somehow to avoid that, or break out of that, if the browser is to obey
them.
2) The type of the tags is limited ("<a>", "<!--" and "<span>" tags in
the above examples).
3) The final two examples that use "<" will mean that we cannot close
the tag (because, as described above, by using the "<" character we
lose the privilege of having close tags).
However we can avoid problem 3) with this, which never uses a "<" character:
---------------------------------------------------------
{| WIDTH=[[image:ftp://~
onmouseover="alert(document.cookie)">test
---------------------------------------------------------
Which will give this HTML output:
---------------------------------------------------------
<table width="[[image:<a" class="external free" title="ftp://~">
onmouseover="alert(document.cookie)">test
---------------------------------------------------------
... however this still has problems 1) and 2) described above.
Problem 2) may not necessarily be a showstopper (e.g. HTML like: '<a
href="#" onmouseover="alert(document.cookie);">Free Porn!</a>' is not
as powerful as something that successfully uses "onLoad", but it is
predictable that it will work a reasonable percentage of the time).
On the other hand, problem 1) is currently a huge restriction.
Conclusions
===========
* If anyone knows of a way of overcoming problems 1) and 2), or of an
alternate method, then please let me know. By combining that
information with the information above, it may well be possible to
create a working Proof-Of-Concept.
* Why does MediaWiki ever allow unescaped ">" characters? This
behaviour seem to increase the chances of a JavaScript security
problem.
All the best,
Nick.