Reliable Browser Detection

September 18, 2006 at 7:52 pm (Browsers)

Browser detection is nothing new and has been used since the beginning of the internet .. usually because web pages may display fine in one browser, but horribly deformed in another. There are many reasons you may want to know exactly what browser the user is viewing the site with, and even more ways of determining it. The typical ways are by reading the information that browsers supply in their navigator object: userAgent, vendor, appName, etc. The problem with these methods is that they’re easily spoofable, many Opera users are identified as using Internet Explorer, for example.

Now, for determining what percentage of readers use each browser to read this blog, it’s not really a big deal if 1 in 50 is miscounted. But when the time comes for the next XSS Warhol Worm .. if it needs different browsers to run a different script, a couple bad detections early on can drastically slow its propogation speed. Reliable browser detection is worth incorporating for these cases.. Ideally, finding something that is not spoofable ahead of time will suffice. Just about every detection method can be fooled using a GreaseMonkey script or an intelligent proxy to return false data to the worm, but only after they know what the worm’s source is. Since the goal is just to have it execute once, it doesn’t matter if they can trick subsequent executions.

No two browsers interpret unperfect html in exactly the same way (aside from Netscape running its IE6 replica – as far as i can tell). What’s more, is that the same browsers of different versions can interpret the same html differently. I noticed this when viewing the source of a page rendered in Netscape in Firefox mode. It turns code like this:

<SCRIPT src=”http://ha.ckers.org/xss.js?&#8221; <B>

into:

<SCRIPT src=”http://ha.ckers.org/xss.js?&#8221; ><B>

Netscape automatically inserts the closing bracket, so its Gecko rendering engine can display it properly.. The great thing about this auto correction is that when you read the html on a page using javascript, it reads the corrected version, not the original. Why is this useful..? Well, there’s no standard on how one should autocorrect some of the more funky malformed HTML.. After some playing around, I found this simple break tag: <br a/>. In each of the different browsers it gets adjusted four different ways.

Firefox and Netscape in FF mode: <br a=””>
IE6, IE7, and Netscape in IE mode: <BR a>
Opera 8.54: <BR a/=””/>
Opera 9: <BR a=””/>
This is just one of an infinite number of examples which get translated differently, so there really is no way to block them all ahead of time. -and i’m not sure anyone would care to. But for browser detection you can count on, it’s like a candy store.

Telling the difference between Opera 8 and 9 is nice and all (and FF vs IE) .. but trying to discern between FF/IE6 and it’s Netscape clone is a whole nother beast.

This code returns differently for FF and Netscape in FF mode:

<span id=”cspan”></span>
document.getElementById(‘cspan’).innerHTML = “<br a/s> “;

Based on the way Netscape handles a space after an HTML tag inserted.

In Firefox: <b a/s=””> </b>
Netscape: <b a/s=””></b>

I keep hearing how IE7 will be standards compliant for CSS, something IE6 fails miserably at, so it’s quite easy to tell the two apart. On my quest to find special CSS differences, I came across atest you web developers have probably seen long ago, the ACID2 test which is a litmus test of many CSS2 special cases. Check it out in every browser, and it will likely look drastically different – all except IE6 and Netscape in IE mode which are identical in their failures >.< (Note – Opera 9 is the only one i saw that passes, although Safari should as well)

In Summary, I’ve given up on discerning between Netscape in IE, and IE6 .. except using the easily spoofable navigator.userAgent testing. For the rest, i’ll be compiling my own litmus test for browsers(link currently down) which you can try out for yourself. It’s made as modular as possible.. so pick your favorite one or two to use.

Permalink 2 Comments