I am trying to implement the OWASP CSRF Guard in a web application that I am updating (written in Java 17, running on a tomcat 10.1.25 server). We had been using the ESAPI library, but since we only used 6 unique methods from it, we've decided to use smaller libraries. From all the research I've done, I really only need to use the OWASP Java HTML Sanitizer and the OWASP CSRF Guard. I got the HTML Sanitizer implemented with no issues, but I can't seem to resolve some things with the CSRF Guard.
I have been trying to read and apply the example code I've found:
but I must not be understanding it and applying it correctly. This is what happens:
doPost()
method is not runSometimes it would bring me to a blank page immediately after starting the application. There were no errors in any logs or in the browser console and all server responses were 200, but with blank files.
My web.xml
looks like:
<context-param>
<param-name>Owasp.CsrfGuard.Config</param-name>
<param-value>WEB-INF/csrfguard.properties</param-value>
</context-param>
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardServletContextListener</listener-class>
</listener>
<listener>
<listener-class>org.owasp.csrfguard.CsrfGuardHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>AccessFilter</filter-name>
<filter-class>wy.web.app.security.AccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AccessFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- */ -->
</filter-mapping>
<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>
<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>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
My csrfguard.properties
file is like:
org.owasp.csrfguard.configuration.provider.factory = org.owasp.csrfguard.config.PropertiesConfigurationProviderFactory
org.owasp.csrfguard.Enabled = true
# have test both "true" and "false"
org.owasp.csrfguard.ValidateWhenNoSessionExists = true
org.owasp.csrfguard.TokenLength = 32
org.owasp.csrfguard.TokenName = OWASP-CSRFTOKEN
org.owasp.csrfguard.SessionKey = OWASP-CSRFTOKEN
org.owasp.csrfguard.PRNG = SHA1PRNG
org.owasp.csrfguard.PRNG.Provider = SUN
org.owasp.csrfguard.Ajax = true
org.owasp.csrfguard.LogicalSessionExtractor = org.owasp.csrfguard.session.SessionTokenKeyExtractor
org.owasp.csrfguard.JavascriptServlet.sourceFile = WEB-INF/Owasp.CsrfGuard.js
org.owasp.csrfguard.JavascriptServlet.domainStrict = false
org.owasp.csrfguard.JavascriptServlet.cacheControl = private, maxage=28800, no-cache, no-store, must-revalidate
org.owasp.csrfguard.JavascriptServlet.refererPattern = .*
# have test both "true" and "false"
org.owasp.csrfguard.JavascriptServlet.refererMatchProtocol = false
# have test both "true" and "false"
org.owasp.csrfguard.JavascriptServlet.refererMatchDomain = false
org.owasp.csrfguard.JavascriptServlet.injectIntoForms = true
org.owasp.csrfguard.JavascriptServlet.injectGetForms = true
org.owasp.csrfguard.JavascriptServlet.injectFormAttributes = true
org.owasp.csrfguard.JavascriptServlet.injectIntoAttributes = true
org.owasp.csrfguard.JavascriptServlet.injectIntoDynamicNodes = false
org.owasp.csrfguard.JavascriptServlet.xRequestedWith = OWASP CSRFGuard Project
org.owasp.csrfguard.JavascriptServlet.UnprotectedExtensions = js, css, gif, png, ico, jpg
org.owasp.csrfguard.configOverlay.hierarchy = file:WEB-INF/csrfguard.properties
# Mark the login page as unprotected, at least for testing
org.owasp.csrfguard.unprotected.Login = %servletContext%/login.jsp
org.owasp.csrfguard.unprotected.Error = %servletContext%/error.jsp
# Actions to perform when an attack is detected
# 1. Log the information
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%)
# 2. Rotate the token; not supported with AJAX
#org.owasp.csrfguard.action.Rotate = org.owasp.csrfguard.action.Rotate
# 3. Invalidate the token that was misused
#org.owasp.csrfguard.action.Invalidate=org.owasp.csrfguard.action.Invalidate
# 4. Redirect the user/hacker to a specific page
#org.owasp.csrfguard.action.Redirect = org.owasp.csrfguard.action.Redirect
#org.owasp.csrfguard.action.Redirect.Page = /Owasp.CsrfGuard.Test/error.html
org.owasp.csrfguard.Logger = org.owasp.csrfguard.log.JavaLogger
org.owasp.csrfguard.log.JavaLogger.level = TRACE
org.owasp.csrfguard.Config.Print = true
org.owasp.csrfguard.forceSynchronousAjax = true
Why doesn't the next page load? Why are there no errors?
I found the answer to this question while writing it! In #5 of the process I described, I remembered seeing something in other's csrfguard.properties
files. It turns out that defining the org.owasp.csrfguard.ProtectedMethods
is required. Since it was commented out in CSRFGuard's property file, I thought there were some default settings for it--but apparently not! Setting it to POST
fixed the issue!
I also think that if I had set up the CSRFGuard error page, I may have noticed this issue sooner; maybe something like
org.owasp.csrfguard.action.Redirect = org.owasp.csrfguard.action.Redirect
org.owasp.csrfguard.action.Redirect.Page = %servletContext%/error.html