您现在的位置是:首页 > 技术人生 > 后端技术后端技术
js解密之获取中高风险地区接口(一)
高晓波2023-02-13【后端技术】人已围观
简介最近部门做了一个疫情信息填报的小程序,里面涉及到行程码途经地及来宁地区是否为中高风险的智能判断,加上数据治理项目组那边也需要获取中高风险地区数据,所以开始寻找全国中高风险地区发布的来源。
一、前言
最近部门做了一个疫情信息填报的小程序,里面涉及到行程码途经地及来宁地区是否为中高风险的智能判断,加上数据治理项目组那边也需要获取中高风险地区数据,所以开始寻找全国中高风险地区发布的来源。
二、数据来源
通过网上搜索后发现,中高风险地区的发布有以下来源:
本地宝采用的是服务端渲染,想拿到中高风险地区要解析dom,比较麻烦。
国务院客户端无疑是最权威、最及时的发布方,猜测其他地方的风险地区信息来源都是这儿。但是有个比较棘手的问题,国务院客户端小程序默认是微信登陆,无法通过接口调用的方式进行模拟;加上小田、小鑫的测试发现,cookie每天0点会自动失效,意味着每天都要人工进行登陆拿取cookie,长期来看无疑是个麻烦的工作,如果哪天忘了更新cookie,会造成信息更新不及时的后果。
最终,通过苦苦寻找发现了国家卫健委web发布端,http://bmfw.www.gov.cn/yqfxdjcx/risk.html,这为风险地区的自动获取带来了新的途径。
三、接口难点
通过浏览器调试模式,查看接口参数返回值等情况发现,参数中存在时间戳和加密签名。
那么,就存在以下问题:
- 1.如果传参的时间戳与当前时间距离超过180秒会报错,意味着我们不能拿固定参数进行接口调用
- 2.时间戳参数参与签名参数的生成,意味着我们光改时间戳为当前时间戳是没有用的,时间戳变了,签名参数校验会不通过
- 3.签名参数的生成方式。
四、解决方案
1. 模拟操作浏览器
如:开源的Selenium,或是直接通过api操作chrome或Chromium。此种方式的好处是简单粗暴,缺点是比较耗费资源,并且本质上是浏览器真实的访问目标站点,需要加载运行各种资源,故效率较低。一般对于深度加密防爬的站点实在没有办法才采取这样的方式,本篇暂不讨论。
2. js解密
此种方式优点是直接调用api,效率自然是最高,另外大部分接口返回数据为json,数据解析也是最为方便;缺点是对技术要求较高且需要花费时间进行js解密。本篇我们主要讨论此方式。
五、签名生成方式分析
想要成功的获取到数据,必须弄清楚参数中的signatureHeader生成方式,以及其他一些关键参数的来源,如:参数中的key、appId、paasHeader、nonceHeader。
当然,部分参数可以写死,但如果后面发布方进行了参数更新,那么接口调用也随之会失效。所以以上参数,我们都尽量采用动态获取的方式。
1. 搜索关键字: signatureHeader
我们以参数中的signatureHeader
作为关键字,在js中进行搜索,搜索结果如下:
存在signatureHeader
关键字的js有两处,这两处都在risk.dc7936e2.js中,从Respons中我们看到,这是一段经过压缩加密处理的js。
2. 对risk.js进行格式化
我们利用chrome调试工具对js代码格式化,再将格式化后的js代码粘贴到代码编辑器中,方便我们阅读分析
3. js代码分析
首先我们还是找到signatureHeader关键字处。
function v(e) {
if (!e.commonParams)
return e;
var t = c.value;
return e.data = e.data || {},
Object.assign(e.data, {
appId: "NcApplication",
paasHeader: o,
timestampHeader: t,
nonceHeader: s,
signatureHeader: CryptoJS.SHA256(t + r + s + t).toString(CryptoJS.enc.Hex).toUpperCase()
}),
e
}
上述代码我们解读一下:接口参数appId
值为NcApplication,参数paasHeader
值为变量o,参数timestampHeader
值为变量t,从参数名和值上猜测为时间戳,参数nonceHeader
值为变量s,参数signatureHeader
的生成方式是变量t+r+s+t
拼接后进行sha256加密。
参数追踪
上述代码我们看到var t = c.value;
, 再追踪参数c:
var a = n("bc3a"),
i = n.n(a),
r = (n("b680"),n("25f0"),"23y0ufFl5YxIyGrI8hWRUZmKkvtSjLQA"),
s = "123456789abcdefg",
o = "zdww",
c = {
value: 0
};
发现c.value的默认值是0,猜测一定有其他地方更改了这个值。
另外,从此段代码中我们发现了变量s(对应接口参数nonceHeader)的值为123456789abcdefg
;变量r前面两个n("b680")和n("25f0")是干扰项,真正的值为23y0ufFl5YxIyGrI8hWRUZmKkvtSjLQA
;变量o(对应接口参数paasHeader)的值为zdww
。
继续追踪变量c发现:
function d(e) {
return c.value = (Date.now() / 1e3).toFixed(),
e
}
原来c.value是个10位时间戳,所以,变量t和我们猜测的一样,为时间戳。
参数key查找
我们再看一下接口发送的请求参数:
{
"key": "3C502C97ABDA40D0A60FBEE50FAAD1DA",
"appId": "NcApplication",
"paasHeader": "zdww",
"timestampHeader": "1658923498",
"nonceHeader": "123456789abcdefg",
"signatureHeader": "5590D43894BA76A541AB0403705BE08BF5B1AB17E100FC325631A25A143E8D62"
}
其中的appId,paasHeader,timestampHeader,nonceHeader我们都已经知道从何而来,signatureHeader也知道是如何产生的:sha256(t+r+s+t)
,拿浏览器的参数进行反向验证:t的值为:1658923498
r的值为:23y0ufFl5YxIyGrI8hWRUZmKkvtSjLQA
s的值为:123456789abcdefg
t+r+s+t值为:165892349823y0ufFl5YxIyGrI8hWRUZmKkvtSjLQA123456789abcdefg1658923498
进行sha256加密后为:
5590d43894ba76a541ab0403705be08bf5b1ab17e100fc325631a25a143e8d62
,计算得出的值与我们从浏览器中得到的参数signatureHeader一致,验证了我们的分析没有错。那么,现在还剩下参数key。我们在js代码中搜索参数key的值:3C502C97ABDA40D0A60FBEE50FAAD1DA:
var j = "243D215B2CA449ECABF1E6C93B7D973C",
x = "2CA32596474B4077834CCC191D351839",
O = "3C502C97ABDA40D0A60FBEE50FAAD1DA";
key的值为变量O的值,继续追踪:
function k() {
return _({
data: {
key: O
}
}).then((function(e) {
return e.data
}))
}
k函数中,将变量O的值赋给了key。因为上面定义了3个变量j、x、O,而赋值的是O,猜测后面有可能会换成其他的。
至此,接口中所有参数的值都已经搞定。
Tags:js解密
很赞哦! ()
相关文章
随机图文
-
通过Redis限制API调用次数
最近在做微信公众号返利机器人,通过曲线救国的方式拿到的淘宝客工具商权限(用别人的App Key),在服务器搭建了透传程序。 使用过程中发现一个问题:阿里妈妈对淘宝API的调用频率有限制,报错信息反馈是40次/秒。 -
Springboot集成quartz定时任务可视化配置
使用quartz定时任务已经有一段时间了,今天记录一下Springboot 2.x集成Quartz。 -
SpringBoot排除自动配置
SpringBoot的自动配置给我们开发带来了极大的便利,但有些时候也带来了一些问题。 问题场景: 该项目是基于Springboot + dubbo的微服务架构,框架结构web + facade + service,某 -
mybatis plus生成实体entity没有id
总是写很多重复的增删改查毫无意义,浪费生命,于是乎准备弄一个增删改查代码生成工具。网上查了一下mybatis plus挺好的,于是乎打开官网 Quick Start!按照官网的演示栗子:// 演示