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
- check alternative encodings:
: isn't allowed, but
: 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
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<scr.pt>pt>. So maybe
i is only substituted in
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: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
: 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
[*] And you even contradict yourself a bit; if
<script> becomes a blank space, and
., 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:
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: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.
script, and also
You can see that the first one only fails because of a rule you haven't mentioned: the
But now to a solution that does work. For level two:
on attribute that isn't
ondblclick. There are a lot, for example
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:
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.