Filter Bypass Procedure

When dealing with filters, we need to determine how it is filtering our input in order to find a successful bypass technique.

Again we will work only with the event based payloads (on*=), because they represent more than 99% of all possible XSS payload constructions.

So, if we already can inject the tag part like “<anything”, we can simply set it as something with the minimum amount of chars like “<x” and start to test for the event handlers accepted.

That’s what I tried to summarize in this tweet (regarding WAFs – Web Application Firewalls):

The filter may be using a regex (regular expression) that flags a minimum number of chars after the “on” prefix and/or blacklists the known event handlers. If it does the latter, exclusively, there’s a great chance that they have missed one, and it will be just a matter of trying all of them.

But usually we have to test for how many chars it accepts after the “on” string, followed by a “=” sign. For this we will use the following pseudo-payload:

<x onxxx=1

If it accepts it, we start to increase the number of X’s one by one, until we get a filter blocking.


<x onxxx=1     -> pass

<x onxxxx=1   -> pass

<x onxxxxx=1 -> block

From there we will have the maximum number of chars (6 in our example) that we can use to choose an event handler: the webGun tool has its event handlers list separated by number of chars to help on this task.

Event handlers with up to 6 chars:

oncut, onblur, oncopy, ondrag, ondrop, onhelp, onload, onplay, onshow

So the next step is just trying all event handlers allowed based on that number of chars; after finding one that does not get blocked, change the “<x” tag to one associated with it (no need if it’s one of the agnostic event handlers).

But if it does not accept the pseudo-payload above without blocking, with just 3 chars after “on”, it’s because we can’t inject even the shortest event handler so far, oncut.

In this case we will need to move to the following tricks to try to break the filter:

1) Encoding

Encoding one or more key chars of the payload can be really tricky:

%3Cx onxxx=1

<%78 onxxx=1

<x %6Fnxxx=1

<x o%6Exxx=1

<x on%78xx=1

<x onxxx%3D1

2) Mixed Case

Using uppercase in one or more chars may trick some poor filters:

<X onxxx=1

<x ONxxx=1

<x OnXxx=1

<X OnXxx=1

3) Doubling

Maybe the filter only looks for one occurrence of the pattern:

<x onxxx=1 onxxx=1

4) Spacers

The following spacers can be used between the tag name and the event handler:







5) Quotes

We may try to fool the filter with a quote before the handler using a tag pseudo-attribute:

<x 1=‘1’onxxx=1

<x 1=“1”onxxx=1

6) Mimetism

The filter flow may allow us to pass a rule being disguised by allowed stuff:

<x </onxxx=1 (mimics a closing tag)

<x 1=“>” onxxx=1 (mimics a text outside of the tag)

<http://onxxx%3D1/ (mimics an URL)

7) Combo

We may combine some or all of the above:


When we find a way to make it work, all we need is to add the javascript code, which also has its own obfuscation tricks in case of it’s being filtering too.


7 thoughts on “Filter Bypass Procedure

  1. Hi i today saw your blog and it really very nice. I am beginner in xss and in web development.I saw webgun site of your and i want to know how you build it?
    I also want to build like that on my localhost so that i learn and practice from my self.Please guide me

    • Thanks. The core of webGun is its database, which is available exclusively online. You can create your own with some PHP + MySQL skills if you want, but you will have to put together all the same info.

  2. Hahaha 😀

    Sorry in my above comment the tags were not reflecting in the comments on your website. So, let me put it in this way…. What is “Less than” and “Greater than” tags get filtered? How can we bypass this?

    • We can’t bypass always, sometimes it’s just being coded in the right and safe way. Usually when < is filtered we can't do much (except in inline and javascript injections).

Leave a Reply