如何防止簡訊API介面遍歷

  • 2019 年 10 月 4 日
  • 筆記

簡訊API介面在web中得到越來越多的應用,如用戶註冊,登錄,密碼重置等業務模組都會使用手機驗證碼進行身份驗證。一般情況下,我們會採用這樣的安全策略,將簡訊發送頻率限制在正常的業務流控範圍內,比如,一個手機號一天最多下發10條簡訊,同時限制時效,驗證次數。但這樣的策略,攻擊者通過遍歷手機號,還是阻止不了簡訊資源被消耗的情況。

如何防止簡訊api介面遍歷呢?

在平時瀏覽網站的時候,我會稍微留意一些網站是怎麼做的,並記錄了一些簡訊API介面防遍歷的技術實現方式。

第一種方式:白名單

這是最簡單的一種方式,但應用場景有限,比如,在一些內部應用系統(從HR系統或其他系統同步手機號過來驗證),此時,只需要驗證是否為內部員工手機號,如不是,直接提示非內部員工手機號;如是,再執行簡訊api流控策略。

第二種方式:驗證碼(推薦)

用戶點擊獲取簡訊驗證碼的時候,彈出圖形驗證碼進行驗證,同時發送圖形驗證碼和手機號碼到後台驗證。

當然,這種方式用戶體驗極差,每次都需要手動需要圖片驗證碼才能發送手機驗證碼,於是,有了進一步的優化方案,從用戶體驗和安全形度出發,可設計為當用戶輸入3次錯誤手機驗證碼後自動彈出驗證碼。

還有另外一種方式,採用當下比較流行的滑塊驗證或點選驗證方式,用戶體驗也會有所改善。

第三種方式:介面加密(不推薦)

前端與後台協商好加密方式,比如md5(timestamp+telphone+salt),前台發起請求時,同時發送 timestamp、telephone、sign參數,後台接收這些參數,按照協商好的加密方式生成一個校驗值與sign進行對比,如果錯誤,則不處理。另外,js程式碼混淆+簡訊api業務流控限制。

風險點:雖然做了程式碼混淆,但js加密演算法一旦泄漏,並不是一種安全的措施,但也是一種比較容易實現的技術方案。

客戶端ajax程式碼實現:

var timestamp = (new Date).getTime();  var sign = md5(timestamp+telephone+"qwertyuiopasdfghjkl");  ajax.post({  'url': '/sms_captcha/',  'data':{  'telephone': telephone,  'timestamp': timestamp,  'sign': sign  },  ...........

以上,是三種常見的預防簡訊api介面遍歷的技術實現方案。

我創建了一個免費的知識星球,主要用於技術問題探討。我將這個問題發表在知識星球,得到了不少星友的熱情回應,以下摘錄一些星友們的看法。

@超人:限制ip有可能誤傷同一區域網下的用戶,最好是登陸後允許發送,限制用戶的發送次數    @密因:同一手機號,60秒內不能重複發送,24小時內總共發送不超過5次;2個及以上手機號,通過識別客戶端特徵,出口ip,隨機字元串,判定是否為同一用戶,對同一用戶使用限制措施。或者設定略高於平常請求數的基準線,如日常1分鐘100個簡訊請求,基準線設置為150,1分鐘內超過150次之外的請求丟棄。    @Antares:限制每個IP、帳號每天的請求頻率和數量,對請求參數做簽名校驗,防止請求重放    @Adler:在獲取驗證碼前加驗證,然後黑名單螢幕蔽虛擬號,限制每個IP一定時間內的請求數和限制每個手機號請求的總次數。    @yd:一般都是限制ip在時間段內請求次數,限制同一手機號發送次數,加圖形或滑動等驗證碼。    @Mr.周:設置請求上線 屏蔽虛擬號碼段。    @ch4ce:我們限制了IP地址,雖然這樣不是最好的解決方案。    @Loki⚡:我個人感覺,首先確保發送簡訊驗證碼的邏輯是正確的,然後可以根據業務的重要程度決定是用安全產品,還是自己開發人機識別功能。    1024:人機驗證,設備號,帆布指紋, ip。    corp0ra1:如果可以的話,匹配用戶名?    掉到魚缸里的貓:限制同IP請求次數。    zxt:每個用戶一天或者一個小時只允許三個驗證碼,同ip每天只允許三個用戶獲取驗證碼。這種模式比較常用。