一、序言
在Web開發中,總有一些接口需要暴露在用戶認證前訪問,短信發送接口特別是短信驗證碼注冊接口便是其中典型的一類,這類接口具有如下特點:
- 流量在用戶認證之前
流量在用戶認證之前,意味着無法獲取用戶ID
等唯一標識符信息對流量限流
- 手機號未知
手機號未知意味着無法對待發送短信的手機號做精准檢測,判斷是否是合法的手機號。通過正則表達式判斷手機號連號過多,容易滋生短信盜刷。
本文將重點聚焦接口的防盜刷實踐。
二、盜刷流量
在解決防盜刷之前先認識盜刷流量的特點和防盜刷的目標。
(一)防盜刷的目標
1、減少盜刷的總量
如果能將盜刷的頻率控制在60秒
之外,那么單日盜刷的最大數量為24*60=1440
。假如系統入侵者發現請求頻率間隔在60秒以上,那么可自動勸退入侵者,原因是投入與產出不匹配。
實際上盜刷流量以秒級
甚至毫秒級
刷新,對系統造成明顯的損害。
2、回避周期性盜刷
周期性盜刷隱匿性更高,對系統有持續破壞能力,積少成多,不易察覺,相比於單次爆破性盜刷,周期性盜刷的危害可能會更大。
對於重要的接口,可考慮動態URL
或者給參數增加時間戳簽名,避免靜態接口被暴露出去。
3、減小對正常用戶的影響
防盜刷的重要目標是避免因提高安全等級而誤傷正常用戶,即使對正常用戶有影響,也要減少相應的比率。
(二)盜刷流量的特點
盜刷與正常用戶流量有明顯區別,盡管盜刷可以模擬正常用戶,但是還是通用性區別。
正常用戶訪問是隨機的,失敗重試的次數有限並且也是隨機的。盜刷流量是周期性的,並且間隔很小。
正常用戶是通過瀏覽器或者APP間接的產生請求流量,盜刷通過代碼直接發送HTTP請求。
三、可行性方案
下面通過逐步探究的方式,尋找合適的防盜刷方案。
(一)無安全防護
如果說重要的接口無安全防護措施,那么過於粗心大意。僅靠短信運營商提供的限流和預警方案不能滿足短信防盜刷的需求,本質原因是手機號可以合法的模擬,短信運營商不管是正常手機號、停機號、注銷號還是尚未投入使用手機號,均會響應發送短信的指令,哪怕是空號發送不成功也會計數。實際上盜刷使用的空號正是接口盜刷的典型特征。
僅靠短信運營商提供的限流和預警方案不能滿足短信防盜刷的需求,盡管可以針對單個手機號定制發送短信限額,按小時、按天可定制發送總額,依然不滿足短信防盜刷的目標。當觸發限流時,正常用戶流量同樣被限流,對於短信注冊來說新增正常用戶受影響。如果惡意破壞者連多日耗盡限額短信資源,對正常用戶的使用影響很大。
(二)圖片驗證碼
在無防護措施的基礎上增加圖片驗證碼,有驗證碼的保護,短信接口相對安全許多。
短信驗證碼盡管能夠有效保護短信接口防盜刷,但是不能夠保護自己被盜刷。盜刷流量惡意刷新圖片驗證碼接口,給服務器CPU造成極大的負載:圖片驗證碼服務與業務耦合,則業務可能響應緩慢;圖片驗證碼服務獨立部署,隔離了對業務的影響,但是圖片驗證碼服務器CPU依舊可能過載,正常用戶依然收到影響。
Web系統使用圖片驗證碼正逐漸減少,原因是引入了圖片驗證碼保護了短信接口,卻無法保護自己。
(三)基於IP限流
上述兩種方法存在明顯的缺陷,實施落地時幾乎不使用,通過基於IP限流
對無安全防護
方案進行升級改造。基於IP地址,每60秒允許發送一條短信(不關聯手機號),通過后端強制限流,能夠大幅減少短信接口被盜刷的數量。
基於IP限流回避了盜刷模擬手機號的影響,使用IP地址一刀切,穩妥的保證了短信接口的安全。
IP限流有個潛在隱患是如果惡意攻擊者與正常用戶復用同一個公網IP出口,那么正常用戶可能會收到影響,不過這種情況影響范圍有限且可控。
惡意盜刷通過代理IP地址
仍然能夠破解IP限流,只不過增加了破壞者的成本。
UCode CMS內置分布式IP限流的實現,可快速集成到項目中,請訪問開源項目中說明文檔獲取更多內容。
(四)動態請求
通過上述三種方案並沒有找到令人滿意的防盜刷方案,下面在IP限流的基礎上繼續打補丁,升級到動態請求。
動態請求的核心思想是將短信驗證碼接口動態化,既可以接口URL動態化
,也可以是參數動態化
。下面介紹一種基於時間戳簽名參數
的方式,實現動態請求。
1、簽名參數生成
前后端約定簽名參數生成算法,此算法應當保密。
比如:手機號=18612345678,則key=MD5(手機號 + 當前時間/分鍾),這里使用60秒的緩沖時間,也可以約定3分鍾或者5分鍾。
前后端都用這種方式生成key,前端頁面通過js腳本生成“簽名”,服務端“驗簽”。
需要注意的是:時間校驗要留buffer,客戶機時間與服務器時間並不完全相同。
同一個簽名參數超過緩沖時間在后端無法實現驗簽,因此盜刷在不知道簽名算法的前提下,盜刷流量有時間維度限制,解決了周期性盜刷的問題。
2、簽名算法安全性
簽名算法在后端是安全的,出開發人員外,幾乎無泄漏的可能。下面着重討論簽名算法在前端的安全性,以Web端和APP端討論。
(1)Web端
Web端通過JS實現簽名算法,由於可通過瀏覽器直接查看JS,有泄露算法的可能。不過目前大多數JS都是通過壓縮處理的,無法直接查看JS的詳細內容,如果前端做一些偽裝,破壞者找到簽名算法有一定難度。
(2)APP端
相比於Web端,APP端的安全性略高,簽名拳法封裝在APP應用程序中,除非通過反編譯手段,無法得知簽名算法的詳情。
對於非HTTPS流量,可通過抓包程序獲取短信接口的URL和參數,在不知道簽名算法的前提下,仍不能周期性的盜刷。
四、小結
上述可行性方案逐步升級,能夠實現重要接口的防盜刷需求。
(一)防盜刷建議
對於重要接口的防盜刷,除了使用上述方案外,建議遵循如下要點:
1、使用POST請求
盡量使用POST請求方式,增加盜刷者的嘗試成本。
2、使用HTTPS
HTTPS在Web端形同虛設,在APP端有較為很好的保護作用,盜刷者通過抓包工具無法直接獲取接口的詳情信息,有效的保護了接口。
3、周期性修改接口
隨着項目的迭代升級,周期性的隨機變更
重點接口的請求地址,前后端同步更新。
(二)補充說明
上述可行性討論方案適用於與短信注冊類似的接口。
1、短信登錄接口
短信登錄在IP限流的基礎上增加手機號BitMap檢驗,如果當前客戶端訪問IP限流正常,並且當前請求手機號已經注冊,則發送短信。
短信登錄接口無必要使用復雜的動態請求的方式,原因是已經默認了當前請求手機號存在數據庫中,如果不存在那么便是錯誤請求,快速響應即可。
UCode CMS內置分布式BitMap的實現,可快速集成到項目中,請訪問開源項目中說明文檔獲取更多內容。
2、已認證接口
對於已經經過登錄認證的接口,可使用用戶ID
限流,直接在無安全防護的基礎上使用用戶ID
限流。