中秋節時候我們的應用在短信驗證碼這塊被惡意刷單,比如被用來做垃圾短信之類的,如果大規模被刷也能造成不小的損失。這還只是短信驗證碼,如果重要的API遭到CSRF的攻擊,損失不可估量。所以緊急加班解決了CSRF的攻擊問題。
CSRF是什么鬼?
CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。
CSRF能干嘛?
你這可以這么理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私泄露以及財產安全。
CSRF特性?
依靠用戶標識危害網站
利用網站對用戶標識的信任
欺騙用戶的瀏覽器發送HTTP請求給目標站點
另外可以通過IMG標簽會觸發一個GET請求,可以利用它來實現CSRF攻擊。
CSRF原理

簡單來說,CSRF必須經過兩個步驟:
1、用戶訪問可信任站點A,並產生了相關的cookie;
2、用戶在訪問A站點時沒有退出,同時訪問了危險站點B;
大家同時訪問多個網站是很正常的事情,所以也很容易遭到CSRF的攻擊。
舉個栗子:
某電商網站A,你購買時候支付的操作是:http://www.market.com/Transfer.php?bankId=11&money=1000; 某危險網站B,他有段代碼是 <img src=http://www.market.com/Transfer.php?bankId=11&money=1000>
訪問A支付后你會發現銀行卡里面多扣了1000塊錢,why?通過get方式,你在訪問A網站進行支付操作時,A網站保存了你的cookie信息,如果B網站拿到了你的cookie或者他偽造的數據剛好就是cookie里的,就能偽造你的請求,進行同樣的支付操作。
也許你會說,我換成post請求不就行了,但是如果你的server代碼沒有處理,一樣可以進行偽造。
So,如何進行防御?
1、服務器端表單hash認證
在所有的表單里面隨機生成一個hash,server在表單處理時去驗證這個hash值是否正確,這樣工作量比較大,我們之前所有的表單都沒添加!!!,好幾十個頁面,這個當前處境不切實際
2、驗證http Referer字段
根據HTTP協議,在HTTP頭中有一個字段叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求必須來自於同一個網站。比如某銀行的轉賬是通過用戶訪問http://bank.test/test?page=10&userID=101&money=10000頁面完成,用戶必須先登錄bank.test,然后通過點擊頁面上的按鈕來觸發轉賬事件。當用戶提交請求時,該轉賬請求的Referer值就會是轉賬按鈕所在頁面的URL(本例中,通常是以bank. test域名開頭的地址)。而如果攻擊者要對銀行網站實施CSRF攻擊,他只能在自己的網站構造請求,當用戶通過攻擊者的網站發送請求到銀行時,該請求的Referer是指向攻擊者的網站。因此,要防御CSRF攻擊,銀行網站只需要對於每一個轉賬請求驗證其Referer值,如果是以bank. test開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的。如果Referer是其他網站的話,就有可能是CSRF攻擊,則拒絕該請求。
3、在HTTP頭中自定義屬性並驗證
自定義屬性的方法也是使用token並進行驗證,和前一種方法不同的是,這里並不是把token以參數的形式置於HTTP請求之中,而是把它放到HTTP頭中自定義的屬性里。通過XMLHttpRequest這個類,可以一次性給所有該類請求加上csrftoken這個HTTP頭屬性,並把token值放入其中。這樣解決了前一種方法在請求中加入token的不便,同時,通過這個類請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心token會通過Referer泄露到其他網站。
我們就是采用的這種方法,因為基本上所有的請求都是通過ajax,我們通過重新封裝ajax,在ajax頭部添加一個token,server去識別這個token,如果請求沒有這個token或者錯誤就拒絕。
4、CSRF攻擊是有條件的,當用戶訪問惡意鏈接時,認證的cookie仍然有效,所以當用戶關閉頁面時要及時清除認證cookie,對支持TAB模式(新標簽打開網頁)的瀏覽器尤為重要。
5、盡量少用或不要用request()類變量,獲取參數指定request.form()還是request. querystring (),這樣有利於阻止CSRF漏洞攻擊,此方法只不能完全防御CSRF攻擊,只是一定程度上增加了攻擊的難度。
6、
通過圖形驗證碼
相對來說圖形驗證碼應該是最安全的,但是我們不可能在所有的API上去加上這么個玩意兒,一般是在表單,比如注冊,登錄等,當用戶頻繁操作時出現,避免影響用戶體驗
所以建議以后ajax請求都盡量加上token驗證,雖然不一定能防御所有的CSRF攻擊,但是可以大幅度提升接口的安全性,中秋節加班通過緊急修復后,CSRF攻擊基本沒有了。