博客 / 詳情

返回

H5滲透實戰:從負數金額漏洞到簽名繞過

前言

免責聲明:本文僅供安全學習研究,所有測試均在授權環境或自建靶場中進行。嚴禁用於非法用途,否則後果自負。

某水卡系統漏洞實戰

此次實戰是針對混合開發APP的滲透測試,通過抓包提取APP內嵌的H5頁面,對其API接口進行安全測試。

常見混合開發框架:

Cordova

  • 技術棧:WebView + H5

  • 代表應用:早期銀行APP、政務APP

  • 特點:最早的混合開發方案,插件生態豐富

Ionic

  • 技術棧:Angular/React/Vue + WebView

  • 代表應用:企業OA、CRM系統

  • 特點:UI組件豐富,適合企業應用

原生WebView

  • 技術棧:原生殼 + H5頁面

  • 代表應用:各種物業/水電繳費APP

  • 特點:開發成本低,更新靈活,最常見

為什麼選擇混合開發APP?因為原生APP需要逆向、Hook等技術門檻較高,而混合APP內嵌H5頁面,只需抓包分析即可發現漏洞,是APP滲透的最佳入門目標。這次實戰目標就是從app提取的h5頁面進行挖掘(更偏向Web滲透)

混合APP容易測試的原因點如下:

  1. 業務邏輯在H5中,可直接抓包

  2. 前端JS代碼可查看,簽名算法可逆向

  3. 提取H5鏈接後可在瀏覽器中測試

如何判斷APP類型

最簡單的方法就是看請求包

舉個栗子(比如接口裏面帶有h5關鍵詞的):

GET https://h5.***/app/index.html

亦或者解包apk去搜索WebView相關代碼or查看assets目錄是否有H5文件

話不多説,直接開始實戰!本次實戰基於真實場景搭建的模擬靶場進行演示。

正文

由於充值後會立即重定向,瀏覽器F12抓不到完整請求,這裏用Reqable抓包。

直接將amount改為 -50,充值成功!這是典型的負數金額漏洞——後端未校驗金額正負,導致 balance + (-50) 使餘額反減。既然充值接口沒有校驗金額正負,那麼轉賬接口大概率也存在同樣的問題

轉賬功能在前端是進行了校驗的,跟充值一樣,轉賬後會立即重定向,瀏覽器F12抓不到完整請求,繼續使用Reqable抓包

轉賬也是一樣,存在相同的邏輯漏洞

雖然頁面展示的我轉賬至A-102是-50,但是我的餘額沒扣反加,餘額從349.48變成了399.48。原理很簡單:

我的餘額 = 100 - (-50) = 150 ← 不減反加

對方餘額 = 200 + (-50) = 150 ← 被扣錢了

emmm,思考ing...既然是水電卡系統,那麼充值也只是資金入口,真正的業務核心在繳費環節。繼續沿着業務流程測試電費繳納模塊,看看是否存在類似的漏洞。

【----幫助網安學習,以下所有學習資料免費領!加vx:YJ-2021-1,備註 “博客園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客户端安全檢測指南(安卓+IOS)

進入到繳費頁面,發現只有兩個接口

還是跟之前一樣測試是否能修改成負值進行充電勒

充電的接口與充值、轉賬接口不同,電費繳納接口增加了安全防護——請求中包含 sign 簽名參數:直接修改 amount 為 -100 後發送,返回"簽名驗證失敗"。這是一種常見的防篡改機制,後端會根據參數重新計算簽名並與請求中的 sign 比對。要繞過簽名校驗,需要逆向分析簽名算法。由於這是混合APP,簽名邏輯在前端JS中實現,我們可以直接分析。

直接全局搜索sign參數,觸發充值事件,斷點斷住了,明文就是amount加上meter_no和時間戳放到generateSign函數進行了加密。

進入到generateSign函數進行分析

function generateSign(params) {
    // 1. 獲取所有參數名,過濾掉sign本身,然後按字母順序排序
    // → ["amount", "meter_no", "timestamp"]
    const sortedKeys = Object.keys(params).filter(k => k !== 'sign').sort();
    // 2. 將參數按 key=value 格式拼接,用 & 連接
    let signStr = sortedKeys.map(k => `${k}=${params[k]}`).join('&');
    // 3. 在末尾追加密鑰(這就是簽名的關鍵!密鑰硬編碼在前端)
    signStr += '&key=WaterCard@2024#SecretKey';
    // 4. 對拼接後的字符串進行MD5哈希,得到簽名
    return md5(signStr);
}

簽名算法總結:

sign = MD5(參數按字母排序拼接 + &key=密鑰)

加密算法分析完之後,進行py模擬發包

跟之前充值,轉賬的後端邏輯一樣的,但是這次危害更大,因為不僅吸了錢還加了電費

負數度數 → 負數費用 → 扣負數 = 加錢

電錶讀數直接加負數 → 讀數倒退

結尾:

本文僅供安全學習研究使用,請勿用於非法用途。

更多網安技能的在線實操練習,請點擊這裏>>

  

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.