Total Recall On Firefox.

What a great movie! a classic yes, but cool anyway.

Today we are going to investigate the level of privacy in Firefox. Many underestimate the power of reconnaissance, while it is such an important tool in tracking possible attackers. In security reconnaissance is of great importance, because successful exploitation of a system can only be ensured if the attacker can't be located or can't be traced back. For me, working with Firefox gives me zero privacy and zero anonymity. Even when I can surf through proxies or the tor onion network, Firefox gives it all away. I talked about it many times, and Mozilla seems to ignore the wish for privacy and better anonymity by many surfers. Basically it is impossible to hide your tracks. This will be an example of how we can abuse the browsers features to track attackers or regular surfers. The problem is the inner workings of Firefox. Last year I gave away a method where one can retrieve almost any plugin file inside Firefox. It is important to understand that while these are public open source files, they can be used to de-anonymize someone, or track someone.

Total Recall consists out of two scripts. One HTML file and one XML file that tries to retrieve the chrome DTD files from extensions plus additional user settings in the browser. It then calculates a unique hash sum upon that info. The importance of this is, is that we can basically create unique hashes and correlate the client through it. In combination with cookies, IP checks and this hash sum we can store all data inside a database and perform analysis upon them. Imagine you visit my website verbatim, without any anonymization. This moment I can track your IP, which we can store. Then I could calculate a hash sum of all variables I want to analyze. Next time when you visit my website and you are using a proxy or simply a Tor route, I could correlate you to the fingerprint you left the first time: the hash sum. This can get very complex, but theoretically it would mean that anonymization and privacy are not possible in the Firefox client.

In the XML file I check for fifteen DTD files, the source has around 30. For the sake of brevity we could load in every possible DTD file, but this isn't important now. I do like you to understand that it is just a matter of time to retrieve all DTD files and attach them to our program. The DTD XML execution is lightning fast, faster than the Javascript we additionally put into it, that checks basic browser configuration settings like screen size and OS version which might not be very consistent 'as-is' but I put it in for you to try.

I hope you like it, if you have more ideas or comments; drop me an e-mail. I'm always interested in your ideas.

Total Recall XML file:

