There are injection scenarios with correct filtering for each HTML context that may have a couple of conditions which allows a successful XSS exploitation. This is done using interesting tricks that will transcend the filter blocking capabilities.
In a regular HTML source code we have 3 contexts for reflection:
1) among tags
2) inside a tag
3) in a script section
For each context, a correct filter have to be applied.
The following code available live here will be used for demonstration of the technique. It applies the following filters (PHP), one for each context:
1) preg_replace(“/\<script|=/i”, “-“, $_REQUEST[‘q’]);
2) preg_replace(“/on\w+\s*=|\>/i”, “-“, $_REQUEST[‘q’]);
3) htmlspecialchars($_REQUEST[‘q’], ENT_QUOTES);
As we can see, the 1st filter prevents any use of the script tag (<script), the only one that can execute javascript code without the need of an equal sign, also replaced by a “-” in this context. The 2nd one, due to be an input of the type hidden, is more tolerant allowing the injection of anything but the tag closing (>) and any event handler (on\w+\s*=), both replaced by a “-” again. The 3rd encodes the input to be reflected on the javascript section, leaving no room for breaking out of the single quotes.
So this page can be exploited? Aside from making use of some weird and old version specific tricks on Microsoft’s Internet Explorer and an attack with the need of high user interaction (both in the end of this post), there are 2 interesting solutions with XML based tags, the ones with built-in support in the HTML5 parser.
We can’t use event handlers. In the previous post, XSS Without Event Handlers, we can see a list of possible candidates to execution. There we can see the <math> tag being used with <brute, as a sign that it is an arbitrary tag (so it can be almost anything).
<math><brute href=javascript:alert(1)>
It can’t be used fully in the 1st context because the “=” is being filtered. But we can split it, because the equal sign is tolerated in the second filter.
1) <math>
2) ” href=javascript:alert(1)
So we have <math> in the 1st filter (which pass unchanged) and href=javascript:alert(1) (discarding the tag and adding double quotes) in the second.
But what about the native code between these 2 reflection places?
As we already saw in the post Source-Breaking Injections, we can break the source, making a part of the code “disappear”. Our goal here is not only to invalidate the code between the reflections but also “jump” to bring them together as close as possible.
Using an HTML comment, this is achieved:
1) <math><!–
2) ” href=javascript:alert(1)
And then we land close to our next reflection which is inside an input field of the hidden type. But in the presence of a <math> before it, it becomes a regular tag that can be used to trigger an href.
<math><!–” href=javascript:alert(1)//
or
” href=javascript:alert(1) <math><!–
In order to make it more appealing to a click, the payload for an attack could be:
lol video<!–“href=javascript:alert(1) style=font-size:50px;
display:block;color:transparent;
background:url(‘//brutelogic.com.br/webgun/img/youtube1.jpg’);
background-repeat:no-repeat –><math><!–
Interesting enough, it still relies on UI (user interaction) and works only in Mozilla’s Firefox web browser. The next one is much more impressive: it does not need UI and also works on latest Google’s Chrome.
The other XML based tag with built-in support in the HTML5 parser is <svg>. Although much more powerful than <math> regarding XSS exploitation, <svg> can’t be used with the 2nd filter in the same way for a XSS in this scenario.
So here comes the 3rd filter. Designed to prevent exploitation in the javascript section, perfect on its own, it falls victim of a similar trick:
<svg><!–‘-alert(1)-‘
or
‘-alert(1)-‘<svg><!–
This happens because the <svg> tag makes the next <script> block be parsed even with chars encoded as HTML entities, hence the breaking out of the native variable value and “concatenation” of the alert function.
What about the native code between <svg> and alert(1)? As the page was carefully crafted to demonstrate this technique, the tags between these 2 are known to be innocuous to this payload construction. We just need to make the first jump, to avoid the <p> tags which would not let this work.
Unfortunately, none of the above solutions were enough to bypass Microsoft’s latest XSS filters (IE and Edge). This last one, the most promising because of the absence of the easily flagged “javascript:” string, has the needed bypass for IE messed by the page filter: “alert%26lpar;1)” becomes “alert&lpar;1)” in source.
Alternative Solutions
It was pointed out by @httpsonly that it’s possible to XSS in IE version 6 up to 9 using the %00 char to evade the <script regex pattern. There are more bypasses involving these ancient browser versions but it’s worth to note that the filters were designed to prevent XSS in modern browsers. The real unintended bypass came from @asdizzle_ who was able to XSS it with high user interaction in the following way:
” accesskey=x onclick=alert(1) 1=’
It needs pressing of ALT+SHIFT+X keys to trigger the alert and it’s only possible in this scenario because of the technique described here.
#hack2learn
[…] There are injection scenarios with correct filtering for each HTML context that may have a couple of conditions which allows a successful XSS exploitation. This is done using interesting tricks that will transcend the filter blocking capabilities. […]
Really amazing~thank you for sharing