记某次金融小程序数据加密及签名逆向
0X01 前言
某次对某金融小程序渗透测试,依旧是对数据包加密以及签名验证,以往遇到类似站点往往选择放弃,但是这次选择尝试逆一下,也分享一下此次渗透的过程,文笔粗糙,还请见谅
0X02 定位
先贴一张数据包:
请求头的参数不少、请求和响应的数据都被加密了
由于是小程序,于是决定先反编译一下小程序看源码,找下是怎么生成的
搜下关键字Encryptkey
,源码里找还是很快的,请求头中的几个参数以及加密的数据参数生成方法都在一块
由于静态代码不是很方便分析其生成的逻辑,选择用工具开启微信devtools进行断点调试
wx小程序开启devtools工具(建议用小号):https://github.com/JaveleyQAQ/WeChatOpenDevTools-Python
目前支持最新的版本如下:
在C:\Users\admin\AppData\Roaming\Tencent\WeChat\XPlugin\Plugins\RadiumWMPF
目录查看下自己的微信小程序版本
目前最新版的微信应该是不支持,那么就需要降低微信版本了,笔者用的是3.9.10.19
更换微信版本:https://github.com/tom-snow/wechat-windows-versions/releases
(PS:如果版本对了没有成功开启devtools可以将这两个文件删除,退出微信重进一下)
开启成功,打开devtools界面
找关键字下断点定位一下代码,和刚刚反编译看到的代码是一样的
0X03 分析加密和签名逻辑
开启devtools后,接下来才是最关键的步骤,通过调试分析逆向加解密生成的逻辑,利用伪代码生成新的参数
对于请求数据的加密,基本上就是在y方法中完成的,看到在y方法中,传入了三个参数,t,e,n
t既是未加密的数据,e这里是通过微信的接口获取的wechatcode,n则是一个公钥和私钥
在刚刚看源码的时候看到公钥和私钥是直接硬编码写在前端了,既然给出了固定的公钥和私钥,对于本次渗透来说可谓是大大降低难度
securityParam
先看securityParam参数的加密是如何进行的
图中圈出的代码就是securityParam参数加密的过程
r和i通过p()方法获取,然后分别赋值给salt和encryptkey,p()调用g()用来生成随机的字符串
再将原始参数t和salt、encryptkey一起给u()进行AES-CBC加密
那这个salt和encryptkey不就是iv和key吗,看下u的代码:
原生的AES加密,在线网站先解一波
到这里以为加密就解决了,然后重新构造一个数据包进行重放
显示签名验证失败,到这也正常,毕竟还几个参数没用上
接着看其他的参数
salt和encryptkey
通过上一步securityParam参数的分析,salt和encryptkey就是aes用来加解密的iv和key,至于放在header中,猜测是通过请求一起发送到后端,后端对请求参数用iv和key解密后,再将返回数据用相同的iv和key加密,返回到前端解密。
结合刚刚找到的公钥和私钥,以及请求头中的salt和encryptkey都是加密的,前端调试找到加密的代码
传入的参数为未加密的数据和publickey公钥,通过h()进行加密
h()里面的代码通过s.default.KJUR.crypto.Cipher.encrypt(t, r);
这行代码进行加密
这里的s是jsrsasign
依赖,调用的也就是原生RSA算法
所以salt和encryptkey利用公钥进行RSA加密
sign
同样的,按照前面的步骤,找到sign加密方法
利用y方法,将securityParam和加密后的值传入,通过私钥进行签名,这里调用的也是jsrsasign
,也是原生算法
0X04
至此,所有的参数都已经知道是如何生成的,
-
securityParam:原始数据进行AES-CBC加密
-
Salt:AES-CBC加密的IV,通过公钥进行RSA加密放在请求头中发送给后端
-
Encryptkey:AES-CBC加密的key,通过公钥进行RSA加密放在请求头中发送给后端
-
Timestamp:时间戳
-
Sign:防重放验证,将securityParam参数和加密后的值通过私钥进行签名
整体的逻辑就是前端随机生成iv和key对数据进行加密,并且又将aes加密的iv和key用RSA公钥加密一起带给后端,后端用私钥解密后再返回给前端,同时将每次请求都用私钥进行签名
由于用到的都是原生的算法,加密的iv和key都是前端发送的,所以我们可以直接固定iv和key,用其他代码实现该过程,这里我用的python来生成
将重新生成的参数替换,重放成功
至此分析结束,我们可以直接修改请求数据进行渗透测试,对于下一步自动化替换参数和加解密操作可以参考另一篇文章https://xz.aliyun.com/t/15969
利用插件进行自动替换请求头参数和加解密请求包和返回包,就可以愉快的进行测试了。
总结
整个分析的过程花费了不少时间,调试代码需要耐心和细节,相对来说没有特别的难,最后成功扣出算法后也算是一种正反馈