<!DOCTYPE window [


<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">


%brandDTD;


<!ENTITY brandDTD "null">





<!ENTITY % noscriptDTD SYSTEM "chrome://noscript/locale/noscript.dtd">


%noscriptDTD;


<!ENTITY noscriptPlugins "null">





<!ENTITY % creditsDTD SYSTEM "chrome://browser/locale/credits.dtd">


%creditsDTD;


<!ENTITY brandMotto "null">





<!ENTITY % cs_settingsDTD SYSTEM "chrome://cachestatus/locale/cs_settings.dtd">


%cs_settingsDTD;


<!ENTITY presence.label "null">





<!ENTITY % ChromeListOverlayDTD SYSTEM "chrome://chromelist/locale/ChromeListOverlay.dtd">


%ChromeListOverlayDTD;


<!ENTITY chromelist.menu "null">





<!ENTITY % downbartextDTD SYSTEM "chrome://downbar/locale/downbartext.dtd">


%downbartextDTD;


<!ENTITY pTitle.label "null">





<!ENTITY % pref-fasterfoxDTD SYSTEM "chrome://fasterfox/locale/pref-fasterfox.dtd">


%pref-fasterfoxDTD;


<!ENTITY prefetching.tab "null">





<!ENTITY % firebugDTD SYSTEM "chrome://firebug/locale/firebug.dtd">


%firebugDTD;


<!ENTITY firebug.Firebug "null">





<!ENTITY % foxyproxyDTD SYSTEM "chrome://foxyproxy/locale/foxyproxy.dtd">


%foxyproxyDTD;


<!ENTITY foxyproxy.label "null">





<!ENTITY % ocspDTD SYSTEM "chrome://mozapps/locale/preferences/ocsp.dtd">


%ocspDTD;


<!ENTITY certOCSP.label "null">





<!ENTITY % aboutDTD SYSTEM "chrome://reporter/locale/about.dtd">


%aboutDTD;


<!ENTITY thanks.text "null">





<!ENTITY % tamperdataDTD SYSTEM "chrome://tamperdata/locale/tamperdata.dtd">


%tamperdataDTD;


<!ENTITY tamperdata.toolbar.startTamper "null">





<!ENTITY % entitiesDTD SYSTEM "chrome://trashmail/locale/entities.dtd">


%entitiesDTD;


<!ENTITY trashmail.title "null">





<!ENTITY % useragentswitcherDTD SYSTEM "chrome://useragentswitcher/locale/useragentswitcher.dtd">


%useragentswitcherDTD;


<!ENTITY useragentswitcher.name "null">





<!ENTITY % aboutDTD SYSTEM "chrome://simpledelicious/locale/about.dtd">


%aboutDTD;


<!ENTITY extName.label "null">





<!ENTITY % autosavetexttocookieDTD SYSTEM "chrome://autosavetexttocookie/locale/autosavetexttocookie.dtd">


%autosavetexttocookieDTD;


<!ENTITY autosavetexttocookie.label "null">





<!ENTITY % ieviewOverlayDTD SYSTEM "chrome://safariview/locale/ieviewOverlay.dtd">


%ieviewOverlayDTD;


<!ENTITY toolbarbutton.label "null">





<!ENTITY % igsidebarDTD SYSTEM "chrome://igsidebar/locale/igsidebar.dtd">


%igsidebarDTD;


<!ENTITY igsidebar.title "null">





<!ENTITY % keyscramblerDTD SYSTEM "chrome://keyscrambler/locale/keyscrambler.dtd">


%keyscramblerDTD;


<!ENTITY keyscrambler.label "null">





<!ENTITY % overlayDTD SYSTEM "chrome://firephish/locale/overlay.dtd">


%overlayDTD;


<!ENTITY firephish "null">





<!ENTITY % quickrestartDTD SYSTEM "chrome://quickrestart/locale/quickrestart.dtd">


%quickrestartDTD;


<!ENTITY menu.tools.item.restart "null">





<!ENTITY % simplemailDTD SYSTEM "chrome://simplemail/locale/simplemail.dtd">


%simplemailDTD;


<!ENTITY sendBySimpleMail "null">





<!ENTITY % sqlitemanagerDTD SYSTEM "chrome://sqlitemanager/locale/sqlitemanager.dtd">


%sqlitemanagerDTD;


<!ENTITY window.title "null">





<!ENTITY % passhash-optionsDTD SYSTEM "chrome://passwordhasher/locale/passhash-options.dtd">


%passhash-optionsDTD;


<!ENTITY pshOpt.title "null">


]>





<body>


<x1>&brandShortName;</x1>


<x2>&brandMotto;</x2>


<x3>&noscriptPlugins;</x3>


<x4>&presence.label;</x4>


<x5>&chromelist.menu;</x5>


<x6>&pTitle.label;</x6>


<x7>&prefetching.tab;</x7>


<x8>&firebug.Firebug;</x8>


<x9>&foxyproxy.label;</x9>


<x10>&certOCSP.label;</x10>


<x11>&thanks.text;</x11>


<x12>&tamperdata.toolbar.startTamper;</x12>


<x13>&trashmail.title;</x13>


<x14>&useragentswitcher.name;</x14>


<x15>&extName.label;</x15>


</body>

Total Recall HTML file:

<html xmlns="http://www.w3.org/1999/xhtml">


<head>


<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


<title>TOTAL RECALL</title>


<script>





var tapped='';





call_xml = document.implementation.createDocument('','',null);


call_xml.async = false;


call_xml.load("total_recall.xml");





for(i=1;i<15;++i) {





tapped += call_xml.getElementsByTagName("x"+i)[0].childNodes[0].nodeValue +'|';


}





