案例介绍

闲来无事,在测试某小程序的时候,发现存在sessionkey泄露漏洞。具体流程如下:

1、打开小程序后,点击【用户一键登录】:

image.png

2、burp抓包,发现在请求参数中携带了几个比较敏感的字段,如下所示:

image.png

三个敏感参数

  • encryptedData
  • iv
  • session_key

3、参考上篇文章,微信小程序登录流程。知道session_key的作用之一是将小程序前端从微信服务器获取到的encryptedData 解密出来。

服务端获取开放数据

微信会对开放数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。

image-20240506141657312

签名校验以及数据加解密涉及用户的会话密钥 session_key。 开发者应该事先通过 wx.login 登录流程获取会话密钥 session_key 并保存在服务器。为了数据不被篡改,开发者不应该把 session_key 传到小程序客户端等服务器外的环境。

image.png

加密数据解密算法

接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。 解密算法如下:

  1. 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
  2. 对称解密的目标密文为 Base64_Decode(encryptedData)。
  3. 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
  4. 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。

微信官方提供了多种编程语言的示例代码(点击下载)。每种语言类型的接口名字均一致。

Python本地实现

# -*- utf-8 -*-
# @Time: 2024-04-26 15:42
# @Author: muhe Jing
# @File: decrypt.py
# @Software: PyCharm


import urllib
from urllib import parse
import base64
from Crypto.Cipher import AES


def decrypt(data, key, i_v):
data = base64.b64decode(urllib.parse.unquote(data))
key = base64.b64decode(urllib.parse.unquote(key))
i_v = base64.b64decode(urllib.parse.unquote(i_v))

print(data)
print(key)
print(i_v)

cipher = AES.new(key, AES.MODE_CBC, i_v)
decrypted = cipher.decrypt(data)
print(decrypted.decode)
return decrypted


if __name__ == '__main__':
encryptedData = input("输入获取到的encryptedData:")
session_key = input("输入获取到的session_key:")
iv = input("输入获取到的iv:")
decrypt(encryptedData, session_key, iv)

img

这块可以看到解密之后,在明文字符串后面有特殊字符 “\0e”

这主要是因为AES算法填充使用的是PKCS#7,该填充模式的特性如下:

image-20240506142355445

所以,这块填充个了 14字节的 “\x0e”。。。