什么是CSRF?
摘自【CSRF百度百科】
注意:原理性的東西自行搜索。
原理
當前防御 CSRF 的幾種策略
在業界目前防御 CSRF 攻擊主要有三種策略:
驗證 HTTP Referer 字段;- 在請求地址中添加 token 並驗證;
- 在 HTTP 頭中自定義屬性並驗證。
下面就分別對這三種策略進行詳細介紹。
驗證 HTTP Referer 字段
根據 HTTP 協議,在 HTTP 頭中有一個字段叫 Referer,它記錄了該 HTTP 請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求來自於同一個網站,比如需要訪問 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用戶必須先登陸 bank.example,然后通過點擊頁面上的按鈕來觸發轉賬事件。這時,該轉帳請求的 Referer 值就會是轉賬按鈕所在的頁面的 URL,通常是以 bank.example 域名開頭的地址。而如果黑客要對銀行網站實施 CSRF 攻擊,他只能在他自己的網站構造請求,當用戶通過黑客的網站發送請求到銀行時,該請求的 Referer 是指向黑客自己的網站。因此,要防御 CSRF 攻擊,銀行網站只需要對於每一個轉賬請求驗證其 Referer 值,如果是以 bank.example 開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的。如果 Referer 是其他網站的話,則有可能是黑客的 CSRF 攻擊,拒絕該請求。
這種方法的顯而易見的好處就是簡單易行
,網站的普通開發人員不需要操心 CSRF 的漏洞,只需要在最后給所有安全敏感的請求統一增加一個攔截器來檢查 Referer 的值就可以。特別是對於當前現有的系統,不需要改變當前系統的任何已有代碼和邏輯,沒有風險,非常便捷。
然而,這種方法並非萬無一失。 Referer 的值是由瀏覽器提供的,雖然 HTTP 協議上有明確的要求,但是每個瀏覽器對於 Referer 的具體實現可能有差別,並不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴於第三方(即瀏覽器)來保障,從理論上來講,這樣並不安全。事實上,對於某些瀏覽器,比如 IE6 或 FF2,目前已經有一些方法可以篡改 Referer 值。 如果 bank.example 網站支持 IE6 瀏覽器,黑客完全可以把用戶瀏覽器的 Referer 值設為以 bank.example 域名開頭的地址,這樣就可以通過驗證,從而進行 CSRF 攻擊。
即便是使用最新的瀏覽器,黑客無法篡改 Referer 值,這種方法仍然有問題。因為 Referer 值會記錄下用戶的訪問來源,有些用戶認為這樣會侵犯到他們自己的隱私權,特別是有些組織擔心 Referer 值會把組織內網中的某些信息泄露到外網中。因此,用戶自己可以設置瀏覽器使其在發送請求時不再提供 Referer。 當他們正常訪問銀行網站時,網站會因為請求沒有 Referer 值而認為是 CSRF 攻擊,拒絕合法用戶的訪問。
在請求地址中添加 token 並驗證
CSRF 攻擊之所以能夠成功,是因為黑客可以完全偽造用戶的請求,該請求中所有的用戶驗證信息都是存在於 cookie 中,因此黑客可以在不知道這些驗證信息的情況下直接利用用戶自己的 cookie 來通過安全驗證。要抵御 CSRF,關鍵在於在請求中放入黑客所不能偽造的信息,並且該信息不存在於 cookie 之中。 可以在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在服務器端建立一個攔截器來驗證這個 token,如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。
這種方法要比檢查 Referer 要安全一些,token 可以在用戶登陸后產生並放於 session 之中,然后在每次請求時把 token 從 session 中拿出,與請求中的 token 進行比對,但這種方法的難點在於如何把 token 以參數的形式加入請求。對於 GET 請求,token 將附在請求地址之后,這樣 URL 就變成 http://url?csrftoken=tokenvalue。 而對於 POST 請求來說,要在 form 的最后加上 ,這樣就把 token 以參數的形式加入請求了。但是,在一個網站中,可以接受請求的地方非常多,要對於每一個請求都加上 token 是很麻煩的,並且很容易漏掉, 通常使用的方法就是在每次頁面加載時,使用 javascript 遍歷整個 dom 樹,對於 dom 中所有的 a 和 form 標簽后加入 token。這樣可以解決大部分的請求,但是對於在頁面加載之后動態生成的 html 代碼,這種方法就沒有作用,還需要程序員在編碼時手動添加 token。
該方法還有一個缺點是難以保證 token 本身的安全。特別是在一些論壇之類支持用戶自己發表內容的網站,黑客可以在上面發布自己個人網站的地址。由於系統也會在這個地址后面加上 token,黑客可以在自己的網站上得到這個 token,並馬上就可以發動 CSRF 攻擊。為了避免這一點,系統可以在添加 token 的時候增加一個判斷,如果這個鏈接是鏈到自己本站的,就在后面添加 token,如果是通向外網則不加。不過,即使這個 csrftoken 不以參數的形式附加在請求之中,黑客的網站也同樣可以通過 Referer 來得到這個 token 值以發動 CSRF 攻擊。這也是一些用戶喜歡手動關閉瀏覽器 Referer 功能的原因。
在 HTTP 頭中自定義屬性並驗證
這種方法也是使用 token 並進行驗證,和上一種方法不同的是,這里並不是把 token 以參數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性里。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。這樣解決了上種方法在請求中加入 token 的不便,同時,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心 token 會透過 Referer 泄露到其他網站中去。
然而這種方法的局限性非常大。XMLHttpRequest 請求通常用於 Ajax 方法中對於頁面局部的異步刷新,並非所有的請求都適合用這個類來發起,而且通過該類請求得到的頁面不能被瀏覽器所記錄下,從而進行前進,后退,刷新,收藏等操作,給用戶帶來不便。 另外,對於沒有進行 CSRF 防護的遺留系統來說,要采用這種方法來進行防護,要把所有請求都改為 XMLHttpRequest 請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。
開源項目 CSRFGuard
簡介
OWASP CSRFGuard是一個庫,它實現同步器令牌模式的變體,以降低跨站點請求偽造(CSRF)攻擊的風險。OWASP CSRFGuard庫通過使用JavaEE過濾器進行集成,並公開了各種自動和手動方式,以將每會話或偽每請求令牌集成到HTML中。當用戶與此HTML交互時,將使用相應的HTTP請求提交CSRF預防令牌(即加密隨機同步器令牌)。OWASP CSRFGuard負責確保令牌存在且對當前HTTP請求有效。在沒有正確的相應令牌的情況下向受保護資源提交請求的任何嘗試都被視為正在進行的CSRF攻擊並被丟棄。在放棄請求之前,可以將CSRFGuard配置為執行一個或多個操作,例如記錄請求的各個方面以及將用戶重定向到登錄頁面。最新版本增強了此策略,以支持使用Ajax提交的HTTP請求的可選驗證以及referrer標頭的可選驗證。
OWASP-CSRFGuard 官網
github 項目地址
疑問?上面有介紹三種方式解決CSRF的攻擊策略。為什么還要介紹CSRFGuard項目?
- 對於沒有進行 CSRF 防護的遺留系統來說,以上方式無疑是致命的;CSRFGuard可以很好的解決這個問題。
- 三種策略都需自己實現,性能以及安全性並不高; CSRFGuard提供實現,直接配置即可。
- 控制粒度更具優勢。可以設置不受保護的頁面及URL請求。
測試項目
- 確保安裝了
Apache Maven 3.0.4
或更高版本; - 確保安裝了GPG並使用密鑰生成密鑰;
- 在本地克隆此存儲庫;
- 首先建立
csrfguard
項目,cd csrfguard
然后是mvn clean install;
- 隨后構建並運行
csrfguard-test
項目;cd ../csrfguard-test
啟動:mvn clean package tomcat7:run
; - 使用Web瀏覽器訪問http://localhost:8000以打開測試項目的主頁。
注:把測試項目代碼看一遍就行。或者源碼看一下,東西並不多,有興趣可以稍微看看源碼就能接上項目的。
安裝
- 將Owasp.CsrfGuard.jar文件復制到應用程序的類路徑中
- 在應用程序的部署描述符(web.xml)中聲明CsrfGuard
- 根據需要配置Owasp.CsrfGuard.properties文件
將以下依賴項添加到Maven POM(pom.xml
)文件以使用該庫:
<dependency>
<groupId>org.owasp</groupId>
<artifactId>csrfguard</artifactId>
<version>3.1.0</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
或者將二進制:從Maven Central下載二進制版本jar文件復制到應用程序的類路徑中。
聲明CsrfGuard上下文參數以及HttpSessionListener和Filter。
web.xml
:
<!-- 兩個參數: CSRFGuard將按照外觀順序搜索以下位置來搜索指定的屬性文件:應用程序的類路徑,容器可訪問的目錄或任意絕對路徑。-->
<!-- 兩個上下文參數:Owasp.CsrfGuard.Config和Owasp.CsrfGuard.Config.Print。 Owasp.CsrfGuard.Config參數是必需的,它指定CSRFGuard屬性文件的位置。默認為:Owasp.CsrfGuard.properties。CSRFGuard將按照外觀順序搜索以下位置來搜索指定的屬性文件:應用程序的類路徑,容器可訪問的目錄或任意絕對路徑。 Owasp.CsrfGuard.Config.Print參數是可選的,只是指示CSRFGuard將解析的屬性顯示到應用程序服務器日志文件。-->
<!-- 注:Owasp.CsrfGuard.properties文件可以配置多個文件覆蓋。 -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>
<!-- 聲明並啟用CSRFGuard HttpSessionListener:根據session生成token -->
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>
<!-- CsrfGuardFilter負責促進JavaEE Web應用程序中CsrfGuard對象和相關令牌驗證邏輯的集成。 -->
<filter>
<filter-name>CSRFGuard</filter-name>
<filter-class>org.owasp.csrfguard.CsrfGuardFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CSRFGuard</filter-name>
<!-- 過濾所有請求,映射到我們想要保護免受攻擊的所有資源。 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 聲明並配置JavaScriptServlet。強烈建議默認使用JavaScript令牌注入策略,Token注入邏輯是自動化的,改動最小。 詳見:https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection#JavaScript_DOM_Manipulation -->
<servlet>
<servlet-name>JavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JavaScriptServlet</servlet-name>
<url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
配置
最重要的地方是配置Owasp.CsrfGuard.properties文件。在運行OWASP CSRFGuard實例之前,用戶應查看並指定最少數量的配置設置。此類配置包括指定新Token登錄頁面,為使用XMLHttpRequest的應用程序啟用Ajax支持,設置不應受保護的頁面,以及配置在識別CSRF攻擊時應調用的一個或多個操作。本文的目的是提供關鍵OWASP CSRFGuard配置設置的概述。
日志記錄
org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.ConsoleLogger
- 1
登陸頁面Token
org.owasp.csrfguard.NewTokenLandingPage=%servletContext%/index.html
- 1
頁面唯一Token
org.owasp.csrfguard.TokenPerPage=true
- 1
Token輪換
org.owasp.csrfguard.Rotate = false
- 1
Ajax和XMLHttpRequest支持
org.owasp.csrfguard.Ajax=true
- 1
不受保護的頁面
默認值:CSRFGuard必須驗證所請求的資源。
示例1:請求uri和不受保護的頁面之間的完全匹配。例如:/Owasp.CsrfGuard.Test/tag.jsp
示例2:最長路徑前綴匹配。例如:/test/JavaScriptServlet
示例3:正則擴展匹配。例如:*.html
、/MySite/Public/*
org.owasp.csrfguard.unprotected.Tag=/test/tag.jsp
org.owasp.csrfguard.unprotected.JavaScriptServlet=/test/JavaScriptServlet
org.owasp.csrfguard.unprotected.Html=*.html
org.owasp.csrfguard.unprotected.Public=/MySite/Public/*
- 1
- 2
- 3
- 4
注:該表格只是簡單的一個解釋。具體詳細介紹還看下面的配置文件及官網。
屬性 | 值 | 語義 |
---|---|---|
org.owasp.csrfguard.Logger |
JavaLogger /ConsoleLogger |
負責處理CSRFGuard生成的所有日志消息的對象。 |
org.owasp.csrfguard.Enabled |
true |
啟用csrfguard過濾器 |
org.owasp.csrfguard.TokenName |
OWASP-CSRFTOKEN |
Token名 |
org.owasp.csrfguard.SessionKey |
OWASP-CSRFTOKEN |
會話密鑰名稱 |
org.owasp.csrfguard.TokenLength |
32 | Toekn值長度 |
org.owasp.csrfguard.PRNG |
SHA1PRNG |
偽隨機數發生器 |
org.owasp.csrfguard.configOverlay.hierarchy |
classpath:Owasp.CsrfGuard.properties, classpath:Owasp.CsrfGuard.overlay.properties |
指定多個配置文件 |
org.owasp.csrfguard.configOverlay.secondsBetweenUpdateChecks |
60 | 檢查配置文件是否更新之間的秒數 |
Owasp.CsrfGuard.properties
# The OWASP CSRFGuard Project, BSD License
# Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of OWASP nor the names of its contributors may be used
# to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# From: https://github.com/esheri3/OWASP-CSRFGuard/blob/master/csrfguard-test/src/main/webapp/WEB-INF/csrfguard.properties
# Common substitutions
# %servletContext% is the servlet context (e.g. the configured app prefix or war file name, or blank.
# e.g. if you deploy a default warfile as someApp.war, then %servletContext% will be /someApp
# if there isnt a context it will be the empty string. So to use this in the configuration, use e.g. %servletContext%/something.html
# which will translate to e.g. /someApp/something.html
# Logger
#
# The logger property (org.owasp.csrfguard.Logger) defines the qualified class name of
# the object responsible for processing all log messages produced by CSRFGuard. The default
# CSRFGuard logger is org.owasp.csrfguard.log.ConsoleLogger. This class logs all messages
# to System.out which JavaEE application servers redirect to a vendor specific log file.
# Developers can customize the logging behavior of CSRFGuard by implementing the
# org.owasp.csrfguard.log.ILogger interface and setting the logger property to the new
# logger's qualified class name. The following configuration snippet instructs OWASP CSRFGuard
# to capture all log messages to the console:
#
# org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.ConsoleLogger
org.owasp.csrfguard.Logger=org.owasp.csrfguard.log.JavaLogger
# Which configuration provider factory you want to use. The default is org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory
# Another configuration provider has more features including config overlays: org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory
# The default configuration provider is: org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory
# which will look for an overlay file, it is there, and the factory inside that file is set it will use it, otherwise will be PropertiesConfigurationProviderFactory
# it needs to implement org.owasp.csrfguard.config.ConfigurationProviderFactory
org.owasp.csrfguard.configuration.provider.factory = org.owasp.csrfguard.config.overlay.ConfigurationAutodetectProviderFactory
# If csrfguard filter is enabled
org.owasp.csrfguard.Enabled = true
# If csrf guard filter should check even if there is no session for the user
# Note: this changed around 2014/04, the default behavior used to be to
# not check if there is no session. If you want the legacy behavior (if your app
# is not susceptible to CSRF if the user has no session), set this to false
org.owasp.csrfguard.ValidateWhenNoSessionExists = true
# New Token Landing Page
#
# The new token landing page property (org.owasp.csrfguard.NewTokenLandingPage) defines where
# to send a user if the token is being generated for the first time, and the use new token landing
# page boolean property (org.owasp.csrfguard.UseNewTokenLandingPage) determines if any redirect happens.
# UseNewTokenLandingPage defaults to false if NewTokenLandingPage is not specified, and to true
# if it is specified.. If UseNewTokenLandingPage is set true then this request is generated
# using auto-posting forms and will only contain the CSRF prevention token parameter, if
# applicable. All query-string or form parameters sent with the original request will be
# discarded. If this property is not defined, CSRFGuard will instead auto-post the user to the
# original context and servlet path. The following configuration snippet instructs OWASP CSRFGuard to
# redirect the user to %servletContext%/index.html when the user visits a protected resource
# without having a corresponding CSRF token present in the HttpSession object:
#
# org.owasp.csrfguard.NewTokenLandingPage=%servletContext%/index.html
# Protected Methods
#
# The protected methods property (org.owasp.csrfguard.ProtectedMethods) defines a comma
# separated list of HTTP request methods that should be protected by CSRFGuard. The default
# list is an empty list which will cause all HTTP methods to be protected, thus preserving
# legacy behavior. This setting allows the user to inform CSRFGuard that only requests of the
# given types should be considered for protection. All HTTP methods not in the list will be
# considered safe (i.e. view only / unable to modify data). This should be used only when the
# user has concrete knowledge that all requests made via methods not in the list
# are safe (i.e. do not apply an action to any data) since it can actually introduce new
# security vulnerabilities. For example: the user thinks that all actionable requests are
# only available by POST requests when in fact some are available via GET requests. If the
# user has excluded GET requests from the list then they have introduced a vulnerability.
# The following configuration snippet instructs OWASP CSRFGuard to protect only the POST,
# PUT, and DELETE HTTP methods.
#
# org.owasp.csrfguard.ProtectedMethods=POST,PUT,DELETE
# or you can configure all to be protected, and specify which is unprotected. This is the preferred approach
# org.owasp.csrfguard.UnprotectedMethods=GET
# Unique Per-Page Tokens
#
# The unique token per-page property (org.owasp.csrfguard.TokenPerPage) is a boolean value that
# determines if CSRFGuard should make use of unique per-page (i.e. URI) prevention tokens as
# opposed to unique per-session prevention tokens. When a user requests a protected resource,
# CSRFGuard will determine if a page specific token has been previously generated. If a page
# specific token has not yet been previously generated, CSRFGuard will verify the request was
# submitted with the per-session token intact. After verifying the presence of the per-session token,
# CSRFGuard will create a page specific token that is required for all subsequent requests to the
# associated resource. The per-session CSRF token can only be used when requesting a resource for
# the first time. All subsequent requests must have the per-page token intact or the request will
# be treated as a CSRF attack. This behavior can be changed with the org.owasp.csrfguard.TokenPerPagePrecreate
# property. Enabling this property will make CSRFGuard calculate the per page token prior to a first
# visit. This option only works with JSTL token injection and is useful for preserving the validity of
# links if the user pushes the back button. There may be a performance impact when enabling this option
# if the .jsp has a large number of proctected links that need tokens to be calculated.
# Use of the unique token per page property is currently experimental
# but provides a significant amount of improved security. Consider the exposure of a CSRF token using
# the legacy unique per-session model. Exposure of this token facilitates the attacker's ability to
# carry out a CSRF attack against the victim's active session for any resource exposed by the web
# application. Now consider the exposure of a CSRF token using the experimental unique token per-page
# model. Exposure of this token would only allow the attacker to carry out a CSRF attack against the
# victim's active session for a small subset of resources exposed by the web application. Use of the
# unique token per-page property is a strong defense in depth strategy significantly reducing the
# impact of exposed CSRF prevention tokens. The following configuration snippet instructs OWASP
# CSRFGuard to utilize the unique token per-page model:
#
# org.owasp.csrfguard.TokenPerPage=true
# org.owasp.csrfguard.TokenPerPagePrecreate=false
org.owasp.csrfguard.TokenPerPage=true
org.owasp.csrfguard.TokenPerPagePrecreate=false
# Token Rotation
#
# The rotate token property (org.owasp.csrfguard.Rotate) is a boolean value that determines if
# CSRFGuard should generate and utilize a new token after verifying the previous token. Rotation
# helps minimize the window of opportunity an attacker has to leverage the victim's stolen token
# in a targeted CSRF attack. However, this functionality generally causes navigation problems in
# most applications. Specifically, the 'Back' button in the browser will often cease to function
# properly. When a user hits the 'Back' button and interacts with the HTML, the browser may submit
# an old token causing CSRFGuard to incorrectly believe this request is a CSRF attack in progress
# (i.e. a 'false positive'). Users can prevent this scenario by preventing the caching of HTML pages
# containing FORM submissions using the cache-control header. However, this may also introduce
# performance problems as the browser will have to request HTML on a more frequent basis. The following
# configuration snippet enables token rotation:
#
# org.owasp.csrfguard.Rotate=true
# Ajax and XMLHttpRequest Support
#
# The Ajax property (org.owasp.csrfguard.Ajax) is a boolean value that indicates whether or not OWASP
# CSRFGuard should support the injection and verification of unique per-session prevention tokens for
# XMLHttpRequests. To leverage Ajax support, the user must not only set this property to true but must
# also reference the JavaScript DOM Manipulation code using a script element. This dynamic script will
# override the send method of the XMLHttpRequest object to ensure the submission of an X-Requested-With
# header name value pair coupled with the submission of a custom header name value pair for each request.
# The name of the custom header is the value of the token name property and the value of the header is
# always the unique per-session token value. This custom header is analogous to the HTTP parameter name
# value pairs submitted via traditional GET and POST requests. If the X-Requested-With header was sent
# in the HTTP request, then CSRFGuard will look for the presence and ensure the validity of the unique
# per-session token in the custom header name value pair. Note that verification of these headers takes
# precedence over verification of the CSRF token supplied as an HTTP parameter. More specifically,
# CSRFGuard does not verify the presence of the CSRF token if the Ajax support property is enabled and
# the corresponding X-Requested-With and custom headers are embedded within the request. The following
# configuration snippet instructs OWASP CSRFGuard to support Ajax requests by verifying the presence and
# correctness of the X-Requested-With and custom headers:
#
# org.owasp.csrfguard.Ajax=true
org.owasp.csrfguard.Ajax=true
# The default behavior of CSRFGuard is to protect all pages. Pages marked as unprotected will not be protected.
# If the Protect property is enabled, this behavior is reversed. Pages must be marked as protected to be protected.
# All other pages will not be protected. This is useful when the CsrfGuardFilter is aggressively mapped (ex: /*),
# but you only want to protect a few pages.
#
# org.owasp.csrfguard.Protect=true
# Unprotected Pages:
#
# The unprotected pages property (org.owasp.csrfguard.unprotected.*) defines a series of pages that
# should not be protected by CSRFGuard. Such configurations are useful when the CsrfGuardFilter is
# aggressively mapped (ex: /*). The syntax of the property name is org.owasp.csrfguard.unprotected.[PageName],
# where PageName is some arbitrary identifier that can be used to reference a resource. The syntax of
# defining the uri of unprotected pages is the same as the syntax used by the JavaEE container for uri mapping.
# Specifically, CSRFGuard will identify the first match (if any) between the requested uri and an unprotected
# page in order of declaration. Match criteria is as follows:
#
# Case 1: exact match between request uri and unprotected page
# Case 2: longest path prefix match, beginning / and ending /*
# Case 3: extension match, beginning *.
# Case 4: if the value starts with ^ and ends with $, it will be evaulated as a regex. Note that before the
# regex is compiled, any common variables will be substituted (e.g. %servletContext%)
# Default: requested resource must be validated by CSRFGuard
#
# The following code snippet illustrates the four use cases over four examples. The first two examples
# (Tag and JavaScriptServlet) look for direct URI matches. The third example (Html) looks for all resources
# ending in a .html extension. The next example (Public) looks for all resources prefixed with the URI path /MySite/Public/*.
# The last example looks for resources that end in Public.do
#
# org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
# org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
# org.owasp.csrfguard.unprotected.Html=*.html
# org.owasp.csrfguard.unprotected.Public=%servletContext%/Public/*
# regex example starts with ^ and ends with $, and the %servletContext% is evaluated before the regex
# org.owasp.csrfguard.unprotected.PublicServlet=^%servletContext%/.*Public\.do$
#org.owasp.csrfguard.unprotected.Default=%servletContext%/
#org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html
#org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
#org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html
#org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html
#org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html
#org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html
#org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
#org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp
#org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp
#org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp
# Actions: Responding to Attacks
#
# The actions directive (org.owasp.csrfguard.action.*) gives the user the ability to specify one or more
# actions that should be invoked when a CSRF attack is detected. Every action must implement the
# org.owasp.csrfguard.action.IAction interface either directly or indirectly through the
# org.owasp.csrfguard.action.AbstractAction helper class. Many actions accept parameters that can be specified
# along with the action class declaration. These parameters are consumed at runtime and impact the behavior of
# the associated action.
#
# The syntax for defining and configuring CSRFGuard actions is relatively straight forward. Let us assume we wish
# to redirect the user to a default page when a CSRF attack is detected. A redirect action already exists within
# the CSRFGuard bundle and is available via the class name org.owasp.csrfguard.actions.Redirect. In order to enable
# this action, we capture the following declaration in the Owasp.CsrfGuard.properties file:
#
# syntax: org.owasp.csrfguard.action.[actionName]=[className]
# example: org.owasp.csrfguard.action.class.Redirect=org.owasp.csrfguard.actions.Redirect
#
# The aforementioned directive declares an action called "Redirect" (i.e. [actionName]) referencing the Java class
# "org.owasp.csrfguard.actions.Redirect" (i.e. [className]). Anytime a CSRF attack is detected, the Redirect action
# will be executed. You may be asking yourself, "but how do I specify where the user is redirected?"; this is where
# action parameters come into play. In order to specify the redirect location, we capture the following declaration
# in the Owasp.CsrfGuard.properties file:
#
# syntax: org.owasp.csrfguard.action.[actionName].[parameterName]=[parameterValue]
# example: org.owasp.csrfguard.action.Redirect.ErrorPage=%servletContext%/error.html
#
# The aforementioned directive declares an action parameter called "ErrorPage" (i.e. [parameterName]) with the value
# of "%servletContext%/error.html" (i.e. [parameterValue]) for the action "Redirect" (i.e. [actionName]). The
# Redirect action expects the "ErrorPage" parameter to be defined and will redirect the user to this location when
# an attack is detected.
#
#org.owasp.csrfguard.action.Empty=org.owasp.csrfguard.action.Empty
org.owasp.csrfguard.action.Log=org.owasp.csrfguard.action.Log
org.owasp.csrfguard.action.Log.Message=potential cross-site request forgery (CSRF) attack thwarted (user:%user%, ip:%remote_ip%, method:%request_method%, uri:%request_uri%, error:%exception_message%)
#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate
org.owasp.csrfguard.action.Redirect=org.owasp.csrfguard.action.Redirect
org.owasp.csrfguard.action.Redirect.Page=%servletContext%/error.html
#org.owasp.csrfguard.action.RequestAttribute=org.owasp.csrfguard.action.RequestAttribute
#org.owasp.csrfguard.action.RequestAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key
org.owasp.csrfguard.action.Rotate=org.owasp.csrfguard.action.Rotate
#org.owasp.csrfguard.action.SessionAttribute=org.owasp.csrfguard.action.SessionAttribute
#org.owasp.csrfguard.action.SessionAttribute.AttributeName=Owasp_CsrfGuard_Exception_Key
#org.owasp.csrfguard.action.Error=org.owasp.csrfguard.action.Error
#org.owasp.csrfguard.action.Error.Code=403
#org.owasp.csrfguard.action.Error.Message=Security violation.
# Token Name
#
# The token name property (org.owasp.csrfguard.TokenName) defines the name of the HTTP parameter
# to contain the value of the OWASP CSRFGuard token for each request. The following configuration
# snippet sets the CSRFGuard token parameter name to the value OWASP-CSRFTOKEN:
#
# org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN
org.owasp.csrfguard.TokenName=OWASP-CSRFTOKEN
# Session Key
#
# The session key property (org.owasp.csrfguard.SessionKey) defines the string literal used to save
# and lookup the CSRFGuard token from the session. This value is used by the filter and the tag
# libraries to retrieve and set the token value in the session. Developers can use this key to
# programmatically lookup the token within their own code. The following configuration snippet sets
# the session key to the value OWASP_CSRFTOKEN:
#
# org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN
org.owasp.csrfguard.SessionKey=OWASP_CSRFTOKEN
# Token Length
#
# The token length property (org.owasp.csrfguard.TokenLength) defines the number of characters that
# should be found within the CSRFGuard token. Note that characters are delimited by dashes (-) in groups
# of four. For cosmetic reasons, users are encourage to ensure the token length is divisible by four.
# The following configuration snippet sets the token length property to 32 characters:
#
# org.owasp.csrfguard.TokenLength=32
org.owasp.csrfguard.TokenLength=32
# Pseudo-random Number Generator
#
# The pseudo-random number generator property (org.owasp.csrfguard.PRNG) defines what PRNG should be used
# to generate the OWASP CSRFGuard token. Always ensure this value references a cryptographically strong
# pseudo-random number generator algorithm. The following configuration snippet sets the pseudo-random number
# generator to SHA1PRNG:
#
# org.owasp.csrfguard.PRNG=SHA1PRNG
org.owasp.csrfguard.PRNG=SHA1PRNG
# Pseudo-random Number Generator Provider
# The pseudo-random number generator provider property (org.owasp.csrfguard.PRNG.Provider) defines which
# provider's implementation of org.owasp.csrfguard.PRNG we should utilize. The following configuration
# snippet instructs the JVM to leverage SUN's implementation of the algorithm denoted by the
# org.owasp.csrfguard.PRNG property:
# org.owasp.csrfguard.PRNG.Provider=SUN
org.owasp.csrfguard.PRNG.Provider=SUN
# If not specifying the print config option in the web.xml, you can specify it here, to print the config
# on startup
org.owasp.csrfguard.Config.Print = true
###########################
## Javascript servlet settings if not set in web.xml
## https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection
###########################
# leave this blank and blank in web.xml and it will read from META-INF/csrfguard.js from the jarfile
# Denotes the location of the JavaScript template file that should be consumed and dynamically
# augmented by the JavaScriptServlet class. The default value is WEB-INF/Owasp.CsrfGuard.js.
# Use of this property and the existence of the specified template file is required.
org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js
# Boolean value that determines whether or not the dynamic JavaScript code should be strict
# with regards to what links it should inject the CSRF prevention token. With a value of true,
# the JavaScript code will only place the token in links that point to the same exact domain
# from which the HTML originated. With a value of false, the JavaScript code will place the
# token in links that not only point to the same exact domain from which the HTML originated,
# but sub-domains as well.
org.owasp.csrfguard.JavascriptServlet.domainStrict = true
# Allows the developer to specify the value of the Cache-Control header in the HTTP response
# when serving the dynamic JavaScript file. The default value is private, maxage=28800.
# Caching of the dynamic JavaScript file is intended to minimize traffic and improve performance.
# Note that the Cache-Control header is always set to "no-store" when either the "Rotate"
# "TokenPerPage" options is set to true in Owasp.CsrfGuard.properties.
org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800
# Allows the developer to specify a regular expression describing the required value of the
# Referer header. Any attempts to access the servlet with a Referer header that does not
# match the captured expression is discarded. Inclusion of referer header checking is to
# help minimize the risk of JavaScript Hijacking attacks that attempt to steal tokens from
# the dynamically generated JavaScript. While the primary defenses against JavaScript
# Hijacking attacks are implemented within the dynamic JavaScript itself, referer header
# checking is implemented to achieve defense in depth.
org.owasp.csrfguard.JavascriptServlet.refererPattern = .*
# Similar to javascript servlet referer pattern, but this will make sure the referer of the
# javascript servlet matches the domain of the request. If there is no referer (proxy strips it?)
# then it will not fail. Generally this is a good idea to be true.
org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = true
# Boolean value that determines whether or not the dynamic JavaScript code should
# inject the CSRF prevention token as a hidden field into HTML forms. The default
# value is true. Developers are strongly discouraged from disabling this property
# as most server-side state changing actions are triggered via a POST request.
org.owasp.csrfguard.JavascriptServlet.injectIntoForms = true
# if the token should be injected in GET forms (which will be on the URL)
# if the HTTP method GET is unprotected, then this should likely be false
org.owasp.csrfguard.JavascriptServlet.injectGetForms = true
# if the token should be injected in the action in forms
# note, if injectIntoForms is true, then this might not need to be true
org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true
# Boolean value that determines whether or not the dynamic JavaScript code should
# inject the CSRF prevention token in the query string of src and href attributes.
# Injecting the CSRF prevention token in a URL resource increases its general risk
# of exposure to unauthorized parties. However, most JavaEE web applications respond
# in the exact same manner to HTTP requests and their associated parameters regardless
# of the HTTP method. The risk associated with not protecting GET requests in this
# situation is perceived greater than the risk of exposing the token in protected GET
# requests. As a result, the default value of this attribute is set to true. Developers
# that are confident their server-side state changing controllers will only respond to
# POST requests (i.e. discarding GET requests) are strongly encouraged to disable this property.
org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = true
org.owasp.csrfguard.JavascriptServlet.xRequestedWith = OWASP CSRFGuard Project
###########################
## Config overlay settings if you have the provider above set to ConfigurationOverlayProvider
## This CSRF config provider uses Internet2 Configuration Overlays (documented on Internet2 wiki)
## By default the configuration is read from the Owasp.CsrfGuard.properties
## (which should not be edited), and the Owasp.CsrfGuard.overlay.properties overlays
## the base settings. See the Owasp.CsrfGuard.properties for the possible
## settings that can be applied to the Owasp.CsrfGuard.overlay.properties
###########################
# comma separated config files that override each other (files on the right override the left)
# each should start with file: or classpath:
# e.g. classpath:Owasp.CsrfGuard.properties, file:c:/temp/myFile.properties
org.owasp.csrfguard.configOverlay.hierarchy = classpath:Owasp.CsrfGuard.properties, classpath:Owasp.CsrfGuard.overlay.properties
# seconds between checking to see if the config files are updated
org.owasp.csrfguard.configOverlay.secondsBetweenUpdateChecks = 60
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
自定義覆蓋配置:Owasp.CsrfGuard.overlay.properties
上面文件可采用官網默認,此文件可以進行自定義修改。
org.owasp.csrfguard.configuration.provider.factory=org.owasp.csrfguard.config.overlay.ConfigurationOverlayProviderFactory
org.owasp.csrfguard.JavascriptServlet.refererPattern = http://localhost:80.*
org.owasp.csrfguard.unprotected.Default=%servletContext%/
org.owasp.csrfguard.unprotected.Upload=%servletContext%/upload.html
org.owasp.csrfguard.unprotected.JavaScriptServlet=%servletContext%/JavaScriptServlet
org.owasp.csrfguard.unprotected.Ajax=%servletContext%/ajax.html
org.owasp.csrfguard.unprotected.Error=%servletContext%/error.html
org.owasp.csrfguard.unprotected.Index=%servletContext%/index.html
org.owasp.csrfguard.unprotected.JavaScript=%servletContext%/javascript.html
org.owasp.csrfguard.unprotected.Tag=%servletContext%/tag.jsp
org.owasp.csrfguard.unprotected.Redirect=%servletContext%/redirect.jsp
org.owasp.csrfguard.unprotected.Forward=%servletContext%/forward.jsp
org.owasp.csrfguard.unprotected.Session=%servletContext%/session.jsp
org.owasp.csrfguard.unprotected.Favicon=%servletContext%/favicon.ico
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Token注入
OWASP CSRFGuard的用戶可以使用兩種策略將預防令牌注入HTML:
- JavaScript DOM操作 - 主要是自動化過程,只需要很少的工作量,是大多數Web應用程序的理想選擇
- JSP標記庫 - 提供細粒度策略,適用於自動DOM操作不足的情況。
JavaScript DOM操作
web.xml
聲明並配置JavaScriptServlet:
<!-- 聲明並配置JavaScriptServlet。強烈建議默認使用JavaScript令牌注入策略,Token注入邏輯是自動化的,改動最小。 詳見:https://www.owasp.org/index.php/CSRFGuard_3_Token_Injection#JavaScript_DOM_Manipulation -->
<servlet>
<servlet-name>JavaScriptServlet</servlet-name>
<servlet-class>org.owasp.csrfguard.servlet.JavaScriptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JavaScriptServlet</servlet-name>
<url-pattern>/JavaScriptServlet</url-pattern>
</servlet-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
還需配置參數:sourceFile
org.owasp.csrfguard.JavascriptServlet.sourceFile = /script/csrfguard.js
- 1
注入動態JavaScript:在公共jsp里面或者需要注入的頁面中加入即可。
<script src="/JavaScriptServlet"></script>
- 1
JSP標記庫
頁面中:
<%@ taglib uri="http://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project/Owasp.CsrfGuard.tld" prefix="csrf" %>
- 1
注意:csrf:tokenvalue
的屬性uri
必填。由於公司項目中url提交格式是/xxxx?save
。實際uri為/xxxx
。
顯示Token名稱
<form name="test1" action="protect.html">
<input type="text" name="text" value="text"/>
<input type="submit" name="submit" value="submit"/>
<input type="hidden" name="<csrf:tokenname/>" value="<csrf:tokenvalue uri="protect.html"/>"/>
</form>
- 1
- 2
- 3
- 4
- 5
顯示Token值
<form name="test1" action="protect.html">
<input type="text" name="text" value="text"/>
<input type="submit" name="submit" value="submit"/>
<input type="hidden" name="<csrf:tokenname/>" value="<csrf:tokenvalue/>"/>
</form>
- 1
- 2
- 3
- 4
- 5
使用預防令牌生成鏈接
<a href="protect.html?<csrf:token/>">protect.html</a>
<a href="protect.html?<csrf:token uri="protect.html"/>">protect.html</a>
<csrf:a href="protect.html">protect.html</csrf:a>
- 1
- 2
- 3
- 4
使用預防令牌生成表單
<csrf:form id="formTest2" name="formTest2" action="protect.html">
<input type="text" name="text" value="text"/>
<input type="submit" name="submit" value="submit"/>
</csrf:form>
- 1
- 2
- 3
- 4