Let's say we have <span></span>. Our website takes the value of a query parameter and adds it between the tags so we have <span>Hello!</span>.

If we sanitize the parameter by replacing < with &lt; and > with &gt, is XSS still possible in the case where the untrusted data is inserted between HTML tags?

I have seen example of various odd encoding working but not in modern browsers

  • Voting to close because this is a specific CTF question, and questions asking us to break the security of a specific system are off-topic here. – Polynomial Apr 20 '16 at 15:56
  • I would say no, it's not possible (maybe in combination with other vulnerabilities, eg the encoding issue Polynomial mentioned, but I would say that that is very limited). But when you say "With that said, if I place an apostophe as the value, nothing is shown" it seems that the encoding of < and > isn't the only thing happening. You need to figure out what is actually happening to bypass it. – tim Apr 20 '16 at 16:06

If you only filter for script tags, yes.

For example:

<img src="x" onerror="alert(1)" />


<div style="position: absolute; top: 0; left: 0; width: 9999px; height: 9999px; z-index: 9999" onmouseenter="alert(1)"></div>

Or an infinite number of other vectors.

You need to properly filter the entire contents when you write them out to the page, using whatever encoding function is appropriate for the output encoding (e.g. HTML, XML, JSON, etc.) and available in the language you're using.

Examples for various languages:

I also recommend reading the XSS Prevention Cheat Sheet.

EDIT: After your update, yes, this is still possible.

Imagine you filter < and >, but then put content in an attribute:

<span class="$class">

I can then use this payload:

" style="display: block; position: absolute; top: 0; left: 0; width: 9999px; height: 9999px; z-index: 9999" onmouseenter="alert(1)" foo="

This turns your span into a block element which fills the entire page, executing the onmouseenter event as soon as the user's mouse enters the page.

Ok, so you're still not convinced.

People have spent a LOT of time making XSS work in all sorts of simple filter-based environments. The number of tricks is astounding, getting into all sorts of madness like tricking the browser to misinterpret the page as having a different character encoding so that UTF-8 or other Unicode codepoints sent as input later get treated as distinct ASCII codepoints containing HTML-affecting characters like > or ".

As an example, let's say you're using UTF-8 as your character set on your server. I put the 㱁 character into your page, but then through various tricks (this is browser dependent and complicated, but can be achieved trivially if you've got a header-splitting bug on your server) trick your browser into assuming the encoding is simple ASCII. The UTF-8 codepoint for 㱁 is U+3C41, which when interpreted as ASCII is simply <A. Your browser sees this as the opening of a tag.

Example payload:

㱁 href="x" style="display: block; ..." onmouseenter="alert(1)"㸠foo

The huge number of pitfalls makes it impossible to handle yourself. You need a proper XSS filtering library which is encoding-aware to take these issues into account.

| improve this answer | |
  • 1
    That would just deliver: <span>&lt;img src=&quot;x&quot; onerror=&quot;alert(1)&quot; /&gt;</span>. The < and > characters are being encoded. Sorry - made it more clear in an edit. – pee2pee Apr 20 '16 at 15:32
  • @pee2pee Right, which is why I said "if you only filter for script tags". Your question wasn't clear as to which approach you were actually taking. But, realistically, you need to filter for a number of characters (at least ><"&'/). Triangle bracket fitlering alone won't help you if you echo content into an attribute, for example. As the XSS Prevention Cheat Sheet I linked you says, you need a proper secure encoding library. – Polynomial Apr 20 '16 at 15:34
  • Yes sorry - I updated the question. Will encoding do the trick? – pee2pee Apr 20 '16 at 15:35
  • @pee2pee No. See my edit. – Polynomial Apr 20 '16 at 15:37
  • 1
    @pee2pee Added more info. TL;DR - you cannot possibly handle all possible exploit cases, get a proper filter library. – Polynomial Apr 20 '16 at 15:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.