一次对小程序的安全测试
发布日期:2024-05-19 浏览次数: 专利申请、商标注册、软件著作权、资质办理快速响应热线:4006-054-001 微信:15998557370
前言 自2019年开始,中央网信办、工业和信息化部、公安部和国家市场监管总局在全国范围内组织开展App违法违规收集使用个人信息专项治理工作,加大个人信息保护力度。《个人信息保护法》增加了对于App个人信息保护的专门性规定。而如今小程序等新应用形态不断出现,相比App而言,无论开发还是使用门槛更为简便,小程序的安全继承了微信APP整体的安全建设,因此无需像传统的APP测试对客户端本身进行测试,测试的重点在于服务端,即小程序与后端进行交互过程中存在的安全风险。 小程序解包 以往反编译小程序源码都是要从移动端获取,相较于电脑端来说比较麻烦。因本机为Mac电脑,以下方法适用于Mac端wxapkg解密。使用的工具为mac_wxapkg_decrypt 该工具提供了2种解密的方法, 一种是提取解密用的key, 一种是直接让小程序自动解密。这里我使用了第二种方法,通过更改_agent.js里小程序的路径,然后HOOK,自动产生解密后的文件。首先找到Mac小程序地址。 /Users/XXXX/Library/Group Containers/xxxx.com.tencent.xinWeChat/Library/Caches/xinWeChat/xxxxxxxxxx/WeApp/LocalCache/release/ 当我们Mac端微信访问小程序后,会按照AppID生成对应的目录,根据AppID寻找要解包的小程序 然后修改_agent.js文件中小程序的路径以及解密后的文件路径。 搜索本机小程序的进程 ps -ef |grep Mini 利用frida加载_agent.js脚本进行HOOK,生成解密后的wxapkg 小程序反编译 获取了解密后的小程序包,那么下面就开始进行反编译获取源代码。通过github搜索相关小程序反编译工具,发现几乎都已被删除,要么开始收费。最后找到了一款基于wxappUnpacker改进的开源项目,测试发现还可以使用。下载地址:https://gitee.com/ksd/wxappUnpacker 使用方法也很简单,首先安装依赖 npm install esprimanpm install css-treenpm install cssbeautify npm install vm2npm install uglify-esnpm install js-beautify 当检测到wxapkg为子包时, 添加-s参数指定主包源码路径即可自动将子包的wxss,wxml,js解析到主包的对应位置下,完整流程大致如下: 获取主包和若干子包解包主包 ./bingo.sh testpkg/master-xxx.wxapkg解包子包 ./bingo.sh testpkg/sub-1-xxx.wxapkg -s=../master-xxx 运行后即可成功反编译小程序。 然后我们就可以利用开发者工具进行还原小程序。文件夹中的 HTML、WXSS 等文件主要是存放了页面结构、小程序页面样式等内容,对于安全测试来说重点分析文件中JS,如果小程序在与后端服务器进行了加密传输,可以根据传输中的加密参数值进行跟踪,逐步分析参数是进行如何加密的。 小程序抓包安全测试 对于PC端来说,小程序的抓包是比较简单的,直接设置系统代理,然后打开burp也设置代理就能抓到https。设置代理抓包后,运行小程序并抓取登录数据包,发现账号密码以及返回信息均被国密SM2加密传输。所以我们可以通过提取小程序的源码信息,获得小程序在传输过程中进行的数据的加密方式,分析来得出整个加密算法。 通过注册登录后查看个人信息,发现URL参数为明显的数字编号,通过遍历编号发现返回包内容信息发生了变化,猜测该小程序存在越权漏洞,可通过该漏洞获取个人敏感信息。 获取小程序国密SM2密钥 通过反编译获取到的SM2的私钥可对密文进行解密,也可以将泄露的公钥进行加密用户名和密码字典,进行爆破账户。 公钥:04B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5A24620207 私钥:00B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E3D5 最终可通过编写脚本,利用该漏洞可批量解密获取明文的个人敏感信息。 import sys from gmssl import sm2 from base64 import b64encode, b64decode # sm2的公私钥 SM2_PRIVATE_KEY = '' SM2_PUBLIC_KEY = '' sm2_crypt = sm2.CryptSM2(public_key=SM2_PUBLIC_KEY, private_key=SM2_PRIVATE_KEY) # 加密 def encrypt(info): encode_info = sm2_crypt.encrypt(info.encode(encoding="utf-8")) encode_info = b64encode(encode_info).decode() # 将二进制bytes通过base64编码 return encode_info # 解密 def decrypt(info): decode_info = b64decode(info.encode()) # 通过base64解码成二进制bytes decode_info = sm2_crypt.decrypt(decode_info).decode(encoding="utf-8") return decode_info if __name__ == "__main__": action = sys.argv[1] # 取命令中的加解密动作 contact_info = sys.argv[2] # 取命令中需要加解密的内容 if action == "encrypt": encrypted_contact_info = encrypt(contact_info) print(encrypted_contact_info) if action == "decrypt": decrypted_contact_info = decrypt(contact_info) print(decrypted_contact_info) 总结 通过加密参数为关键字进行源代码全局搜索,从而获取到该小程序的加密方式,可以尝试进行越权访问、SQL注入、账号密码的爆破等漏洞的安全测试,也有一些小程序使用云存储,可能会将一些oss的secret key硬编码放在小程序源代码文件中。 文章来源:Tide安全团队 黑白之道发布、转载的文章中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途及盈利等目的,否则后果自行承担! 如侵权请私聊我们删文 END