I was looking for a NoScript detector, something that could tell me if the user has JS disabled in the Firefox preferences or by the NoScript plugin written by Maone, and found nothing. To repair this i wrote this trivial POC that is able to accomplish the task, it performs fingerprinting based on the behavior of the browser under the different possible conditions and is really reliable from the measurements done until now.
It operates in a "passive" way and is fully automatic, once the browser reach the detection page it's magically redirected to the proper results page. The working concept is that every layer you add can be detected and fingerprinted directly (think about service banners for example) or indirectly (it changes how the application/protocol performs) as this code does. It's "passive" because the browser choose on witch result page to land.
The POC is limited in its scope mainly for one reason: it can't be embedded in an existing page (eg: doesn't work in Iframes and Frames). Forgetting this it's the first in it's specie and a good start : ) I'm sure that this task can be accomplished in other ways and better, as like a friend of mine showed and asked to keep secret (damn grayhats).
NoScript tries to emulate some commodities to avoid excessive frustration to its users. For example it fix JavaScript links[1] (a link that has a JS href or an action in the onclick event) using regexprs so that the user can click the link and get the expected result [because who wrote the html/js of the page can't get it]. An other is to fix JS redirects[1], and this is the feature the POC (ab)uses.
In short: when a page has no body, isn't inside a frame/iframe and has something that match a specific regular expression inside the <script>
tags, the matched string is followed as it was a redirect.
Test yourself (the NoScript detector).
Click on the above to test the POC, don't forget to mail me errors, insults, suggestions, etc.
As you can see the whole detector is made of 3 static files: detect.html, the one with the magic and the two landing pages noscript.html and js.html.
<html> <style> html { padding: 10px; } html:before { content: 'You have JS off without NoScript or JS off with whis domain allowed in NoScript.'; } </style> <script> a = 1; switch(a) { /* NoScript will follow this */ case 0:top.location.href = 'noscript.html'; } </script> <script> /* JS will follow this */ eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('2.1=\'0.3\';',4,4,'js|location|document|html'.split('|'),0,{})) </script> </html>
Since NoScript doesn't parse the JS code (obvious) and simply use a regexpr (the function is detectJSRedirects in components/noscriptService.js for the curious) it's possible to get a statement that is never true for a legit parser but match the expression.
const findURL = /(?:(?:\b(?:open|replace)\s*\(|(?:\b(?:href|location|src|path|pathname|search) |(?:[Pp]ath|UR[IL]|[uU]r[il]))\s*=)\s*['"]|['"](?=https?:\/\/\w|\w* [\.\/\?]))([\?\/\.a-z][^\s'"]*)/g;
The variables in play are: NoScript installed or not, Web site allowed or not and JS globally enabled or not. This POC detect them as explained in the following chart (X menas "YES, its recognized"):
NoScript installed .--------+------------------+----------------------. | | allow (NS off) | !allow (NS on) | +--------+------------------+----------------------+ | JS on | X (*2) | X (*1) | +--------+------------------+----------------------+ | JS off | X (*3) | X (*1) | '--------+------------------+----------------------' NoScript not installed .--------+--------. | JS on | X (*2) | +--------+--------+ | JS off | X (*3) | '--------+--------'
*1) Firefox will require noscript.html. Means that you have NoScript installed with ush.it as untrusted website. This happens regardless JS is globally ON or OFF.
*2) Firefox will require js.html. Means that JS is executed. This happens with JS globally ON and NoScript not present or ush.it as a trusted site.
*3) Firefox won't require a file. Means that JS is off and NoScript is not present or is present with ush.it as a trusted site.
[1] pref("noscript.fixLinks", true);
[2] pref("noscript.jsredirectIgnore", false); pref("noscript.jsredirectFollow", true); pref("noscript.jsredirectForceShow", false);