页面校验请求MmEwMD(转载)
写在前面
本人没有深入钻研过前端技术,JS属于亚文盲水平,这篇分析的目的是分享解决解决问题的思路。
- 提出假设,证明它或推翻它,如果推翻,就再提出一个新的假设。该走的弯路,一米都不能少
- 抛开所有不可能的,剩下的,不管多么匪夷所思,那都是事实
- 坚信JS是纯客户端逻辑,理论上一定可破解,需要的是时间和耐心
- 凡是不能杀死你的,最终都会让你更强
问题描述
智联招聘企业端登陆,输入验证码后,点击验证按钮,抓包获得以下请求
https://passport.zhaopin.com/chk/verify?callback=jsonpCallback&MmEwMD=12quxKHKjs0Ueapv9t.fUcurtt8lkuPKNW.iigEyOYlrTOxwONa0ImcCQ8gvRZic3MnqU1WUPdIESozanNi1FCB38raqp0l5vVLXlYgSCIWxh6rR.3q0lK304tlBMH49LDm8FUL4hkfboCm_lhWv9qO7coH_FfFRY1fC8xIZ7_NljGkOJvIWaaUFwhGF2SVwN58UkzX6GuABWNvbUzzVVq5Kzj45tS_p4U2fo.re9LOuwPpp99H5bLKIgmNsI_RALV39ujuLsqhbHTJAgCtQeZzOkhMbjJKciuKPp97TkbIpDpGr_ZqTBghcjRgr_gz1CkGCCoUTn24dIPfVB0tTDenbTTuOot.rT_RmTiIsA0zY5ac445PXgJZXaXHxrV_ASY0
问题:如何构建MmEwMD参数?
初步分析
查看智联招聘login页面的相关JS文件,分析query param的构建方法
scripts/chk/captcha.js
从上图中我们可以看到调用JQuery的$.ajax方法来发送请求,发送的url只有 callback
一个query param,并没有看到 MmEwMD
的踪迹,说明不是在zhilian自己的JS文件中加这个参数,猜测是给JQuery加了 prefilter
或者 beforeSend
之类的钩子
构建本地JS Debug环境
通过
wget
抓取html和相关资源文件wget --mirror --page-requisites --adjust-extension --no-parent --convert-links --directory-prefix=sousers https://passport.zhaopin.com/org/login
使用python启动simple web server
python -m SimpleHTTPServer 8081
访问本地login页面
http://localhost:8081/org/login.html
智联招聘使用的JQuery版本是1.7.1,我们从官网下载非min版本方便debug。下载完成后放到script目录下,然后修改login.html中include script代码
http://code.jquery.com/jquery-1.7.1.js
Debug JQuery
// Dosend the request// This may raisean exceptionwhich isactually// handled injQuery.ajax (so notry/catch here)xhr.send((s.hasContent &&s.data )||null);
从 scripts/chk/captcha.js
的 $.ajax
入手一路debug进去,直到上面这行代码,我们inspector xhr对象发现,并没有任何JQuery的钩子,此时,我们怀疑xhr (XMLHttpRequest) 被hook了。
验证方法如下:
在浏览器console中执行以下代码
varxhr =newwindow.XMLHttpRequest();xhr.open('POST','/hello',true);xhr.send('abc');
出现了以下请求,说明在当前页面中的xhr肯定被hook了,同时解除对JQuery的怀疑。
POST http://localhost:8081/hello?MmEwMD=1zXMRFfiFy00rBpdSoJ2cJ4EvS6mQ1dvl5jZLrqB…oRVu5t.x8Y3GVQLmqdG.lmuE2snbEk.YHif4rmHwOtKQoTiHpODCa6HikgWg1X2S._aq8rKTLr
分析Login HTML
Login页面的html中有三段非常有趣的代码
第一段代码是:
<metaname="renderer"content="webkit"><metaid="9DhefwqGPrzGxEp9hPaoag"content="{qqqkkGZAkCAGc60cEqNGqD3DD5aef8al4605kUdZ}FH00lxmQZlsYUWYqfYOapWmqyrK0HMVZCsczHJ90Xl1mUHYqzYOqpHmqJrYVhVAAsUfwWmYqV102mqmgDsaJppYakV2QoUGAwKTymDYgwsSNpK2aFV9aopaAtK07pqmQFVqSKlSlwVrEmXq5_s8RWy24CUi0pdmIbVHfKySoNVi3mzq5CJ1489597716416YipgfCWy.0N5u81OO.MzYPhz_sUNCdYZHoc64qqqVqDASVkfQJYZ6Vkm8J20yqqqqqqqqqqqqqqqqKBgyFY2AtnVVvvzAyQm_MlqqqiR9xU82xnVUwUIqc80{BxLZUzp12oHeoyld0p5rxyaOOYIxVTlI6A8eodlHZm_QVjSuSpeRHS9IK1wlE0YUqYiNonVowpZyknf8pmx0Qa0I3sZfoSlvkcJJKa6kpYWRHCVGkl3W8iplVtALfc1VJxa07kPgqEa9Nk10HhAh1CI9DpmpzDfqr0k130qqqr0qqqqqqqqqqqqqqqq">
关键字: 9DhefwqGPrzGxEp9hPaoag
- 好消息是这套机制不是智联独创的,别的网站也有用。
- 坏消息是网上的资料非常非常非常稀少
第二段代码是:
<scripttype="text/javascript"src="/4QbVtADbnLVIc/d.FxJzG50F.js?D9PVtGL=5aef8a"></script>https://passport.zhaopin.com/4QbVtADbnLVIc/d.FxJzG50F.js?D9PVtGL=5aef8a
关键字: FxJzG50F
- 和上面情形差不多,有别的网站在用,但资料非常稀缺
- 差不多可以推断出这个JS是用来做混淆的
第三段代码是:
<scripttype="text/javascript">var_$qk=window,_$rL=top,_$vH,_$vy,_$nX,_$x5,_$an=String.fromCharCode,_$xU=[],_$ch,_$xF,_$nh,_$su,_$oR,_$l7,_$h4,_$xR=_$qk.Error;var_$kO,_$wL,_$wA;var_$gg=1;_$gf();_$qk[_$an(101,118,97,108)]// 内容太多,文章的最后会帖一个完整版</script>
- 这段代码的是经过混淆的JS,并且每次请求login页面,拿到的JS内容都会变化,意味每次会随机用于混淆的变量名和函数名,真是太贱了。
- 接下来我们挑选一个版本,然后解剖下这段JS究竟在做什么
做到这一步,已经产生了一些敬畏之心,既然搜了这么多冷门的关键字,不妨搜一下主角 MmEwMD
关键字: MmEwMD
百度终于比谷歌牛逼了一回,谷歌完全搜不到,百度可以搜到一条论坛信息,时间还挺近的,是有人在论坛上求助咪咕的login请求问题,再一次印证了这东西不是智联原创,但网络上相关资料非常稀少,可能是一个非公开,非开源的东西
分析被混淆过的outer.js
由于代码有500多行,我将完整代码贴在文章最后的附录中,我们称这个js为 outer.js
为了debug这个混淆过的 outer.js
文件,我们需要:
- 在login.html文件中注释掉这段JS的
<script>...</script>
- 将format后的JS保存到文件中放到script/outer.js
- 在login.html中include这个JS文件
准备工作完成后,开始debug这个JS,初步猜想,这个JS中应该有一个callback函数,当点击验证按钮的时候,可以到这个函数中。我们给所有的function的入口出都打上断点,但按下验证按钮后,居然没有一个function被触发,这说明callback函数不在这些function中!
经过逐行跟踪,我们猜测callback function的代码,以及inject hook的代码可能都是运行过程中产生的,然后通过 eval()
或者 window['execScript']
之类的来动态加载的,最后我们定位到下面这个函数
outer.js line 405~417function_$tx(_$dq){if(_$dq ===undefined||_$dq ==="")return;var_$dL =_$h1[_$k1][_$ls],_$kD;if(!_$jr)_$jr =_$dL.push;if(_$h1[_$o4])_$kD =_$h1[_$o4](_$dq);else{var_$sD =_$h1[_$bn];_$kD =_$sD[_$hm](_$h1,_$dq);}if(_$jr !==_$dL.push)_$dL.push =_$jr;return_$kD;}
window["execScript"]动态加载代码
_$dq
里面就是被动态加载的代码,接下来我们将debug这段被动态加载的代码。- 我们将他保存为
inner.js
,完整代码参见最下面的附录(有2000多行,太长贴不下,分了卷一和卷二) - 做到这一步已经有些心力憔悴,因为我们不知道前方会有几层迭代,会不会不停地产生动态代码并且加载
字符串变量替换表
在分析 outer.js
过程中,我们发了一张字符串和混淆变量之间的对应关系表,将下面这段代码执行后,可以得到以下变量定义(完整定义请见附录),这里定义了 inner.js
用到的所有全局变量,对我们分析2000+行的 inner.js
非常有帮助
..._$eS ="XMLHttpRequest",_$ml ="send",_$ij ="MmEwMD",...
outer.js line 52_$h1[_$w6(101,118,97,108)](_$kw("FSSBBIl1UgzbN7N`use strict`document`localStorage`globalStorage`sessionStorage`indexedDB`mozIndexedDB`webkitIndexedDB`msIndexedDB`name`top`vdFm`unload`prototype`get`call`set`openDatabase`EkcP`windowData`sessionData`globalData`localData`userData`dbData`idbData`tests`function`setItem`getItem`div`userdata_el`addBehavior`style`behavior`url(#default#userdata)`setAttribute`save`load`getAttribute`transaction`executeSql`CREATE TABLE IF NOT EXISTS `EkcP_t`id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, `name TEXT NOT NULL, `value TEXT NOT NULL, `UNIQUE (name)`INSERT OR REPLACE INTO `(name, value) `VALUES(?, ?)`SELECT value FROM ` WHERE name=?`rows`length`item`value`open`onerror`onupgradeneeded`target`result`createObjectStore`onsuccess`objectStoreNames`contains`readwrite`objectStore`put`close`vlaue`escape`indexOf`substr`string`split`charAt`substring`unescape`location`host`replace`getElementById`createElement`visibility`hidden`position`absolute`id`body`appendChild`slice`concat`splice`floor`t__`B_`fontList`$b_onBridgeReady`$b_callHandler`$b_setup`$b_platform`android`iframe`display`none`documentElement`cb_`getTime`src`jbscheme://`stringify`jbscheme://queue_has_message`$b_fetchQueue`$b_onNativeResponse`navigator`platform`test`Uint8Array`subarray`lastIndexOf`XMLHttpRequest`send`Microsoft.XMLHTTP`Array`charCodeAt`from`language`browserLanguage`zh-CN`_tCbyRDtiXFzNibfz8bwLXK67X84O5PPj58BL8FVX1uL.4I9XE6LNLoLBNH2fFUb23dbfxd9B_obGFdbPxMvG.v2f4B9X4B9BRUN944bOjVf`alert`apply`GET`href`responseType`arraybuffer`setRequestHeader`X-sOYOcALfiiw`onreadystatechange`readyState`status`response`VBArray`responseBody`toArray`MmEwMD`Math`ceil`JSON`0000`toString`number`null`boolean`object`[object Array]`hasOwnProperty`%20`addEventListener`on`attachEvent`random`assert failed with condition: `assert failed: ` is not same as `acceleration`accelerationIncludingGravity`alpha`beta`gamma`battery`getBattery`then`level`charging`chargingTime`Infinity`$_YWTU`$_cDro`isNaN`keyCode`button`offsetX`offsetY`touches`screenX`screenY`clientX`clientY`userAgent`standalone`$PreUCBrowserClassic,UCBrowserMessageCenter`__firefox__,_firefox_ReaderMode`__mttCreateFrame,mttCumstomJS`__crWeb,__gCrWeb`MicroMessenger`SeMobFillFormTool,SogouMse`Sogou`ApplePaySession`Safari`PointerEvent`MSPointerEvent`msCredentials`webkitPersistentStorage`browser_parameters,item`FaveIconJavaInterface,jesion` OPR/`chrome`runtime`webstore`onautocomplete`PerformanceObserver`PerformanceObserverEntryList`Entity`AnalyserNode`external`AddSearchProvider`dumpAll`MozAppearance`$_ts`DeviceStorage`controllers`UCWebExt,ucweb`qb_bridge,qbbookshelf`dolphin,dolphininfo,dolphinmeta`safari`pushNotification`orientation`callPhantom,_phantom`$hook$,$$logger,$$lsp,$$lsrb`netsparker,__ns`hp_identifier`spi_hooked,mozAnimationStartTime,mozIndexedDB,mozRequestAnimationFrame`Gamepad`c[`a[b](`WebXMLogMsg_UNIQUE_`stack`pop`Object.InjectedScript.evaluate`@debugger`evaluate`setInterval`eval`var a = new Date(); debugger; new Date() - a > 100;`$_ck`_Selenium_IDE_Recorder,_selenium,callSelenium`__driver_evaluate,__webdriver_evaluate,
转载于:https://www.cnblogs.com/Duke-/p/8492187.html
页面校验请求MmEwMD(转载)相关推荐
- legend3---3、lavarel页面post请求错误之后跳转
legend3---3.lavarel页面post请求错误之后跳转 一.总结 一句话总结: 控制器:return back()->withInput()->with('error','验证 ...
- 使用Filter防止浏览器缓存页面或请求结果
仅仅须要两步: 1.定义一个Filter: /*** 防止浏览器缓存页面或请求结果* @author XuJijun**/ public class NoCacheFilter implements ...
- python get请求 url传参_用Python-get方法向页面发起请求,参数传不进去是怎么回事...
源自:4-1 接口测试工具-python-get接口实战 用Python-get方法向页面发起请求,参数传不进去是怎么回事 #-*-coding:utf-8-*- import urllib impo ...
- java 图形校验_java图形验证码生成工具类 web页面校验验证码
java图形验证码生成工具类 web页面校验验证码 发布于 2020-7-14| 复制链接 摘记: 最近做验证码,参考网上案例,发现有不少问题,特意进行了修改和完善.验证码生成器: ```java i ...
- 在业务层实现校验请求参数
前言 在前面的文章中,我们介绍了在业务层实现管道模式: 响应缓存 记录请求日志 今天,我们同样使用IPipelineBehavior,介绍如何在业务层实现校验请求参数,用于检查输入是否满足业务要求. ...
- 页面发送请求到后台报错“Empty or invalid anti forgery header token.”问题解决
页面发送请求到后台报错"Empty or invalid anti forgery header token."问题解决 参考文章: (1)页面发送请求到后台报错"Emp ...
- vue关闭页面发出请求
vue关闭页面发出请求: 问题描述: 要求在页面关闭时,向后端发送一个请求.但是有时候会请求成功,有时候后端不会收到请求 mounted() {this.messageWrapper = docume ...
- 学会处理ASP.NET的页面和请求状态信息 (转载)
作者: BUILDER.COM 2003-04-23 02:41 PM 任何动态Web应用程序都必须能够管理状态信息--ASP.NET的应用程序也不例外.在本文里,我会讨论处理两种类型状态信息的方法: ...
- session图片验证码,页面和请求是两个地址。android手机好用,iphone 失效。
问题描述:之前在H5页面用session做了一个验证码.安卓手机好使.但是到苹果就不好使了(页面访问是一个域名地址,ajax请求是用另外的一个ip地址). 详细说明: 验证码请求后台图片正常显示,an ...
最新文章
- PHP-代码审计-文件读取(下载)
- java存入光盘_java 这是 学习笔记(jdk7)书中的光盘里的源码,不知大家需要不,里面都是新手 的好 Develop 238万源代码下载- www.pudn.com...
- arraylist获取前多少位_Java 面试题 :百度前 200 页都在这里
- 图Graph--最短路径算法(Shortest Path Algorithm)
- 软件测试 -------- 数据库设计 的 E-R 模型
- 天空象棋——网站与用户
- Webkit中textarea的设定
- @程序员,如何在编程面试中脱颖而出?
- 在浏览器地址栏输入一个URL后回车,背后会进行哪些技术步骤?
- 斯坦福NLP名课带学详解 | CS224n 第5讲 - 句法分析与依存解析(NLP通关指南·完结)
- easyUi combobox setValue 引起的关于js的坑
- linux awk 区别,linux awk 中 RS,ORS,FS,OFS 区别与联系
- Pictures of Ascii Art
- android系统旧版本下载安装,我的世界旧版下载安装-我的世界老版本下载手机版-乐游网安卓下载...
- 普通话测试第四题评分标准_普通话测试第四题评分细则
- JavaSE基础知识回顾
- 怎样把gis锯齿边_在arcgis中如何消除锯齿状边缘
- 《无法打开包括文件:“Eigen\Dense”:No such file or directory》亲测有效的解决方法
- maven 国内可用的中央仓库 阿里云
- 百年烈酒公司William Grant&Sons将通过区块链追踪威士忌产品
热门文章
- 五角星是不是旋转对称图形_新部编二年级下册数学第10单元总复习教案,克和千克、图形的运动...
- JAVA常用工具类→Date、SimpleDateFormat、Calendar、System、Math
- python删除文件夹中的jpg_python删除文件夹下相同文件和无法打开的图片
- pytorch .item_从数据到模型,你可能需要1篇详实的pytorch踩坑指南
- SQL Server高级查询之常见数据库对象(数据库事务)第五章节
- JQueryDOM之属性操作
- 通信中的ATM cell:ATM信源结构
- 猜数游戏--MOOC中习题
- bzoj 4001: [TJOI2015]概率论(找规律)
- bzoj 1257: [CQOI2007]余数之和sum