There are some characteristics in internet explorer that could aid
attackers when doing XSS attacks.

In IExplorer:
??script:
and
???script:
are translated to vbscript:
so, for example:
MYscript:msgbox("hi")
or
YOUscript:msgbox("hi")
will be treated as:
vbscript:msgbox("hi")
and anything with:
????script:
will be treated as:
javascript:
so..
somescript:alert("hi");
will be treated as:
javascript:alert("hi");

Well the problem is - it doesn't make sense to filter \w+: because it would rain false positives and i would have to give that rule very low impact. \w+script: is already included in current rules - what do you think? I guess it's okay if the IDS concentrates on the code afterwards.

@mario:
my klingon: joke was just pointing out that inside an event handler you don't need to specify any scheme (neither javascript: nor vbscript:), because the attribute isn't expected to be an URL but just raw script code.

In JavaScript, any non-reserved-keyword identifier sequence followed by colons (\w+:) is parsed as a label.
For instance,

outputs 1 and 3.
That's why onclick="javascript:someCode()" doesn't produce any error, even if it's plain useless and should be written just onclick="someCode()".

On the other hand, you still need to filter \w+script: as a potential XSS vector, because it's likely to be used as a proper URL, for instance in an iframe, a meta refresh or a Flash GetURL().

An example of attack which is conveniently detectable only if you're triggered by "javascript:" is http://sla.ckers.org/forum/read.php?11,13121

@ronald:
I'm not sure, what security advantage would I gain if src attribute was limited to a certain file extension (aside breaking many applications which dynamically generate included scripts and which don't/can't use URL rewriting, e.g. those relying on Struts validators)?
Once someone manages to (over)write a script tag, I'm pwned anyway, ain't I?

Also notice that the file extension doesn't mean that much over HTTP, where the MIME type is inferred looking at the "Content-Type" header.
So your examples are unlikely to work as they are, unless you've configured your web server to attach "Content-Type: text/javascript" to every random file or you're testing locally.

However, if you were impressed by those snippets, I bet you'll go crazy for the following:
<script type="text/javascript" src="data:text/javascript,alert(document.location)"></script>

It works with Opera and with Firefox (without NoScript - otherwise, it will be blocked even on trusted sites). IE7 doesn't support data: URLs.

QuoteIn JavaScript, any non-reserved-keyword identifier sequence followed by colons (\w+:) is parsed as a label.

I didn't know that - thx!

I knew that you can trigger execution by just creating a link like this: <a href="#" onclick="alert('hello')">Test</a> but I didn't know that even alphanumerical signs don't stress the parser - see above...

@mal:
the use of spidermonkey for validating is clever, you could trap when some properties like document.cookie, location, etc.. are accessed.

I sent today another mail to the php-ids group about the use of with:
with(document)location.href=cookie

the use of spidermonkey could stop any kind of way of accessing the properties.

<off topic>
I found today a filter that validates that the input is a valid url if it has: "://", in javascript, this would "comment-out" everything after the "//", anyway, there is the possibility to use:

javascript://anything%0d%0a--code-here--

this could be useful for anyone that finds another filter similar to this.
</off topic>

sirdarckcat Wrote:
-------------------------------------------------------
> I would like to add something.
>
> when you filter the functions "eval()", they are
> not really filtered, because, you can access them
> like this:
>
> window["eval"](--code-here--);
>
> any way, if the [""] is filtered, you can use:
>
> window](code-here)
>
> the use of window works for every function..
>
> Also you cant filter "window[" because, eval
> exists also in:
>
> any_function().eval()
>
> so I could use:
>
> unescape["eval"](--code--)
> open["eval"](--code--)
>
> Greetz!!

You don't even have to use the eval method, you can do something like:

var a = new Function("alert(1)");
a();

Or create a script element, and set the .text property of it, before attaching it to the DOM, and the .text script will be executed.

@ma1: This and all the others work in the JS console of firebug - so anywhere between script tags and combined with event handlers.

@all: I guess problem with Spidermonkey is first how to embed the engine in a PHP application and second the performance - I was thinking about a PHPJS parser engine too and there are already some approaches like this:

http://phpjs.berlios.de/

But those solutions aren't very mature plus you can't of courser acccess the browser and DOM objects - so it's pretty useless.

I still trust in the usage of regular expressions to detect JavaScript injections and I still see the pattern - whether if it's foo(bar), foo["bar"], foo().bar(), foo] or new Function foo("bar") - thing is one has to detect the function names combined with the matching special chars and delimiters. This should (almost) always lead to a successful match. I will customize the PHPIDS rules asap and hope that I didn't brag - if yes shame on me ;)

Anyway - I love this thread. It has changed my very view on JS in 24hrs...

I agree but not in particular Javascript, but for me how browsers handle c.q. parse it. This has always been a mystery to me why they allow sloppy coding. MSIE is king in allowing this for ages, Mozilla was way more stricter but even they bend a few rules lately.

I thought last year someone on the board said that a lot of stuff can be prevented with validation HTML, Don't know who it was, I thought Edward Z Yang. Anyway, that's kinda true in some sense, not recommended in coding, but in browsers themselfs. That is why I love XHTML and XML, mainly for their strictness.

3. a variation on your last theme which does work on Firefox and doesn't throw exceptions (Firefox doesn't seems to enumerate eval among window properties):
payload="javascript:alert(123)"; t=top;for(p in t)/^o.*n$/.test(p)&&(p=t[p])&&p(payload)

@.mario:
BTW, I don't manage to run this in Firebug either:
/*;alert(1)