Skip to content

Commit

Permalink
Fixed NewTokenLandingPage functionality OWASP#55
Browse files Browse the repository at this point in the history
* If the user has no session (e.g. missing JSESSIONID cookie) and the "org.owasp.csrfguard.UseNewTokenLandingPage" property is configured to true, the user will be redirected to the new token landing page (defined by the "org.owasp.csrfguard.NewTokenLandingPage" property). If the "NewTokenLandingPage" is protected, a new CSRF token is sent along in the auto-submit form. The request body and query parameters are discarded.
* Removed null check for the "getNewTokenLandingPage()" method in the "CsrfGuard.java#writeLandingPage" method, because the method is only being invoked if "org.owasp.csrfguard.UseNewTokenLandingPage" is true, which can only happen if the "org.owasp.csrfguard.NewTokenLandingPage" property is not null.

This is a very rare/special use-case that can only happen if an application without authentication is protected against CSRF attacks (probably anti-automation), or if for some reason the CSRF filter is before the integrator application's authentication filter (which is not recommended!), otherwise the authentication filter should redirect to the login page.
  • Loading branch information
forgedhallpass committed Feb 22, 2022
1 parent a1cf527 commit 74008a2
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true
# 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
# 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
Expand Down
21 changes: 5 additions & 16 deletions csrfguard/src/main/java/org/owasp/csrfguard/CsrfGuard.java
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,8 @@ public void onSessionDestroyed(final LogicalSession logicalSession) {
}
}

public void writeLandingPage(final HttpServletRequest request, final HttpServletResponse response, final String logicalSessionKey) throws IOException {
String landingPage = getNewTokenLandingPage();

/* default to current page */
if (landingPage == null) {
landingPage = request.getContextPath() + request.getServletPath();
}
public void writeLandingPage(final HttpServletResponse response, final String logicalSessionKey) throws IOException {
final String landingPage = getNewTokenLandingPage();

/* create auto posting form */
final StringBuilder stringBuilder = new StringBuilder();
Expand All @@ -347,20 +342,14 @@ public void writeLandingPage(final HttpServletRequest request, final HttpServlet
.append("<script type=\"text/javascript\">")
.append("var form = document.createElement(\"form\");")
.append("form.setAttribute(\"method\", \"post\");")
.append("form.setAttribute(\"action\", \"")
.append(landingPage)
.append("\");");
.append(String.format("form.setAttribute(\"action\", \"%s\");", landingPage));

/* only include token if needed */
if (new CsrfValidator().isProtectedPage(landingPage).isProtected()) {
stringBuilder.append("var hiddenField = document.createElement(\"input\");")
.append("hiddenField.setAttribute(\"type\", \"hidden\");")
.append("hiddenField.setAttribute(\"name\", \"")
.append(getTokenName())
.append("\");")
.append("hiddenField.setAttribute(\"value\", \"")
.append(getTokenService().getTokenValue(logicalSessionKey, landingPage))
.append("\");")
.append(String.format("hiddenField.setAttribute(\"name\", \"%s\");", getTokenName()))
.append(String.format("hiddenField.setAttribute(\"value\", \"%s\");", getTokenService().getTokenValue(logicalSessionKey, landingPage)))
.append("form.appendChild(hiddenField);");
}

Expand Down
15 changes: 8 additions & 7 deletions csrfguard/src/main/java/org/owasp/csrfguard/CsrfGuardFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Objects;

public class CsrfGuardFilter implements Filter {

Expand Down Expand Up @@ -81,8 +80,13 @@ private void doFilter(final HttpServletRequest httpServletRequest, final HttpSer
final LogicalSessionExtractor sessionKeyExtractor = csrfGuard.getLogicalSessionExtractor();
final LogicalSession logicalSession = sessionKeyExtractor.extract(httpServletRequest);

if (Objects.isNull(logicalSession)) {
handleNoSession(httpServletRequest, httpServletResponse, interceptRedirectResponse, filterChain, csrfGuard);
if (logicalSession == null) {
if (csrfGuard.isUseNewTokenLandingPage()) {
final LogicalSession createdLogicalSession = sessionKeyExtractor.extractOrCreate(httpServletRequest);
csrfGuard.writeLandingPage(interceptRedirectResponse, createdLogicalSession.getKey());
} else {
handleNoSession(httpServletRequest, httpServletResponse, interceptRedirectResponse, filterChain, csrfGuard);
}
} else {
handleSession(httpServletRequest, interceptRedirectResponse, filterChain, logicalSession, csrfGuard);
}
Expand All @@ -93,15 +97,12 @@ private void handleSession(final HttpServletRequest httpServletRequest, final In

final String logicalSessionKey = logicalSession.getKey();

if (logicalSession.isNew() && csrfGuard.isUseNewTokenLandingPage()) {
csrfGuard.writeLandingPage(httpServletRequest, interceptRedirectResponse, logicalSessionKey);
} else if (new CsrfValidator().isValid(httpServletRequest, interceptRedirectResponse)) {
if (new CsrfValidator().isValid(httpServletRequest, interceptRedirectResponse)) {
filterChain.doFilter(httpServletRequest, interceptRedirectResponse);
} else {
logInvalidRequest(httpServletRequest);
}

// TODO this is not needed in case of un-protected pages
final String requestURI = httpServletRequest.getRequestURI();
final String generatedToken = csrfGuard.getTokenService().generateTokensIfAbsent(logicalSessionKey, httpServletRequest.getMethod(), requestURI);

Expand Down
2 changes: 1 addition & 1 deletion csrfguard/src/main/resources/csrfguard.properties
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ org.owasp.csrfguard.ValidateWhenNoSessionExists = true
# 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
# 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
Expand Down

0 comments on commit 74008a2

Please sign in to comment.