写在前面

本人没有深入钻研过前端技术,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(转载)相关推荐

  1. legend3---3、lavarel页面post请求错误之后跳转

    legend3---3.lavarel页面post请求错误之后跳转 一.总结 一句话总结: 控制器:return back()->withInput()->with('error','验证 ...

  2. 使用Filter防止浏览器缓存页面或请求结果

    仅仅须要两步: 1.定义一个Filter: /*** 防止浏览器缓存页面或请求结果* @author XuJijun**/ public class NoCacheFilter implements ...

  3. python get请求 url传参_用Python-get方法向页面发起请求,参数传不进去是怎么回事...

    源自:4-1 接口测试工具-python-get接口实战 用Python-get方法向页面发起请求,参数传不进去是怎么回事 #-*-coding:utf-8-*- import urllib impo ...

  4. java 图形校验_java图形验证码生成工具类 web页面校验验证码

    java图形验证码生成工具类 web页面校验验证码 发布于 2020-7-14| 复制链接 摘记: 最近做验证码,参考网上案例,发现有不少问题,特意进行了修改和完善.验证码生成器: ```java i ...

  5. 在业务层实现校验请求参数

    前言 在前面的文章中,我们介绍了在业务层实现管道模式: 响应缓存 记录请求日志 今天,我们同样使用IPipelineBehavior,介绍如何在业务层实现校验请求参数,用于检查输入是否满足业务要求. ...

  6. 页面发送请求到后台报错“Empty or invalid anti forgery header token.”问题解决

    页面发送请求到后台报错"Empty or invalid anti forgery header token."问题解决 参考文章: (1)页面发送请求到后台报错"Emp ...

  7. vue关闭页面发出请求

    vue关闭页面发出请求: 问题描述: 要求在页面关闭时,向后端发送一个请求.但是有时候会请求成功,有时候后端不会收到请求 mounted() {this.messageWrapper = docume ...

  8. 学会处理ASP.NET的页面和请求状态信息 (转载)

    作者: BUILDER.COM 2003-04-23 02:41 PM 任何动态Web应用程序都必须能够管理状态信息--ASP.NET的应用程序也不例外.在本文里,我会讨论处理两种类型状态信息的方法: ...

  9. session图片验证码,页面和请求是两个地址。android手机好用,iphone 失效。

    问题描述:之前在H5页面用session做了一个验证码.安卓手机好使.但是到苹果就不好使了(页面访问是一个域名地址,ajax请求是用另外的一个ip地址). 详细说明: 验证码请求后台图片正常显示,an ...

最新文章

  1. PHP-代码审计-文件读取(下载)
  2. java存入光盘_java 这是 学习笔记(jdk7)书中的光盘里的源码,不知大家需要不,里面都是新手 的好 Develop 238万源代码下载- www.pudn.com...
  3. arraylist获取前多少位_Java 面试题 :百度前 200 页都在这里
  4. 图Graph--最短路径算法(Shortest Path Algorithm)
  5. 软件测试 -------- 数据库设计 的 E-R 模型
  6. 天空象棋——网站与用户
  7. Webkit中textarea的设定
  8. @程序员,如何在编程面试中脱颖而出?
  9. 在浏览器地址栏输入一个URL后回车,背后会进行哪些技术步骤?
  10. 斯坦福NLP名课带学详解 | CS224n 第5讲 - 句法分析与依存解析(NLP通关指南·完结)
  11. easyUi combobox setValue 引起的关于js的坑
  12. linux awk 区别,linux awk 中 RS,ORS,FS,OFS 区别与联系
  13. Pictures of Ascii Art
  14. android系统旧版本下载安装,我的世界旧版下载安装-我的世界老版本下载手机版-乐游网安卓下载...
  15. 普通话测试第四题评分标准_普通话测试第四题评分细则
  16. JavaSE基础知识回顾
  17. 怎样把gis锯齿边_在arcgis中如何消除锯齿状边缘
  18. 《无法打开包括文件:“Eigen\Dense”:No such file or directory》亲测有效的解决方法
  19. maven 国内可用的中央仓库 阿里云
  20. 百年烈酒公司William Grant&Sons将通过区块链追踪威士忌产品

热门文章

  1. 五角星是不是旋转对称图形_新部编二年级下册数学第10单元总复习教案,克和千克、图形的运动...
  2. JAVA常用工具类→Date、SimpleDateFormat、Calendar、System、Math
  3. python删除文件夹中的jpg_python删除文件夹下相同文件和无法打开的图片
  4. pytorch .item_从数据到模型,你可能需要1篇详实的pytorch踩坑指南
  5. SQL Server高级查询之常见数据库对象(数据库事务)第五章节
  6. JQueryDOM之属性操作
  7. 通信中的ATM cell:ATM信源结构
  8. 猜数游戏--MOOC中习题
  9. bzoj 4001: [TJOI2015]概率论(找规律)
  10. bzoj 1257: [CQOI2007]余数之和sum