紀錄一次面對ddos盜刷微信企業支付的經歷

紀錄一次面對ddos盜刷微信企業支付的經歷

這次的文章屬於對於之前在工作中發生的一次ddos攻擊應對分析和應對經驗.很有意思.雖然可能對於大多數的讀者和我本人來說這樣的事件可能不會在一次發生.但是有一句話說的很好(ps這一句話是我經常看的一個公衆號架構師之路里面寫的,給大佬的公衆號打一個廣告).

思路比結論重要,有收穫就是好的。

事件

這次是我們公司開發的一個微信公衆號,裏面有一個答題搶紅包的模塊.需要用戶答題成功後,領取紅包,按照設定的代碼是根據設置,每天最多拿一個.但是某一天,商務那邊拿了微信企業錢包的紀錄過來說被別人盜刷了,在短時間內同一個用戶密集的領取紅包.

然後開始查詢日誌,確實在凌晨,有用戶使用同一個ip密集的訪問領取紅包的接口,並順利躲過每日領取一個的檢查.

分析

如果當時ddos的攻擊的話,可以購買對應的雲服務進行防禦.但是代碼裏面肯定還是存在問題.

我個人還懷疑,這些黑客,只是順手進行嘗試盜刷.當然這些也只是猜測

並不準備放上原始的代碼.只是大體描述一下代碼的邏輯

  • 首先是數據庫.這裏有一張領取記錄表,大概是字段是用戶id,領取金額,領取時間

然後發放紅包代碼邏輯的僞代碼是這樣的

$count = $this->countpackactive( ['member_id' => $memberid, '@date_format(createtime,"%Y-%m-%d")'=>date('Y-m-d')]);//獲取當前用戶當日獲取的次數
 if($packactiveinfo['pack_membernum'] - $count == 0){
         $this->dataerror('今日答題次數已用完!');
 }

 ...
 ...

 //調用企業支付接口.
 $this->addquestionmember_datetime (['quest_tradenumber'=>$tradenumber,'status'=>1]);//insert領取表,增加當前用戶的當日的領取次數

...

上面的代碼的思路還是蠻清晰的.但是在併發測試下就出現了盜刷的問題.原本的檢查完全失敗.那麼問題出在哪裏?我們在簡化上面的代碼

$count = $db->count('question_member',$where);
if ($count ....)
.....
$db->insert('question_member',$set);
.....


我們看到這麼一個邏輯先檢查question_member表,在插入question_member.用一定的數據庫經驗的朋友可以看出來來這裏出現了資源的佔用的問題.在第一次訪問question_member插入完成之前,第二個接口訪問到來,要求檢查當前question_member的情況.這裏有點類似事務處理裏面的幻讀.

資源的佔用與併發訪問的一致性

這裏其實並不像誇誇奇談,我先說的是這一類的問題其實在計算機的各個層面的都是通用的,不僅僅是數據庫中,在操作系統中也見到過注入資源的強佔問題,在網絡層中出現的一致性問題.而這些問題的解決思路往往很詳盡.

而在這裏的方案是增加一個鎖,在增加當前用戶日領取記錄時候使用鎖,而在讀取時候必須等待之前的記錄插入完畢才能讀取.

上面的是第一套方案,當然很快被領導否定了.技術主管提出現在的行業中不流行使用鎖(我對於這一點抱有疑問)

然後提出第二套方案,使用redis進行每天的日訪問記錄進行檢查.大概的邏輯是這樣的


$count = $redis->get( 'question_member:' . $time . ':' $memberid );//獲取當前的訪問數目
if($packactiveinfo['pack_membernum'] - $count == 0){
        $this->dataerror('今日答題次數已用完!');
...
...
$redis->set('question_member:' . $time . ':' $memberid, $count+1);
發放紅包,如果失敗回滾;

這裏的使用邏輯是通過redis原子訪問特性(redis是原子化,必須等一個訪問結束後纔有第二個發文),速度快的特性避免了高併發下出現的資源佔用問題.
其實這裏還是會出現資源的佔用,只不過因爲redis的響應特別快,從而不會輕易出現,在一次插入結束前,繼續訪問接口.(平心而論還是有地雷的).但是配合ddos防禦還是效果很好.

經驗

在這次的事件後我進行了總結

  • 對於關鍵性質的代碼,尤其是涉及到金錢的代碼要慎之又慎
  • 在測試,可以藉助ab之類的工具,檢查這一類關鍵接口是否會在高併發訪問下出現問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章