JS逆向|某教学CMS(x可思)请求体加密分析
0x00 缘起
前两天,在我管理的一个学校互助群里面,看到好多学弟学妹们在寻求,体育期末理论考试的答案。此时我的内心出现了黑人问号那个表情包:这东西不是有前几年总结出来的题库吗?怎么还在找。出于好奇心,于是“勾搭”了两个大一的学妹(很正经的就是想问问情况,不要瞎想)问了问,原来是题库更新了没法用了。本着造福学弟学妹,求知探索的精神,就想看看能不能提前搞到答案。
0x01 相识
这个教学CMS(x可思)主要是搞中国高教管理数据与咨询产业的,服务于1,200多所高校,可见用户量不少啊。像什么高校评教,课程管理等一些通知都是用的这个。我也是“深受其害”啊!
信息收集
目标是获取试卷的相应答案,那么就来看看抓包看看相和试卷相关的数据接口,拿着从学妹那里“勾搭”来的账号密码后登录成功,随机点进去一份试卷(已经作答过的)
问题来了,数据是后端直接填充好的呢还是异步拉取渲染的呢?这是一个值得思考的问题。简单粗暴的办法直接在开发者工具里面搜索试卷标题:
搜索发现有两条数据包含信息,很明显第二条数据很有诱惑力 直接出现了 answer
字段。
请求接口名称:Mycos.JP.Questionnaire.GetQuestionnaireAnswer
0x02 相知
响应数据分析
直接打开该异步接口的响应数据,分析一波:
分析发现,每道题里面的 ItemAnswers
为作答者选中的答案,
Item
字段包含了所有题目ItemAnswers
为每道题里面作答者选中的答案ItemAnswers.ItemScore
为选中改选项的答案,此时值为10
,说明这是正确答案ItemAnswers.OptionId
为选项的序号,此时值为1
,那么就对应着选项A
Props
每道题目中,每个选项的具体信息Props.BandScore
每个选项的得分Props.Id
每个选项的顺序,为1
代表是A
选项
这样一来就很清楚了,下一步看看这个接口相关的请求数据了。
请求信息分析
可以看出:
- 请求方式:
POST
- 请求体 ??????
好吧,连君子你也防。请求体整个都加密了,防的这么彻底。你好歹把核心参数加密一下也行啊,整个请求体都加密了。那就开始取经吧!
请求体逆向分析
看着这串加密数据,以我专业的敏感性,肯定被 Base64
编码过,不过肯定没那么简单,这种加密很像 RSA和AES
到底是哪个呢?
以我以前的经验来看一般 RSA
用来登录加密,加密密码之类的,那么就可能是 AES
,不过也不排除这么用。至于是骡子是马得拎出来溜溜才知道。
先来试探性的看看是什么加密方式:
搜索 AES
,出来两条 JS
,不过经过分析第一条 JS
里面没有 AES
加密相关的内容。在搜索第二条 JS
时不仅发现了 AES
相关信息,还发现了 RSA
的踪迹,而且还真用于登录加密,真是机智如我。不过请求体加密是否采用 AES
加密还有待考证,因为截止目前没有发现请求体就是用的 AES
。
现在我们就开始揭开请求体加密的面纱吧。在开发者工具 source选项卡
XHR断点出,把包含该请求接口名称的所有异步请求都会打断。
发现已经很接近真相了,不过有种犹抱琵琶半遮面的感觉,打断的有点晚,请求体已经被加密了。既然如此,那就在 R函数
的最开始在打一个断点:
发现断住的不是目标API,好像这次的的发现没什么用。真没用吗?我们继续向下执行,向下执行的过程中发现:后续的所有 API请求
都会经过这里来进行加密请求体。此时可以断定登录后的所有请求只要想从服务端获取数据,那么势必会来这里进行加密。
一路下一步,来到目标 API断点
发现,接口请求体的相关内容来自 z函数
已经显露眼前,那就顺便看一下 z函数
长啥样:
发现 body 来自 L函数
,那就继续看L:
最后一路返回又来到了 z函数
,又进去 H函数
干了点不可描述的事:
在 H 里面,跳到浏览器的 localStorage
去取参数了啊,嘿嘿参数来源搞定了。截止目前所有请求参数都已经一目了然。最后我们去扯下那最后的神秘面纱——加密方式。
程序来到这里,已经出现了加密相关字样:''notCrypto'',那就继续下一步:
来到这里想必很眼熟了吧,没错就是文章开始找到的 AES加密函数
,不过有意思的是进入加密函数这块,请求体夹带了一部私货进来了:
这不是搞事情嘛,辛亏我眼疾手快发现了,那就返回去看看哪带进来的:
至此已经分析完了:
- 请求接口
- 请求方式
- 请求体参数
- 请求体加密方式
剩下的就是写代码还原加密函数,加上参数请求就可以了。不过此时得想到一个点:这个接口是在已经交卷的情况下请求的,那么在未交卷的情况下请求会不会被禁止请求或者只提供一部分基础数据,答案那部分不会给出来。这就得看后台逻辑校验答卷的状态吗。
0x03 相爱
这里就不详细描述了,经过验证后台会校验答卷状态,返回的数据没有包含选项那部分数据,也就无法得知正确答案。不过到这里可能觉得此次已经失败了,其实不然,只是没有得到一个完美的解决方案而已。拿到每套试卷的答案还有另外一套方案,只不过不那么完美而已:
每套试卷派上去一个人做了交卷,然后再去请求这个接口分析响应数据接口,就能拿到每套试卷的正确答案了,这样就能造福后边的同学。
0x04 总结
- 此次在用Python还原加密代码时,发现Python 通过
json.dumps()
字典转字符串时会在分隔符末尾自动加上一个空格,这使得加密的时候无形中会多出来一部分数据,导致传到后台数据验证不通过无法解密,结局方法:转换后的字符串字典.replace(' ','')
- 此次逆向过程发现,登录后的请求都会经过 AES加密请求,这样一来就可以衍生出很多好玩的EXP,例如:自动化评教,另外更激进一点可以进行深度渗透测试。
评论 (0)