function recon() {


globals = '';


globals += this.navigator.javaEnabled() + '|';


globals += this.navigator.taintEnabled() + '|';


globals += this.navigator.userAgent + '|';


globals += this.navigator.appMinorVersion + '|';


globals += this.navigator.appVersion + '|';


globals += this.navigator.appName + '|';


globals += this.screen.width + '|';


globals += this.screen.height + '|';


globals += this.screen.availWidth + '|';


globals += this.screen.availHeight + '|';


globals += this.screen.colorDepth + '|';


globals += this.screen.pixelDepth + '|';


globals += this.screen.bufferDepth + '|';


globals += this.navigator.mimeTypes.length + '|';


globals += this.navigator.platform + '|';


globals += this.navigator.cpuClass + '|';


globals += this.navigator.language + '|';


globals += this.navigator.browserLanguage + '|';


globals += this.navigator.systemLanguage + '|';


globals += this.navigator.userLanguage + '|';


globals += this.navigator.cookieEnabled + '|';


globals += this.navigator.userProfile + '|';


return globals;


}


rr = recon();





function total_recall_firefox() {





alert('Computed hashsum: ' + x_recall(rr+tapped));





document.write(tapped.replace(/|/gim,'<br />'));


document.write(rr.replace(/|/gim,'<br />'));


}





function recall_md5(x,len){


x[len>>5] |= 0x80<<((len) % 32);


x[(((len+64) >>> 9)<<4)+14]=len;


var a= 1732584193; var b=-271733879; var c=-1732584194; var d= 271733878;


for(var i=0; i < x.length; i += 16){ var olda=a; var oldb=b; var oldc=c; var oldd=d;


a=x_ff(a,b,c,d,x[i+ 0],7 ,-680876936); d=x_ff(d,a,b,c,x[i+ 1],12,-389564586);


c=x_ff(c,d,a,b,x[i+ 2],17, 606105819); b=x_ff(b,c,d,a,x[i+ 3],22,-1044525330);


a=x_ff(a,b,c,d,x[i+ 4],7 ,-176418897); d=x_ff(d,a,b,c,x[i+ 5],12, 1200080426);


c=x_ff(c,d,a,b,x[i+ 6],17,-1473231341); b=x_ff(b,c,d,a,x[i+ 7],22,-45705983);


a=x_ff(a,b,c,d,x[i+ 8],7 , 1770035416); d=x_ff(d,a,b,c,x[i+ 9],12,-1958414417);


c=x_ff(c,d,a,b,x[i+10],17,-42063); b=x_ff(b,c,d,a,x[i+11],22,-1990404162);


a=x_ff(a,b,c,d,x[i+12],7 , 1804603682); d=x_ff(d,a,b,c,x[i+13],12,-40341101);


c=x_ff(c,d,a,b,x[i+14],17,-1502002290); b=x_ff(b,c,d,a,x[i+15],22, 1236535329);


a=x_gg(a,b,c,d,x[i+ 1],5 ,-165796510); d=x_gg(d,a,b,c,x[i+ 6],9 ,-1069501632);


c=x_gg(c,d,a,b,x[i+11],14, 643717713); b=x_gg(b,c,d,a,x[i+ 0],20,-373897302);


a=x_gg(a,b,c,d,x[i+ 5],5 ,-701558691); d=x_gg(d,a,b,c,x[i+10],9 , 38016083);


c=x_gg(c,d,a,b,x[i+15],14,-660478335); b=x_gg(b,c,d,a,x[i+ 4],20,-405537848);


a=x_gg(a,b,c,d,x[i+ 9],5 , 568446438); d=x_gg(d,a,b,c,x[i+14],9 ,-1019803690);


c=x_gg(c,d,a,b,x[i+ 3],14,-187363961); b=x_gg(b,c,d,a,x[i+ 8],20, 1163531501);


a=x_gg(a,b,c,d,x[i+13],5 ,-1444681467); d=x_gg(d,a,b,c,x[i+ 2],9 ,-51403784);


c=x_gg(c,d,a,b,x[i+ 7],14, 1735328473); b=x_gg(b,c,d,a,x[i+12],20,-1926607734);


a=x_hh(a,b,c,d,x[i+ 5],4 ,-378558); d=x_hh(d,a,b,c,x[i+ 8],11,-2022574463);


c=x_hh(c,d,a,b,x[i+11],16, 1839030562); b=x_hh(b,c,d,a,x[i+14],23,-35309556);


a=x_hh(a,b,c,d,x[i+ 1],4 ,-1530992060); d=x_hh(d,a,b,c,x[i+ 4],11, 1272893353);


c=x_hh(c,d,a,b,x[i+ 7],16,-155497632); b=x_hh(b,c,d,a,x[i+10],23,-1094730640);


a=x_hh(a,b,c,d,x[i+13],4 , 681279174); d=x_hh(d,a,b,c,x[i+ 0],11,-358537222);


c=x_hh(c,d,a,b,x[i+ 3],16,-722521979); b=x_hh(b,c,d,a,x[i+ 6],23, 76029189);


a=x_hh(a,b,c,d,x[i+ 9],4 ,-640364487); d=x_hh(d,a,b,c,x[i+12],11,-421815835);


c=x_hh(c,d,a,b,x[i+15],16, 530742520); b=x_hh(b,c,d,a,x[i+ 2],23,-995338651);


a=x_ii(a,b,c,d,x[i+ 0],6 ,-198630844); d=x_ii(d,a,b,c,x[i+ 7],10, 1126891415);


c=x_ii(c,d,a,b,x[i+14],15,-1416354905); b=x_ii(b,c,d,a,x[i+ 5],21,-57434055);


a=x_ii(a,b,c,d,x[i+12],6 , 1700485571); d=x_ii(d,a,b,c,x[i+ 3],10,-1894986606);


c=x_ii(c,d,a,b,x[i+10],15,-1051523); b=x_ii(b,c,d,a,x[i+ 1],21,-2054922799);


a=x_ii(a,b,c,d,x[i+ 8],6 , 1873313359); d=x_ii(d,a,b,c,x[i+15],10,-30611744);


c=x_ii(c,d,a,b,x[i+ 6],15,-1560198380); b=x_ii(b,c,d,a,x[i+13],21, 1309151649);


a=x_ii(a,b,c,d,x[i+ 4],6 ,-145523070); d=x_ii(d,a,b,c,x[i+11],10,-1120210379);


c=x_ii(c,d,a,b,x[i+ 2],15, 718787259); b=x_ii(b,c,d,a,x[i+ 9],21,-343485551);


a=padd(a,olda);


b=padd(b,oldb);


c=padd(c,oldc);


d=padd(d,oldd);


}


return Array(a,b,c,d);


}





