最新测试结果:
注意!!!!:
2023-10-26日:根据最新测试,以下教程仍然可用,代码测试无问题,以下为测试部分截图:
登录:
接口请求与解密:
解密结果对比原站点:
==================以下为本次教学=====================
写在前面:本篇博客很长,都是手把手一步一步的教程,跟着做就能出结果,文章总共分为以下三部分,我也会在3个部分中详细的说明步骤
(1)接口请求头参数验证
(2)接口响应数据DES3加密
(3)登录状态验证
一、接口请求头参数验证
1、以“民事案件”专栏为例,切换到“民事案件”专栏,点击翻页,观察控制台中的网络请求,rest.q4w结尾的接口及为数据接口。
2、点击打开请求详情,观察请求和响应
3、请求中数据校验主要是 pageId、ciphertext、__RequestVerificationToken参数
4、请求头中校验的主要是Cookie参数,session及登录状态,这里先拿固定的cookie做调试,数据加密解密完成后再研究登录
5、通过观察首页不同案件类型,即可直到pageId与每个案件类型,一一对应,抓取某一块对应写死即可。
6、在控制台中对接口rest.q4w打断点
7、再次请求接口,观察调用栈中的请求
8、观察可知此处生成了第二个参数ciphertext
9、跟进cipher()方法,使用Python还原此方法即可得到ciphertext
10、 全局搜索参数 __RequestVerificationToken,跟进第三个
11、参数是页面中生成的固定值,由base.random(24)生成
12、查找此方法,在website.js里1006行,找到了代码
random: function(size) {
var str = ""
, arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
for (var i = 0; i < size; i++) {
str += arr[Math.round(Math.random() * (arr.length - 1))];
}
return str;
}
算法很简单,就是先定义一个空字符串str作为未来的返回值,然后有一个从0-9,到a-z到A-Z的数组作为字典,再用一个for循环,循环size次,把str的内容变成自身再加上arr字典里面的一个随机下标,这个随机下标就是一个随机数乘上这个字典的长度-1再四舍五入。这里解释一下:
- Math.round();是四舍五入
- Math.random();是随机数
最后根据输入的参数长度,返回对应长度的随机字符串
这里都是随机,理论上不用此方法,自己使用python任意产生随机数量的随机数,然后切片就行。
13、到此请求中的三个校验参数pageId、ciphertext、__RequestVerificationToken 都可获得,接着对响应的加密数据进行分析
二、接口响应数据DES3加密
1、观察响应数据,发现result很长,应该是返回的数据加密后的,还有一个secretKey参数,推测此加密为对称加密 AES或DES,secretKey为密钥,用于解密
2、全局搜索关键字AES,无结果,再次搜索DES,即可发现相关代码
3、跟进第一处后可发现,此处非常可疑,在ajax方法的响应成功(sussecc:)回调中进行了DES3.decrypt(data.result, data.secretKey),decrypt及解密,参数也刚好是 1 中提到的result和secretKey,打上断点继续调试看看
4、果不其然,断点后参数正是数据接口的响应
5、跟进DES3.decrypt()方法看看,这里可看到加密算法是DES3,还有偏移量iv
6、查看整个DES3的声明,可得到vi的获取方法为 $.WebSite.formatDate(new Date(), "yyyyMMdd")
7、通过以上过程可得以下结论
- 加密模式:CBC
- 填充模式:pkcs7(pkcs7padding)
- iv偏移量:CryptoJS.enc.Utf8.parse(a || DES3.iv())
iv偏移量计算原理,对a || DES3.iv() 的结果CryptoJS.enc.Utf8.parse()
CryptoJS.enc.Utf8.parse()是用来从UTF8编码解析出原始字符串的
a || DES3.iv()是一个短路逻辑运算符,运算规则如下:
假若a || b 则
- 当 a == true 时,无论b是什么,都返回a
- 当 a == false 时,无论b是什么,都返回b
观察可知a是个参数,而在Ajax的请求中,却写的是:DES3.decrypt(data.result, data.secretKey),并没有传a,及a为undefined,所以iv的最后结果就是DES3.iv(),
也就是$.WebSite.formatDate(new Date(), "yyyyMMdd"),也就是当前日期的yyyyMMdd格式,看看这个formatDate方法也确实如此,例如今天是2022年9月20日,那么偏移量便是20220920
所以:
- 加密模式:CBC
- 填充模式:pkcs7(pkcs7padding)
- iv偏移量:当日的yyyyMMdd格式,例如:(20220920)
8、通过已知参数对加密结果在线解密,看看是否能得到正确结果,在线解密网址 http://tool.chacuo.net/crypt3des 输入参数 ,大家可用以下参数自行体验解密
3DES加密模式:CBC
填充:pkcs7padding
密码:izsGver6BoK18TE7I90zGvly
偏移量:20220920
输出:base64
字符集:utf8编码
待加密、解密的文本:因数据太长,应外单独存放 【腾讯文档】裁判文书响应体
解密结果如下:
9、到此加密解密已分析完毕,用python还原CBC解密,或者nodejs调用DES3.encrypt()解密即可。
三、登录状态验证
1、通过(1)和(2)的研究分析,已经可以正常请求接口和解密接口的数据,但是在最开始查看此网站时,发现此站是需要登录的,而在(1).4中分析也知请求头中需要验证Cookie,也就是登录后由服务器返回的session,可从登录接口开始进行分析。
2、在新打开的登录窗口中,输入账号,然后随便输入错误的密码,点击登录,开始调试
3、点击登录以后调用了login接口,并返回密码错误
4、点击查看接口信息,可发现在表单数据中,username是输入的手机号,而password则是经过加密后的字符串
5、 对login接口打断点,观察调用栈的每一步,查找密码加密的地方
6、遗憾的是,经过层层调试,在调用栈的最底层,密码已经是加密后的状态。推测密码加密与登录并不是同步进行的,而是在执行登录之前,密码已经经过了加密;
7、按照上述思路,首先全局搜索password,尝试找加密的地方,经过漫长的调试过程,在main.js中发现了很多校验密码的代码
8、第一行跟进后可发现对密码进行了一次编码encodePassword(),查看方法内容,有明显的RSA标志setPublickey,是典型的RSA加密,打上断点改下密码试试、
9、参数e与密码框中的密码一样,输出返回值及是加密后的字符串
10、python还原加密方法,或nodejs调用该方法即可
11、由于登录后窗口跳转到主页,此处切换为fiddler抓包。先请求登录接口,可看到登录成功后,响应体中向Cookie中写入了HOLDONKEY=MjAyMDc3NmMtZGQwMS00MjM1LWE4NDItZGUyNjc5NzNhMzE1; Path=/; Secure; HttpOnly; SameSite=None
12、登录成功后,在请求列表中的login下有个302跳转请求
我们先观察下302请求,发现请求体中带有上一步返回设置的cookie信息HOLDONKEY,以及响应头的相关信息
再看其重定向后的200请求,发现其请求中的cookie参数不再是HOLDONKEY了,而变成SESSION,但是在前两步都未曾设置过Cookie中的SESSION值,那这个SESSION是哪里来的?
13、再思考这个问题中,又想到302请求的url又是哪里来的?往上继续翻找fiddler的请求列表,发现在login请求之前还有个/tongyiLogin/authorize 接口,返回值正是302请求的url,并且在响应头中设置了Cookie中的session值 SESSION=47a396b0-cc8e-4ffd-a841-57ed0c8a0ca7; Path=/; HttpOnly
14、推测其登录权限校验逻辑如下
-请求/tongyiLogin/authorize接口,获取一个url并在Cookie中设置SESSION的值
-请求登录接口,获取登录后的Cookie值HOLDONKEY 。
-在Cookie中设置SESSION 和HOLDONKEY ,去请求第一步返回的url(其中302携带HOLDONKEY,跳转的200携带SESSION)对SESSION进行提权操作
15、根据以上逻辑还原登录过程,并保存SESSION的值
16、使用保存的SESSION,+校验参数 请求接口,正确响应,并对结果解密,得到最终数据
17、至此,参数校验+结果解密+登录权限校验 完成
有问题欢迎评论、私信咨询。