在很多地方就是都出现了使用二维码登录,二维码付款,二维码账户等应用(这里的二维码种马,诈骗就不说了),二维码验证,多终端辅助授权应用开始多起来,这里先说下啥是二维码,其实二维码就是存了二进制数据的黑白图片,当出现要求二维码登录的时候,服务器会生成一条临时的唯一的二维码信息,发送到客户端以二维码(图片)的形式写入到网页,然后你就会看到统一的四个方形的二维码,如果做的好这个二维码信息应该是有时效的,这里暂且不考虑这些,就简单的微信登录作为例子看看吧:
首先说下整个授权流程:
在客户端网页中会不断向服务器发送https连接,并且这里传输很少的数据之后就断开连接了,下面看下微信网页中这个login1c709c.js文件:
(function($, _aoWin) { _aoWin.QRLogin = {}; _aoWin.LoginLog = \"\"; var _sBaseHost = \"\", _oLoginQrCodeImg = document.getElementById(\"loginQrCode\"); if (document.domain == \"qq.com\") { _sBaseHost = \"weixin.qq.com\"; } else if(location.hostname.match(/(wechat\\.com)$/)){ _sBaseHost = \"wechat.com\"; }else{ _sBaseHost = \"wechatapp.com\"; } var show_tip = 1, _sCurUUId, _oResetTimeout, _aWebMMCallbacks = [], _oDetactWebMMInterval = setInterval(function(){ if(_aoWin.WebMM){ clearInterval(_oDetactWebMMInterval); var callback; while(callback = _aWebMMCallbacks.shift()){ if(typeof(callback) != \"function\") continue; callback(); } } }, 1000); function _logInPage(_asLog){ _aoWin.LoginLog = LoginLog + _asLog + \"\\n\"; } function _afterLoadWebMMDo(callback){ if(!_aoWin.WebMM){ _aWebMMCallbacks.push(callback); }else{ callback(); } } function _reportNow(text){ _logInPage(text); _afterLoadWebMMDo(function(){ WebMM.ossLog({Text: text}); WebMM.flushOssLog(); }); } var reLoadQRImgCount = 0, loadQRCodeTime = 0, loadQRImgSucc = function(){ clearInterval(loadQRImgWatchDog); _logInPage(\"Load QRCode Success, time=\" + (new Date().getTime() - loadQRCodeTime) + \"ms, reload count: \" + reLoadQRImgCount); }, loadQRImgFail = function(img){ _reportNow(\"Load QRcode fail!\" + status + \", src: \" + img.src + \", time: \" + (new Date().getTime() - loadQRCodeTime) + \"ms\"); }, loadQRImgWatchDog = null; function _loadQRImg(uuid) { _poll(uuid); _logInPage(\"Load QRCode Start\"); loadQRCodeTime = new Date().getTime(); _oLoginQrCodeImg.onload = function(){ loadQRImgSucc(); _oLoginQrCodeImg.onload = null; }; _oLoginQrCodeImg.onerror = function(){loadQRImgFail(this)}; _oLoginQrCodeImg.src = \"https://login.\"+_sBaseHost+\"/qrcode/\"+uuid+\"?t=webwx\"; loadQRImgWatchDog = setInterval(function(){ if (reLoadQRImgCount >= 5) { _reset(); return; } reLoadQRImgCount++; var _img = new Image(); _img.onload = function () { if(!_oLoginQrCodeImg.onload) return; _oLoginQrCodeImg.onload = null; _oLoginQrCodeImg.src = this.src;//replace loadQRImgSucc(); }; _img.onerror = function(){loadQRImgFail(this)}; _img.src = _oLoginQrCodeImg.src + \"&r=\" + new Date().getTime(); }, 5000); } var _sSecondRequestTime = 0, _nAjaxTimeout = 100 * 1000, _nNewLoginFuncErrCount = 0; function _poll(_asUUID) { var _self = arguments.callee, _nTime = 0; _sCurUUId = _asUUID; _logInPage(\"_poll Request Start, time: \" + new Date().getTime()); _nTime = new Date().getTime(); $.ajax({ type: \"GET\", url: \"https://login.\" + _sBaseHost + \"/cgi-bin/mmwebwx-bin/login?uuid=\" + _asUUID + \"&tip=\" + show_tip, dataType: \"script\", cache: false, timeout: _nAjaxTimeout, success: function(data, textStatus, jqXHR) { _logInPage(\"_poll Request Success, code: \" + window.code + \", time: \" + (new Date().getTime() - _nTime) + \"ms\"); switch (_aoWin.code) { case 200: _sSecondRequestTime = new Date().getTime() - _sSecondRequestTime; _logInPage(\"Second Request Success, time: \" + _sSecondRequestTime + \"ms\"); clearTimeout(_oResetTimeout); var _fNewLoginFunc = function(){ $.ajax({ url: _aoWin.redirect_uri + \"&fun=new\",//new login page type: \"GET\", success:function(msg) { _logInPage(\"new func reponse, reponseMsg: \" + msg); var code = msg.match(/<script>(.*)<\\/script>/); var skey=msg.match(/<skey>(.*)<\\/skey>/); if(code){ eval(code[1]); }else{ $(\"#container\").show(); $(\"#login_container\").hide(); } if(skey && skey[1]){ WebMM.model(\"account\").setSkey(skey[1]); } }, error:function(jqXHR, textStatus, errorThrown){ _nNewLoginFuncErrCount++; if(_nNewLoginFuncErrCount > 5){ if(confirm(\"Call new login page func error, refresh?\")){location.reload()} return; } _reportNow(_aoWin.redirect_uri + \" New login page func error: \" + textStatus +\" retryCount:\" + _nNewLoginFuncErrCount); setTimeout(_fNewLoginFunc, 500); } }); }; _fNewLoginFunc(); _reportNow(\"/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: \" + _asUUID + \", time: \" + _sSecondRequestTime + \"ms\"); break; case 201: clearTimeout(_oResetTimeout); show_tip = 0; $(\'.errorMsg\').hide(); $(\'.normlDesc\').hide(); $(\'.successMsg\').show(); _reportNow(\"/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: \" + _asUUID); _reportNow(\"/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: \" + _asUUID); _sSecondRequestTime = new Date().getTime(); //_nAjaxTimeout = 5 * 1000; _self(_asUUID); break; case 408: setTimeout(function(){ _self(_asUUID); }, 500); break; case 400: case 500: _reset(); _afterLoadWebMMDo(function(){ _aoWin.Log.d(\"500, Login Poll Svr Exception\"); }); break; } }, error: function(jqXHR, textStatus, errorThrown) { if (textStatus == \'timeout\') { setTimeout(function(){ _self(_asUUID); }, 500); } else { setTimeout(function(){ _self(_asUUID); }, 5000); _logInPage(\"_poll Request Error:\" + textStatus); _afterLoadWebMMDo(function(){ _aoWin.Log.e(\"Login Poll Error:\" + textStatus); }); } } }); } var getUUIDCount = 0, _getUUIDWatchDog, _bGetUUIDSuccess = false;//ajax successִ function _getUUID() { getUUIDCount++; var _self = arguments.callee, _loadError = function(errorText){ _reportNow(\"Load UUID Error! ErrorText: \" + errorText + \" getUUIDCount=\" + getUUIDCount); if(getUUIDCount > 5){ if (confirm(\"Load uuid error. Refresh?\")) { location.reload(); } } setTimeout(function(){ _self(); }, 500); }; clearTimeout(_getUUIDWatchDog); _getUUIDWatchDog = setTimeout(function(){ if(!_aoWin.QRLogin.code){ _logInPage(\"GetUUID Timeout, WatchDog Run\"); _self(); } }, 10000); $.ajax({ type: \"GET\", url: \"https://login.\" + _sBaseHost + \"/jslogin?appid=wx782c26e4c19acffb&redirect_uri=\"+encodeURIComponent(location.protocol+\"//\"+location.host+\"/cgi-bin/mmwebwx-bin/webwxnewloginpage\")+\"&fun=new〈=\" + document.lang, dataType: \"script\", cache: false, success : function(){ clearTimeout(_getUUIDWatchDog); if(_bGetUUIDSuccess) return; if (_aoWin.QRLogin && _aoWin.QRLogin.code == 200) { _logInPage(\"GetUUID Success, UUID=\" + QRLogin.uuid); _bGetUUIDSuccess = true; clearTimeout(_oResetTimeout); _oResetTimeout = setTimeout(function(){ location.reload();//Note: Don\'t run _reset(). If you run _reset(), there will may have many _poll request, as they get 408 return code }, 5 * 60 *1000);//5 mins _loadQRImg(QRLogin.uuid); } else { var QRLoginCode = (_aoWin.QRLogin && _aoWin.QRLogin.code) ? _aoWin.QRLogin.code : \"None\"; _logInPage(\"GetUUID Error, QRLogin.code=\" + QRLoginCode); _loadError(\"QRLogin.code= \" + QRLoginCode); } }, error : function(xhr, textStatus, errorThrown){ _logInPage(\"GetUUID Error, textStatus=\" + textStatus); _loadError(textStatus); } }); } function _reset(){ location.reload(); } if ($(\"#login_container\").is(\":visible\") ) { _getUUID(); } var _bHadLog = false; function _ossLog() { if (_bHadLog) return; _bHadLog = true; var _sUvid = document.cookie.match(new RegExp( \"(^| )\"+\"webwxuvid\"+\"=([^;]*)(;|$)\")); if(!_sUvid || _sUvid.length < 3) return; _sUvid = _sUvid[2]; (new Image()).src = \"/cgi-bin/mmwebwx-bin/webwxstatreport?funkey=indexdemo&uvid=\"+_sUvid+\"&uuid=\"+_sCurUUId; } if($(\"img.guide\").length > 0) { var _nTimer = 0, _oGuide$ = $(\".guide\"), _oGuideTrigger$ = $(\"#guideTrigger, #tipTrigger\"), _oMask$ = $(\".mask\"); function _back() { _nTimer = setTimeout(function() { _oMask$.stop().animate({opacity:0}, function(){$(\".mask\").hide()}); _oGuide$.stop().animate({marginLeft:\"-120px\",opacity:0}, \"400\", \"swing\",function(){ _oGuide$.hide(); }); }, 100); } /*guide*/ _oGuide$.css({\"left\":\"50%\", \"opacity\":0}); _oGuideTrigger$.css({\"backgroundColor\":\"white\", \"opacity\":\"0\"}); _oGuideTrigger$.mouseover(function(){ clearTimeout(_nTimer); _oMask$.show().stop().animate({\"opacity\":0.2}); _oGuide$.css(\"display\", \"block\").stop().animate({marginLeft:\"+168px\", opacity:1}, 900, \"swing\", function() { _oGuide$.animate({marginLeft:\"+153px\"}, 300); }); _ossLog(); }).mouseout(_back); _oGuide$.mouseover(function(){ clearTimeout(_nTimer); }).mouseout(_back); } })(jQuery, window);
细读js之后,你就会从网页客户端这边看到请求登录的一面,网页客户端每隔500毫秒就向服务器发起ssl请求,请求当前的二维码是否被其他客户端(手机)授权,如果返回结果是201,就是说明已经获取扫描二维码终端相同的账号登录授权,如果是其他情况就再隔500毫秒再循环发请求。这个过程会一直持续到二维码被扫描通过或者二维码超时(失效)为止。
其中使用的工具有: 抓包工具 Fidller ,Chrome F12开发人员工具,注意偶然的发现,微信的客户端有一个min-webmm1cba21.js ,其中清晰可见的XSS filter规范, 这对于那些喜欢白盒测试XSS的鸽子又有希望拿Q仔了!!!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持phpstudy。
本文地址:https://www.stayed.cn/item/12955
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我