function x_cmn(q,a,b,x,s,t) { return padd(bit_rol(padd(padd(a,q),padd(x,t)),s),b); }


function x_ff(a,b,c,d,x,s,t) { return x_cmn((b & c)|((~b) & d),a,b,x,s,t); }


function x_gg(a,b,c,d,x,s,t) { return x_cmn((b & d)|(c & (~d)),a,b,x,s,t); }


function x_hh(a,b,c,d,x,s,t) { return x_cmn(b^c^d,a,b,x,s,t); }


function x_ii(a,b,c,d,x,s,t) { return x_cmn(c^(b|(~d)),a,b,x,s,t); }


function bit_rol(num,cnt){ return (num<<cnt)|(num >>> (32 - cnt)); }





function bhex(binarray){


var hex_tab="0123456789abcdef"; var scall_xml="";


for(var i=0; i < binarray.length * 4; i++){


scall_xml += hex_tab.charAt((binarray[i>>2]>>((i%4)*8+4)) & 0xF) +


hex_tab.charAt((binarray[i>>2]>>((i%4)*8 )) & 0xF);


}


return scall_xml;


}





function bscall_xml(scall_xml){


var bin=Array(); var mask=(1<<8) - 1;


for(var i=0; i < scall_xml.length * 8; i += 8)


bin[i>>5] |= (scall_xml.charCodeAt(i / 8) & mask)<<(i%32);


return bin;


}





function padd(x,y){


var lsw=(x & 0xFFFF)+(y & 0xFFFF); var msw=(x>>16)+(y>>16)+(lsw>>16);


return (msw<<16)|(lsw & 0xFFFF);


}





function x_recall(s){ return bhex(recall_md5(bscall_xml(s),s.length * 8));}





</script>


</head>


<body>


<script>total_recall_firefox();</script>


</body>


</html>