微信小程序的任意用戶登錄實戰
NO.1
小程序開放數據獲取基本流程
小程序可以通過各種前端接口獲取微信提供的開放數據。考慮到開發者服務端也需要獲取這些開放數據,微信提供了兩種獲取方式:
· 方式一:開發者后臺校驗與解密開放數據
· 方式二:云調用直接獲取開放數據(云開發)
本文簡單分享一下開發者后臺校驗與解密開放數據部分的漏洞形成與案例。

為了保證數據安全,微信會對用戶數據進行加密傳輸處理,所以小程序在獲取微信側提供的用戶數據(如手機號)時,就需要進行相應的解密,這就會涉及到session_key。
NO.2
漏洞形成
1、開發者后臺校驗與解密開放數據
小程序授權時若通過微信處獲取用戶信息,則需要調用接口獲取登錄憑證(code)。通過憑證獲取用戶登錄信息,即用戶對當前小程序的唯一標識(openid)、用戶對小程序主體的唯一標識(unionid)、用戶本次登錄的會話密鑰(session_key)等信息。
代碼及數據包信息如下:

授權后小程序可獲取用戶信息,微信對用戶信息做AES加密處理,即利用session_key、iv對用戶數據進行加密,生成加密參數encryptedData。其中,session_key指的是會話密鑰,可以簡單理解為微信開放數據AES加密的密鑰,它是微信服務器給開發者服務器頒發的身份憑證,這個數據正常來說是不能通過任何方式泄露出去的。小程序若存在session_key泄露漏洞的情況,則代表微信側傳遞的用戶數據有被泄露、篡改等風險。
數據包信息如下:

2、數據加解密算法
涉及用戶敏感數據的加密參數encryptedData,需iv及session_key通過AES解密,具體加解密算法如下:
1. 對稱解密使用的算法為 AES-128-CBC,數據采用PKCS#7填充。
2. 對稱解密的目標密文為 Base64_Decode(encryptedData)。
3. 對稱解密秘鑰 aeskey = Base64_Decode(session_key), aeskey 是16字節。
4. 對稱解密算法初始向量 為Base64_Decode(iv),其中 iv 由數據接口返回。
3、漏洞成因
當用戶存在session_key泄露,可對當前用戶的encryptedData進行解密,并修改用戶登錄信息,例如手機號等。修改為其他用戶信息后,對新信息進行加密并重放,可實現任意用戶登錄。其中,session_key可能泄露的具體如下:
1. Code2Session接口https://XXX/ /OnLogin?code=0031VH0w300XXX
wx.login 接口獲得臨時登錄憑證code后傳到開發者服務器,生成session_key
2. 在解密開放數據時, 將服務端中的session_key傳送至小程序前端,直接在前端進行解密,泄露session_key
NO.3
漏洞案例
發現當用戶在授權小程序登錄時,存在sessionKey泄露,導致該小程序可以使用任意手機號進行綁定登錄,造成任意用戶登錄漏洞。數據包關鍵信息如下:

綁定手機號中關鍵參數為encryptedData、iv、sessionKey。其中encryptedData為綁定用戶的手機號、appid等信息;iv為偏移量;sessionkey為會話密鑰,是微信開放數據AES加密的密鑰,它是微信服務器給開發者服務器頒發的身份憑證,這個數據正常來說是不能通過任何方式泄露出去的。當小程序session_key泄露,則微信側傳遞的用戶信息可篡改。
對小程序進行任意用戶登錄,測試流程如下:
1.手機綁定處數據包信息如下:

2.利用iv及sessionKey對encryptedData進行解密,其中iv和sessionkey均為base64加密,但正常解密后上述兩參數為字節碼,無法正常對encryptedData參數進行解密,利用腳本解密結果如下:

3.修改參數phoneNumber為其他賬號,再進行加密,并用該結果替換數據包中encryptedData結果如下:

4.利用小程序接口、userId及token訪問用戶信息,如下:
當前登錄用戶手機號為13888888888,任意用戶登錄成功。
NO.4
修復建議
請盡快在網絡請求中,去除請求和響應中的session_key字段及其對應值,后續也不應該將session_key傳到小程序客戶端等服務器外的環境,以便消除風險。