安全設計--CSRF跨站僞造

概念


定義

CSRF跨站點請求僞造(Cross—Site Request Forgery):顧名思義,攻擊者僞造用戶請求請求服務端,但並非在官方站點發起,而是攻擊者的站點,或者攻擊者的腳本。而服務器認爲卻是合法的,有點借刀殺人的意思。

原理

攻擊者僞造的網站,或者僞造請求作爲一個鏈接或者按鈕。提供給正常用戶點擊或者在其他站點提交,請求的地址是官方服務器,攜帶的是當前操作人的Cookie信息。導致操作的內容爲攻擊者的想要的,達成攻擊目標。

案例

電商網站,商品詳情頁往往有評論,攻擊者製作一個點擊按鈕,用戶點擊就能對自己下過單的商品進行評論,評論的內容和動作都是攻擊者來設定。對網站和個人的名譽產生負面影響。

防禦方案


體驗與安全兼顧:在請求中添加 token 並驗證

  • token hidden在頁面,對用戶透明。
  • 攻擊者無法獲取到token和僞造。
解決思路
  • 首先將這種操作類請求做成post請求。避免URL上帶token,防止獲取Referer得到token
  • token是在進入操作頁面時由服務端生成並埋入。提交時攜帶token,服務端對token進行校驗,確定請求有效性
  • token要求:與請求用戶有唯一綁定關係,防止僞造。
具體實現

redis + session 實現token (集羣情況下要求分佈式session實現方案)

  • 用戶請求,服務端獲取當前用戶sessionId;同時生成一個UUID,將UUID作爲key sessionId作爲Value存入redis。目的:特定發起者有唯一的token,攻擊者不能模仿請求獲取到token來僞造。
  • 將UUID作爲Token 返回給用戶頁面,用戶提交時攜帶UUID作爲入參,傳遞到服務端。
  • 服務端獲取操作請求,利用UUID獲取SessionId 和本次請求的sessionId比對,通過校驗之後才放過 。不一致則拒絕。
  • 利用sessionId的理由:就算攻擊者模仿請求獲取到UUID的token給到用戶提交的sessionId是不同的,起不到攻擊作用
  • 注意:不要鑽請求劫持的牛角尖,如果用戶請求時被劫持了,這種情況不止是CSRF那麼簡單了,啥都能發生。

關鍵代碼


token
public void generateToken(){
    String userToken = UUID.randomUUID().toString();
    String sessionId = request.getSession().getId();
    RedisUtils.put(userToken,sessionId);
}
check token
public void checkToken(){
	String sessionId = request.getSession().getId();
	String userSessionId = RedisUtils.get(userToken);
	 
	if (sessionId == null || !sessionId.equals(userSessionId)){
	    // false;
	}
	// go
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章