I'm stuck in the XSS part of the security shephard OWASP app. I am not looking for someone to tell me the solution, I just need to learn how to find it myself, I'm a bit rusty on XSS. So what I know so far.

  • it will substitute the char "i" and I for "."
  • it will remove "<script>" for a blank space
  • will substitute ":" for a "!"
  • it will substitute also "on" so any onload etc will be showing load instead etc.

So filter is not what I was used to years a go, I have try many things but can't seen to find a way to bypass it.. but there has to be a way this is why is in the challenge... Curiosity is killing me here.. :/ Any tips will be welcome and hopefully help other people in the future.

  • 2
    If it substitutes i for . then the order of checks may come into play e.g. <scr.pt> may end up being <script> after filtering. Or if, it only does one pass <scri<script>pt> would also become <script>. Apr 20, 2016 at 0:50
  • hello and thanks! I just tried very quick, and looks like the first option no luck still rendering with the . and the second option no luck neither.. the output is <scri<scr.pt>pt> so keeps doing the substitution. Apr 20, 2016 at 1:08
  • 2
    @puzzlepalace your first example doesn't really make sense. i is substituted for ., but not the other way around, so why would <scr.pt> become <script>?
    – tim
    Apr 20, 2016 at 10:09

1 Answer 1


My answer got longer than expected, so just to give you the answer: <body onpageshow="alert(1)"> probably works, and if it doesn't, <body onpaonpageonpagonpageonpageshowshoweshowshowgeshow="alert(1)"> will.

How to try to bypass a custom filter

You say you try to learn how to do is yourself, so here are some first steps I would take:

  • check case: not all filters are case sensitive. Is I also substituted, or just i?
  • check alternative encodings: : isn't allowed, but &#58; may be (and it works the same in most contexts).
  • check what the filter is actually doing. Are replacements always done, or only in certain contexts (eg is i always filtered, or only in script, or only surrounded by characters, or ...)? Are filters only applied once (eg <scri<script>pt> becomes <script>)?

The last point is the most complex one. For example, you say that i is always substituted for .. But then in the comments, you say that <scri<script>pt> becomes <scri<scr.pt>pt>. So maybe i is only substituted in script?

You also said that on is filtered. Are you sure? Or are only some of the specific event attributes filtered? Have you tried onFooBar? If it is filtered, all on attributes will be filtered. But if not, some might bypass the filter. If so, you should especially try the new HTM5 ones, some of which are often forgotten. Here is a list of event attributes to check.

What might work in your case

You weren't specific enough with your rules[*] to give a definite answer, but here are some ideas:

  • <meta http-equIv="refresh" content="0;url=data&#58;text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="> will work if the i filter is not case sensitive (less likely), or if it only applies to script (which seems to be the case in your example). Note that &#58; will work in place of :.
  • if the i filter is indeed not case sensitive, quite a lot of payloads might work: <scrIpt src=http://localhost/s.js></scrIpt> (doesn't contain <script>), <a href="javascrIpt&#58;alert(1)">click</a>, etc.

[*] And you even contradict yourself a bit; if <script> becomes a blank space, and i becomes ., then why does <scri<script>pt> lead to <scri<scr.pt>pt>, instead of <scr. pt>, which would match your rules?

What the actual filter is in your case

The XSS filters can be seen here.

From your filter description, you are at level two (or possibly level three). The filter is:

  • script becomes sc.pt
  • onclick becomes o.ick
  • onmouseover becomes o.ver
  • onload becomes o.oad
  • onerror becomes o.err
  • ondblclick becomes o.dbl
  • & becomes !
  • : becomes !

Or alternatively for level three, the same, except the on filters are a bit less bad.

What payloads will bypass these filters

Now that we have a proper description of the filters, we can easily bypass them.

But first of, the bypasses that will actually not work:

  • <meta http-equiv="refresh" content="0;url=data&#58;text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">: will not work. i is not actually always replaced with . (which makes sense, as such a filter would destroy all actual input), but we can't use &, and thus can't use a data URL.
  • <a href="javascript&#58;alert(1)">click</a>: problem with script, and also &.

You can see that the first one only fails because of a rule you haven't mentioned: the & replace.

But now to a solution that does work. For level two:

  • any on attribute that isn't onclick, onmouseover, onload, onerror, or ondblclick. There are a lot, for example <body onpageshow="alert(1)">.

For level three, the trick is that there are a lot more on attributes filters (I didn't check if it's all), but they are replaced by nothing (four times). That means that if you include the keyword in itself five times, you bypass the filter:

  • <body onpaonpageonpagonpageonpageshowshoweshowshowgeshow="alert(1)">


Your description of the filter is inconsistent and incomplete, so you cannot get the answer based on it.

When testing a filter such as this, you should try as many corner cases around the rules you defined as possible, so you get a description of the filter that is as close to reality as possible.

Then it is just a matter of finding the correct payload to bypass these rules.

  • Awesome! this is exactly what I needed, I had number 2 is number 3 the one i'm stuck, unfortunately your solutions above did no work but that is ok.. I was not really looking for the actual solution, you nail it with the description that is what I am looking for. and you are right sorry I wrote the post from work and was not in front of my notes, so forgot about & and other details sorry. Going to follow up on your logic see if I can find the result myself.. I appreciate your explanation a lot. cheers. Apr 21, 2016 at 4:01
  • Funny thing is that following your tips of including the keyword on itself it wont show error, nor any substitution but also just blank... wont render on the page so the actual XSS won't happen.. there has to be something else going on. i'll post if I find out. actually it is.. I just open it on zap and I get "<h2 class='title'>Search Results</h2><p>Sorry but there were no results found that related to <body onpageshow="alert(1)"></p>" but something else is blocking it from showing on my browser. here is a screenshot tiikoni.com/tis/view/?id=f354454 Apr 21, 2016 at 4:44
  • 3
    I GOT IT!! :) <META onpaonpageonpagonpageonpageshowshoweshowshowgeshow="alert(1)"; BTW thanks! I am not sure if you put the answer wrong to give me a tip and make me look more into the working of the filter, but regardless, I appreciate that I had to give it some thought to get it right. Apr 21, 2016 at 5:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .