業(yè)數(shù)字化爆火背后:餐飲小程序與儲值系統(tǒng)的安全漏洞及低成本防護)
1. 從一只蝦到一條鏈爆火背后被忽視的攻擊面小龍蝦這個品類在過去兩年里經(jīng)歷了一輪罕見的爆發(fā)式增長。從街邊大排檔到連鎖品牌從線下堂食到預制菜電商整條產(chǎn)業(yè)鏈在極短時間內(nèi)完成了數(shù)字化改造。點單小程序、會員系統(tǒng)、供應鏈管理平臺、直播帶貨后臺、外賣聚合接單系統(tǒng)——這些工具在半年內(nèi)被倉促塞進了原本只靠一部電話和一本手寫賬本就能運轉(zhuǎn)的生意里。我之所以關注這個話題是因為身邊好幾個做餐飲SaaS的朋友都在聊同一件事客戶催著上線安全評審基本為零。一個典型的場景是某連鎖品牌為了趕在旺季前上線會員儲值功能從立項到上線只用了十一天。十一天里前端調(diào)通了支付接上了數(shù)據(jù)庫建好了但沒有人問過一句這個系統(tǒng)的接口有沒有做頻率限制用戶手機號在數(shù)據(jù)庫里是明文還是加密后臺管理頁面的登錄態(tài)是怎么維持的這不是個別現(xiàn)象。當一個行業(yè)突然涌入大量熱錢和流量時技術團隊的第一優(yōu)先級永遠是能不能跑起來而不是跑起來之后會不會被人從后面踹一腳。小龍蝦產(chǎn)業(yè)的數(shù)字化恰恰處在這個階段——業(yè)務跑得比安全快而攻擊者最喜歡的就是這種時間差。這篇文章想聊的不是某個具體漏洞的利用教程而是從從業(yè)者視角出發(fā)把這類爆火行業(yè)數(shù)字化中反復出現(xiàn)的幾類安全問題拆開來看。我會講清楚每一類問題的成因、攻擊者通常從哪個角度切入、以及在實際項目中可以怎么低成本地堵住這些口子。適合正在做餐飲/零售類系統(tǒng)的開發(fā)者、剛接手這類項目的技術負責人以及對業(yè)務安全感興趣的讀者參考。2. 點單小程序里的數(shù)據(jù)暴露從手機號到儲值余額2.1 為什么這類系統(tǒng)天生容易泄露數(shù)據(jù)餐飲類小程序的開發(fā)節(jié)奏和傳統(tǒng)企業(yè)軟件完全不同。傳統(tǒng)企業(yè)軟件有明確的需求文檔、測試周期和上線評審而餐飲小程序往往是老板今天說要加個功能明天就要看到效果。這種節(jié)奏下開發(fā)者的注意力全部集中在功能實現(xiàn)上數(shù)據(jù)安全往往被默認成框架會幫我處理。但框架不會幫你處理業(yè)務層面的數(shù)據(jù)暴露。舉個最常見的例子用戶在小程序里查看自己的訂單詳情前端發(fā)起一個請求后端返回一個包含訂單信息的JSON。如果這個接口的設計是傳入訂單ID返回訂單詳情而沒有校驗這個訂單ID是否屬于當前登錄用戶那么任何人只要把訂單ID改一個數(shù)字就能看到別人的訂單——包括姓名、手機號、配送地址、消費金額。這類問題在安全圈里叫越權訪問分為水平越權和垂直越權兩種。水平越權是同級用戶之間的數(shù)據(jù)互訪比如A用戶能看到B用戶的訂單垂直越權是低權限用戶訪問高權限功能比如普通用戶能進管理后臺。餐飲類系統(tǒng)里水平越權是最常見的因為訂單查詢、會員信息查詢、優(yōu)惠券領取這些功能天然就是按ID取數(shù)據(jù)的模式。2.2 一個真實的排查思路假設你接手了一個已經(jīng)上線的點單系統(tǒng)想快速判斷它有沒有越權問題可以按下面的順序過一遍列出所有傳入ID返回數(shù)據(jù)的接口。打開瀏覽器的開發(fā)者工具在小程序里把每個頁面都點一遍記錄下所有請求URL和參數(shù)。重點關注包含id、orderId、userId、memberId這類參數(shù)的接口。用兩個賬號做交叉測試。注冊兩個普通賬號分別下單然后用賬號A的登錄態(tài)去請求賬號B的訂單ID。如果返回了數(shù)據(jù)說明存在水平越權。檢查返回字段。即使接口做了歸屬校驗也要看返回的字段里有沒有多余信息。比如訂單詳情接口返回了用戶的完整手機號但前端只展示了后四位——那這個完整手機號就是多余的暴露面。檢查批量接口。有些系統(tǒng)為了減少請求次數(shù)會提供批量查詢接口比如傳入一個ID數(shù)組返回多條數(shù)據(jù)。這類接口如果沒做逐條歸屬校驗危害比單條查詢更大。注意做這類測試時務必使用自己注冊的測試賬號不要嘗試訪問真實用戶的數(shù)據(jù)。未經(jīng)授權的測試可能觸犯法律。2.3 修復方案與成本評估越權問題的修復其實不復雜核心原則就一條每一個數(shù)據(jù)查詢都必須帶上當前登錄用戶的身份條件。具體到代碼層面就是把WHERE id ?改成WHERE id ? AND user_id ?。如果用的是ORM框架就是在查詢條件里強制附加當前用戶的ID。但實際項目中這個修復往往會遇到阻力。原因在于有些接口在設計之初就沒有考慮用戶維度比如根據(jù)訂單號查詢訂單這個功能可能是給客服用的客服需要能查任何訂單。這種情況下正確的做法是把接口拆成兩個面向用戶的接口強制帶用戶ID面向客服的接口走獨立的權限校驗。成本方面一個中等規(guī)模的餐飲小程序大概有30到50個接口其中涉及數(shù)據(jù)查詢的可能有20個左右。如果代碼結(jié)構(gòu)清晰一個熟練的開發(fā)者大概需要兩到三天完成排查和修復。如果代碼是外包做的、結(jié)構(gòu)混亂時間可能要翻倍。但相比數(shù)據(jù)泄露后的公關成本和監(jiān)管處罰這個投入是值得的。3. 儲值余額與優(yōu)惠券黑產(chǎn)眼中的高價值目標3.1 為什么儲值功能是重災區(qū)小龍蝦品類的客單價不低很多品牌會推儲值優(yōu)惠來鎖定復購。比如充500送100用戶賬戶里就有了600元的余額。這個余額在系統(tǒng)里就是一個數(shù)字字段而這個數(shù)字字段的讀寫邏輯往往就是黑產(chǎn)重點關照的對象。我見過最離譜的一個案例是某品牌的儲值系統(tǒng)在充值回調(diào)接口里沒有做簽名校驗。也就是說支付平臺通知用戶充值成功的那個請求任何人都可以偽造。攻擊者只需要構(gòu)造一個包含用戶ID和充值金額的請求發(fā)給服務器賬戶余額就直接加上去了。這個漏洞從上線到被發(fā)現(xiàn)中間隔了將近兩個月?lián)p失的具體金額沒有對外公布但據(jù)說足夠讓技術負責人直接走人。即使做了簽名校驗還有一類問題叫并發(fā)競爭。比如用戶賬戶里有100元余額同時發(fā)起兩筆80元的消費請求。如果系統(tǒng)在處理時是先讀余額、判斷夠不夠、再扣減那么兩個請求可能同時讀到100元都判斷為夠然后各自扣減80元最終余額變成-60元。這就是典型的競態(tài)條件漏洞。3.2 支付回調(diào)的安全設計要點支付回調(diào)是儲值系統(tǒng)的命門設計時至少要滿足以下幾點簽名驗證支付平臺的回調(diào)請求必須攜帶簽名服務端要用約定的密鑰驗證簽名。簽名不通過的請求直接丟棄不要返回任何業(yè)務信息。金額校驗回調(diào)里的金額必須和訂單創(chuàng)建時的金額一致。有些系統(tǒng)只校驗訂單號不校驗金額攻擊者可以把1元充值的回調(diào)改成1000元。冪等處理同一個回調(diào)可能被重復發(fā)送系統(tǒng)必須保證同一筆訂單只處理一次。通常的做法是在數(shù)據(jù)庫里記錄已處理的回調(diào)ID處理前先查重。異步確認不要依賴前端跳轉(zhuǎn)結(jié)果來判定支付成功必須以服務端收到的回調(diào)為準。前端跳轉(zhuǎn)可以被偽造服務端回調(diào)相對可靠。3.3 優(yōu)惠券系統(tǒng)的常見邏輯漏洞優(yōu)惠券的問題通常不在技術層面而在業(yè)務邏輯層面。比如無限領取領券接口沒有做頻率限制也沒有校驗用戶是否已領過。攻擊者寫個腳本就能把一批券全部領走。疊加使用系統(tǒng)允許同一訂單使用多張優(yōu)惠券但沒有限制疊加規(guī)則。攻擊者通過組合不同券種可以把訂單金額壓到極低甚至負數(shù)。過期券復用券過期后狀態(tài)沒有及時更新或者更新了但核銷接口沒有校驗狀態(tài)導致過期券仍可使用。退款不退券用戶用券下單后申請退款系統(tǒng)退了錢但沒有收回優(yōu)惠券用戶相當于白賺一張券。這些問題的共同點是它們不是代碼寫錯了而是業(yè)務規(guī)則沒有想清楚。修復方式通常是在關鍵操作上加校驗、加限制、加日志。比如領券接口加用戶維度的頻率限制核銷接口加券狀態(tài)和有效期的雙重校驗退款流程里加券的回收邏輯。4. 供應鏈與后臺系統(tǒng)被低估的入口4.1 后臺管理頁面的弱口令問題前臺小程序的安全做得再好如果后臺管理頁面用的是admin/123456那一切努力都白費。餐飲行業(yè)的后臺系統(tǒng)有個特點使用者往往是不懂技術的店長或運營人員他們傾向于設置簡單好記的密碼而且多個系統(tǒng)共用同一個密碼。更麻煩的是很多后臺系統(tǒng)的登錄頁面直接暴露在公網(wǎng)上沒有做IP白名單也沒有做登錄失敗鎖定。攻擊者可以用自動化工具對后臺登錄接口進行撞庫成功率遠比想象中高。我建議的做法是后臺系統(tǒng)盡量不直接暴露在公網(wǎng)通過內(nèi)網(wǎng)訪問或加一層訪問控制。強制密碼復雜度至少8位包含大小寫字母和數(shù)字。登錄失敗5次后鎖定賬戶15分鐘或者引入圖形驗證碼。對后臺的所有操作記錄審計日志包括登錄、查詢、修改、導出。4.2 供應鏈數(shù)據(jù)的敏感性小龍蝦供應鏈涉及采購價格、供應商信息、庫存數(shù)量、物流軌跡等數(shù)據(jù)。這些數(shù)據(jù)在競爭激烈的餐飲行業(yè)里屬于核心商業(yè)機密。如果被競爭對手拿到可以直接推算出你的成本結(jié)構(gòu)和采購渠道。供應鏈系統(tǒng)的安全重點和前臺不同它更關注訪問控制和數(shù)據(jù)脫敏。比如采購價格字段只對采購角色可見運營角色只能看到庫存數(shù)量。供應商聯(lián)系方式在非必要場景下脫敏展示。數(shù)據(jù)導出功能加審批流程防止內(nèi)部人員批量導出后帶走。這些措施聽起來簡單但在實際項目中往往被忽略因為系統(tǒng)上線時通常只考慮了功能能不能用沒有考慮誰能用哪些功能。4.3 第三方接口的信任邊界餐飲系統(tǒng)通常會對接多個第三方服務支付、短信、地圖、外賣平臺、電子發(fā)票等。每對接一個第三方就多一個外部入口。如果第三方接口的調(diào)用沒有做鑒權或者回調(diào)地址暴露在外就可能被利用。一個常見的疏忽是短信接口沒有做頻率限制。攻擊者發(fā)現(xiàn)你的短信發(fā)送接口后可以寫腳本瘋狂調(diào)用導致你的短信費用暴漲同時用戶被騷擾。修復方式是在發(fā)送短信前加圖形驗證碼并對同一手機號、同一IP做頻率限制。另一個疏忽是外賣平臺的訂單回調(diào)沒有做來源校驗。攻擊者可以偽造訂單回調(diào)在你的系統(tǒng)里生成虛假訂單干擾正常運營。修復方式是校驗回調(diào)請求的簽名或來源IP。5. 從應急到常態(tài)小團隊的安全建設路徑5.1 先做資產(chǎn)梳理再談防護很多小團隊一提到安全建設第一反應是買個WAF或者上個堡壘機。但在不知道自己要保護什么的情況下買再多設備也是浪費。第一步應該是資產(chǎn)梳理把所有的域名、服務器、數(shù)據(jù)庫、接口、第三方服務都列出來標注每個資產(chǎn)的重要程度和負責人。資產(chǎn)梳理的產(chǎn)出是一張表大概長這樣資產(chǎn)類型具體資產(chǎn)重要程度負責人當前防護措施域名小程序API域名高后端A無服務器生產(chǎn)環(huán)境應用服務器高運維B基礎防火墻數(shù)據(jù)庫用戶數(shù)據(jù)庫高后端A無審計接口支付回調(diào)接口高后端A簽名校驗第三方短信服務中后端C無頻率限制這張表不需要很精確但必須要有。有了它你才能判斷哪些地方需要優(yōu)先投入。5.2 用最低成本堵住最大的洞對于資源有限的小團隊安全建設應該遵循二八原則用20%的投入解決80%的風險。根據(jù)我的經(jīng)驗以下幾項是性價比最高的接口鑒權全覆蓋確保每一個需要登錄才能訪問的接口都做了身份校驗每一個數(shù)據(jù)查詢都帶了用戶歸屬條件。這一項能擋住大部分越權問題。關鍵操作加日志登錄、支付、退款、修改密碼、導出數(shù)據(jù)這些操作必須記錄日志包括操作人、時間、IP、操作內(nèi)容。出問題時日志是唯一的追溯依據(jù)。數(shù)據(jù)庫定期備份備份要離線保存并且定期驗證可恢復性。很多團隊做了備份但從來沒恢復過真出事時才發(fā)現(xiàn)備份是壞的。依賴組件及時更新框架、中間件、第三方庫的已知漏洞是攻擊者的首選目標。建立一個簡單的依賴清單定期檢查更新。5.3 把安全寫進開發(fā)流程安全問題的根源往往不在技術而在流程。如果每次上線都是先上再說那安全問題永遠只能靠事后補救。小團隊可以嘗試把以下幾件事寫進開發(fā)流程上線前檢查清單包括接口鑒權、敏感數(shù)據(jù)加密、日志記錄、錯誤信息脫敏等。不需要很復雜一頁紙就夠。代碼評審關注安全在代碼評審時除了看邏輯對不對也看一眼有沒有明顯的安全問題比如SQL拼接、硬編碼密鑰、日志打印敏感信息。定期做一次簡單掃描用開源的掃描工具對線上系統(tǒng)做一次基礎掃描看看有沒有暴露的敏感文件、弱口令、已知漏洞。頻率不用很高一個季度一次就行。這些措施不會讓你的系統(tǒng)變得絕對安全但能讓攻擊者的成本顯著提高。在安全領域讓攻擊者覺得不劃算往往比追求無懈可擊更現(xiàn)實。6. 一個值得反復提醒的細節(jié)日志里的敏感信息最后聊一個特別容易被忽略、但危害很大的問題日志泄露。開發(fā)者在排查問題時習慣把請求參數(shù)和響應內(nèi)容都打到日志里。這本身沒問題問題在于很多系統(tǒng)會把用戶的手機號、身份證號、銀行卡號、密碼明文打進日志。而這些日志往往存儲在多個地方應用服務器本地、日志收集系統(tǒng)、監(jiān)控平臺、甚至開發(fā)者的本地電腦。一旦這些日志被泄露危害不亞于數(shù)據(jù)庫被拖。而且日志泄露往往更隱蔽因為很多人根本不知道自己的日志里有什么。我的建議是在日志框架里配置脫敏規(guī)則對手機號、身份證號、銀行卡號等字段自動打碼。禁止在日志里打印密碼、密鑰、Token等憑證信息。日志的訪問權限要控制不是所有開發(fā)人員都需要看生產(chǎn)日志。日志的保留時間要有策略不需要永久保存的日志定期清理。這些操作不需要太多技術投入但能堵住一個非常隱蔽的泄露渠道。我在實際項目中見過太多數(shù)據(jù)庫加密做得很好但日志里全是明文手機號的情況希望你不要成為下一個。