国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

csrf漏洞

2019-11-08 18:46:25
字體:
來源:轉載
供稿:網友

Rails CSRF安全性功能以及取消form驗證

預設產生出來的 Controller 都繼承自 applicationController 。因此定義在這裡的方法可以被所有 Controller 取用,你可以在這邊定義一些共用的方法。預設的 application_controller.rb 長的如下:

class ApplicationController < ActionController::Base

PRotect_from_forgery

end

其中的 protect_from_forgery 方法啟動了 CSRF 安全性功能,所有非 GET 的 HTTP request都必須帶有一個 Token 參數才能存取, Rails 會自動在所有表單中幫你插入 Token 參數,預設的Layout 中也有一行 <%= csrf_meta_tag %> 標籤可以讓 javaScript 讀取到這個 Token 。會需要關閉這個功能的時機是,你需要開放 API 給非瀏覽器客戶端,這時候你會需要取消它:

class ApisController < ApplicationController 

    skip_before_filter :verify_authenticity_token 

end

Http跨站點請求偽造解決方案

1.跨站點請求偽造

首先,什么是跨站點請求偽造?

跨站點請求偽造-CSRF(Cross Site Request Forgery):是一種網絡攻擊方式。

說的白話一點就是,別的站點偽造你的請求,最可怕的是你還沒有察覺并且接收了。聽起來確實比較危險,下面有個經典的實例,了解一下跨站點請求偽造到底是怎么是實現的,知己知彼。

受害者:Bob 黑客:Mal 銀行:bank bob在銀行有一筆存款,可以通過請求http://bank.example/withdraw?account=bob&amount=1000000&for=bob2把錢轉到bob2下。通常情況下,該請求到達網站后,服務器會驗證請求是否來自一個合法的session,并且該session的用戶Bob已登錄。Mal在該銀行也有賬戶,于是他偽造了一個地址http://bank.example/withdraw?account=bob&amount=1000000&for=mal,但是如果直接訪問,服務器肯定會識別出當前登錄用戶是mal而不是Bob,不能接受請求。于是通過CSRF攻擊方式,將此鏈接偽造在廣告下,誘使Bob自己點這個鏈接,那么請求就會攜帶Bob瀏覽起的cookie一起發送到銀行,而Bob同時又登錄了銀行或者剛剛登錄不久session還沒有過期,那服務器發現cookie中有Bob的登錄信息,就接收了響應,攻擊就成功了

2.現在主要的幾種防御CSRF的策略:

1. 驗證Referer:

referer攜帶請求來源,從示例可以看出,受害者發送非法請求肯定不是在銀行的界面,所以在服務器通過驗證Referer是不是bank.example開始就可以了,這個方法簡單粗暴。

最簡單的實現就是加個Filter:

[java] view plain copy 在CODE上查看代碼片/**  * 根據請求地址獲取token-key  */  public static String getTokenKey(HttpServletRequest request){      String key = null;          try {              MessageDigest mDigest = MessageDigest.getInstance("md5");//摘要算法可以自己選擇              byte[] result = mDigest.digest(request.getRequestURL().toString().getBytes());              key = StringUtil.bytes2hex(result);          } catch (NoSuchAlgorithmException e) {             LOGGER.error("get token key failed",e);          }           return key  }    /**  * 獲取token-value并存儲在session中  */  public static String getTokenValue(HttpServletRequest request){      String key = getTokenKey(request);      Map<String,String> tokenMap = null;      Object obj = request.getSession().getAttribute("tokenMap");      if(obj == null){          tokenMap = new HashMap<String,String>();          request.getSession().setAttribute("tokenMap", tokenMap);      } else {          tokenMap = (Map<String,String>)obj;      }      if(tokenMap.containsKey(key)){          return tokenMap.get(key);      }      String value = GUID.generate();//GUID實現可自行百度,其實弄個偽隨機數也是可以的...      tokenMap.put(key,value);      return value;  }    /**  * 驗證token  */  public static boolean verify(String key ,String value ,HttpServletRequest request){      boolean result = false;      if (StringUtil.isEmpty(key) || StringUtil.isEmpty(value)) {//key或value只要有一個不存在就驗證不通過          return result;      }        if (request.getSession() != null) {          Map<String,String> tokenMap = getTokenMap(request);          if(value.equals(tokenMap.get(key))){              result = true;              tokenMap.remove(key);//成功一次就失效          }      }      return result;  }  完成上邊的工具方法后,需要在form中添加token,如下:

[html] view%20plain copy 派生到我的代碼片<form name="frm" action="/test/tokentest.htm"  method="POST">      <input type="hidden" name="token_key" value="<%=Token.getTokenKey(request) %>"/>      <input type="hidden" name="token_value" value="<%=Token.getTokenValue(request) %>"/>      ...  </form>  

驗證可以放在Filter里也可以放在Service里,只要保證請求/test/tokentest.htm會先驗證就行了。直接調用工具方法Token.verify()以下就不贅述了。

3. 在HTTP頭中自定義屬性并驗證:

這個方法和上面那個類似,也是設置token,只是把token設置為HTTP頭中的自定義屬性。

通過xmlHttpRequest可以一次性給所有該類請求的HTTP頭加上token 屬性,但是xmlhttpRequest請求通常用于Ajax方法對局部頁面的異步刷新,比較有局限性;而且通過XMLHttpRequest請求的地址不會被記錄到瀏覽器的地址欄,一方面不會通過Referer泄露token,另一方面會導致前進,后退,刷新,收藏等操作失效,所以還是慎用。

雖然上面介紹了幾種方法,但現在還沒有一種完美的解決方案,但是通過Referer和Token方案結合起來使用,也能很得有效CSRF攻擊。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 上饶县| 延寿县| 新竹县| 南部县| 增城市| 忻州市| 南乐县| 兴义市| 化德县| 襄城县| 台湾省| 白玉县| 谷城县| 鸡泽县| 麻江县| 河南省| 北安市| 赫章县| 广元市| 大理市| 桓台县| 塔河县| 贵溪市| 桦甸市| 南川市| 久治县| 塔河县| 通江县| 诏安县| 元阳县| 临颍县| 洛浦县| 贵阳市| 石柱| 阳西县| 石狮市| 常熟市| 富裕县| 阿荣旗| 北流市| 舒城县|