Add Cross Site Tracing (XST) & HTTP Method Tampering Protection

Fixes: gh-5377
This commit is contained in:
Rob Winch 2018-05-24 09:35:27 -05:00
parent 2c92496911
commit 73345e7434
35 changed files with 276 additions and 87 deletions

View File

@ -15,7 +15,10 @@
*/
package org.springframework.security.config.annotation.web.configurers
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.core.userdetails.PasswordEncodedUser
import org.springframework.security.web.firewall.StrictHttpFirewall
import javax.servlet.http.HttpServletResponse
@ -44,7 +47,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
@Unroll
def "csrf applied by default"() {
setup:
loadConfig(CsrfAppliedDefaultConfig)
loadConfig(CsrfAppliedDefaultConfig, AllowHttpMethodsFirewallConfig)
request.method = httpMethod
clearCsrfToken()
when:
@ -66,11 +69,21 @@ class CsrfConfigurerTests extends BaseSpringSpec {
def "csrf default creates CsrfRequestDataValueProcessor"() {
when:
loadConfig(CsrfAppliedDefaultConfig)
loadConfig(CsrfAppliedDefaultConfig, AllowHttpMethodsFirewallConfig)
then:
context.getBean(RequestDataValueProcessor)
}
@Configuration
static class AllowHttpMethodsFirewallConfig {
@Bean
StrictHttpFirewall strictHttpFirewall() {
StrictHttpFirewall result = new StrictHttpFirewall();
result.setAllowedHttpMethods(StrictHttpFirewall.ALLOW_ANY_HTTP_METHOD);
return result;
}
}
@EnableWebSecurity
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {

View File

@ -46,7 +46,7 @@ public class NamespaceHttpFirewallTests extends BaseSpringSpec {
MockFilterChain chain
def setup() {
request = new MockHttpServletRequest()
request = new MockHttpServletRequest("GET", "")
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}

View File

@ -44,7 +44,7 @@ public class NamespaceHttpPortMappingsTests extends BaseSpringSpec {
MockFilterChain chain
def setup() {
request = new MockHttpServletRequest()
request = new MockHttpServletRequest("GET", "")
request.setMethod("GET")
response = new MockHttpServletResponse()
chain = new MockFilterChain()

View File

@ -371,7 +371,7 @@ public class NamespaceRememberMeTests extends BaseSpringSpec {
}
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)

View File

@ -270,7 +270,7 @@ public class RememberMeConfigurerTests extends BaseSpringSpec {
}
Cookie createRememberMeCookie() {
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)

View File

@ -67,7 +67,7 @@ abstract class AbstractHttpConfigTests extends AbstractXmlConfigTests {
}
FilterInvocation createFilterinvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setMethod(method);
request.setRequestURI(null);
request.setServletPath(path);

View File

@ -69,7 +69,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, defaultHeaders)
}
@ -83,7 +83,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, defaultHeaders)
}
@ -98,7 +98,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['X-Frame-Options'] = 'SAMEORIGIN'
@ -131,7 +131,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Content-Type-Options':'nosniff'])
@ -147,7 +147,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'DENY'])
@ -163,7 +163,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'DENY'])
@ -179,7 +179,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'SAMEORIGIN'])
@ -228,7 +228,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
@ -246,7 +246,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
def request = new MockHttpServletRequest()
def request = new MockHttpServletRequest("GET", "")
request.setParameter("from", "https://example.com");
hf.doFilter(request, response, new MockFilterChain())
@ -265,7 +265,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['a':'b'])
@ -283,7 +283,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response , ['a':'b', 'c':'d'])
@ -304,7 +304,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['abc':'def'])
}
@ -346,7 +346,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
@ -363,7 +363,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
@ -380,7 +380,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'0'])
@ -413,7 +413,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
@ -431,7 +431,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains'])
}
@ -447,7 +447,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
response.headerNames.empty
}
@ -465,7 +465,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Strict-Transport-Security': 'max-age=1'])
}
@ -515,7 +515,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@ -535,7 +535,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@ -555,7 +555,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
response.headerNames.empty
}
@ -575,7 +575,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=604800 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@ -595,7 +595,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="'])
}
@ -615,7 +615,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" ; includeSubDomains'])
}
@ -635,7 +635,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" ; report-uri="http://example.net/pkp-report"'])
}
@ -657,7 +657,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
expectedHeaders.remove('Expires')
expectedHeaders.remove('Pragma')
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -675,7 +675,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-Content-Type-Options')
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -693,7 +693,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('Strict-Transport-Security')
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -714,7 +714,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
MockHttpServletResponse response = new MockHttpServletResponse()
def expectedHeaders = [:] << defaultHeaders
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -732,7 +732,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-Frame-Options')
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -750,7 +750,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-XSS-Protection')
when:
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@ -853,7 +853,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['Content-Security-Policy'] = 'default-src \'self\''
then:
@ -885,7 +885,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Content-Security-Policy':'default-src \'self\''])
}
@ -913,7 +913,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['Content-Security-Policy-Report-Only'] = 'default-src https:; report-uri https://example.com/'
then:
@ -931,7 +931,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'no-referrer'])
}
@ -947,7 +947,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'same-origin'])
}

View File

@ -142,7 +142,7 @@ class MiscHttpConfigTests extends AbstractHttpConfigTests {
createAppContext()
then:
Filter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
request.setServletPath("/unprotected");
debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
request.setServletPath("/nomatch");

View File

@ -93,7 +93,7 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
UserDetailsService uds = appContext.getBean('uds')
UserDetailsService uds2 = appContext.getBean('uds2')
when:
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/first/login"
@ -104,7 +104,7 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
verify(uds).loadUserByUsername(anyString()) || true
verifyZeroInteractions(uds2) || true
when:
MockHttpServletRequest request2 = new MockHttpServletRequest()
MockHttpServletRequest request2 = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response2 = new MockHttpServletResponse()
MockFilterChain chain2 = new MockFilterChain()
request2.servletPath = "/login"

View File

@ -115,7 +115,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
createAppContext()
SessionRegistry registry = appContext.getBean(SessionRegistry)
registry.registerNewSession("1", new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER")))
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
String credentials = "user:password"
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
@ -134,7 +134,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
}
}
createAppContext()
MockHttpServletRequest request = new MockHttpServletRequest()
MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
String originalSessionId = request.session.id
String credentials = "user:password"
@ -282,7 +282,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
mockBean(SessionAuthenticationStrategy,'ss')
createAppContext()
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.servletPath = "/login"
request.setMethod("POST");
@ -343,15 +343,15 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
}
};
when: "First session is established"
seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "ok"
mockResponse.redirectedUrl == null
when: "Second session is established"
seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "ok"
mockResponse.redirectedUrl == null
when: "Third session is established"
seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "Rejected"
mockResponse.redirectedUrl == "/max-exceeded";
}

View File

@ -152,7 +152,7 @@ public class FilterChainProxyConfigTests {
}
private void doNormalOperation(FilterChainProxy filterChainProxy) throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setServletPath("/foo/secure/super/somefile.html");
MockHttpServletResponse response = new MockHttpServletResponse();

View File

@ -54,7 +54,7 @@ public class WebSecurityTests {
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();

View File

@ -274,7 +274,7 @@ public class WebSecurityConfigurationTests {
public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() throws Exception {
this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused");
FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), new MockHttpServletResponse(), new MockFilterChain());
AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class);
EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);

View File

@ -68,7 +68,7 @@ public class AuthorizeRequestsTests {
@Before
public void setup() {
this.servletContext = spy(new MockServletContext());
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();

View File

@ -51,7 +51,7 @@ public class HttpSecurityAntMatchersTests {
@Before
public void setup() {
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}

View File

@ -52,7 +52,7 @@ public class HttpSecurityLogoutTests {
@Before
public void setup() {
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}

View File

@ -55,7 +55,7 @@ public class HttpSecurityRequestMatchersTests {
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();

View File

@ -72,7 +72,7 @@ public class SessionManagementConfigurerServlet31Tests {
@Before
public void setup() {
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@ -88,7 +88,7 @@ public class SessionManagementConfigurerServlet31Tests {
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");

View File

@ -55,7 +55,7 @@ public class UrlAuthorizationConfigurerTests {
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
@ -211,4 +211,4 @@ public class UrlAuthorizationConfigurerTests {
this.context.getAutowireCapableBeanFactory().autowireBean(this);
}
}
}

View File

@ -140,7 +140,7 @@ public class OAuth2ClientConfigurerTests {
AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
new HttpSessionOAuth2AuthorizationRequestRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
MockHttpServletResponse response = new MockHttpServletResponse();
authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response);

View File

@ -104,7 +104,7 @@ public class OAuth2LoginConfigurerTests {
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.response = new MockHttpServletResponse();
this.filterChain = new MockFilterChain();

View File

@ -493,7 +493,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
}
private MockHttpServletRequest sockjsHttpRequest(String mapping) {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
"/289/tpyx6mde/websocket");

View File

@ -65,7 +65,7 @@ public class GrantedAuthorityDefaultsJcTests {
public void setup() {
setup("USER");
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
response = new MockHttpServletResponse();
chain = new MockFilterChain();

View File

@ -58,7 +58,7 @@ public class GrantedAuthorityDefaultsXmlTests {
public void setup() {
setup("USER");
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
response = new MockHttpServletResponse();
chain = new MockFilterChain();

View File

@ -123,7 +123,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
}
private FilterInvocation createFilterInvocation(String path, String method) {
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI(null);
request.setMethod(method);

View File

@ -52,7 +52,7 @@ public class NamespaceHttpBasicTests {
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();

View File

@ -73,7 +73,7 @@ public class SessionManagementConfigServlet31Tests {
@Before
public void setup() {
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@ -89,7 +89,7 @@ public class SessionManagementConfigServlet31Tests {
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
@ -112,7 +112,7 @@ public class SessionManagementConfigServlet31Tests {
public void changeSessionId() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");

View File

@ -55,7 +55,7 @@ public class CustomHttpSecurityConfigurerTests {
@Before
public void setup() {
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
request.setMethod("GET");

View File

@ -18,10 +18,15 @@
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<http-firewall ref="firewall"/>
<http auto-config="true"/>
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
<b:bean id="firewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"
p:unsafeAllowAnyHttpMethod="true"/>
</b:beans>

View File

@ -18,13 +18,18 @@
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<http-firewall ref="firewall"/>
<http auto-config="true">
<intercept-url pattern="/authenticated/**" access="authenticated"/>
<csrf/>
</http>
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
<b:bean id="firewall" class="org.springframework.security.web.firewall.StrictHttpFirewall"
p:unsafeAllowAnyHttpMethod="true"/>
</b:beans>

View File

@ -179,6 +179,45 @@ public StrictHttpFirewall httpFirewall() {
}
----
The `StrictHttpFirewall` provides a whitelist of valid HTTP methods that are allowed to protect against https://www.owasp.org/index.php/Cross_Site_Tracing[Cross Site Tracing (XST)] and https://www.owasp.org/index.php/Test_HTTP_Methods_(OTG-CONFIG-006)[HTTP Verb Tampering].
The default valid methods are "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", and "PUT".
If your application needs to modify the valid methods, you can configure a custom `StrictHttpFirewall` bean.
For example, the following will only allow HTTP "GET" and "POST" methods:
[source,xml]
----
<b:bean id="httpFirewall"
class="org.springframework.security.web.firewall.StrictHttpFirewall"
p:allowedHttpMethods="GET,HEAD"/>
<http-firewall ref="httpFirewall"/>
----
The same thing can be achieved with Java Configuration by exposing a `StrictHttpFirewall` bean.
[source,java]
----
@Bean
public StrictHttpFirewall httpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST"));
return firewall;
}
----
[TIP]
====
If you are using `new MockHttpServletRequest()` it currently creates an HTTP method as an empty String "".
This is an invalid HTTP method and will be rejected by Spring Security.
You can resolve this by replacing it with `new MockHttpServletRequest("GET", "")`.
See https://jira.spring.io/browse/SPR-16851[SPR_16851] for an issue requesting to improve this.
====
If you must allow any HTTP method (not recommended), you can use `StrictHttpFirewall.setUnsafeAllowAnyHttpMethod(true)`.
This will disable validation of the HTTP method entirely.
=== Use with other Filter-Based Frameworks
If you're using some other framework that is also filter-based, then you need to make sure that the Spring Security filters come first.
This enables the `SecurityContextHolder` to be populated in time for use by the other filters.

View File

@ -238,7 +238,7 @@ public class FilterChainProxy extends GenericFilterBean {
* @return matching filter list
*/
public List<Filter> getFilters(String url) {
return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, null)
return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET")
.getRequest())));
}

View File

@ -16,6 +16,8 @@
package org.springframework.security.web.firewall;
import org.springframework.http.HttpMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
@ -35,6 +37,11 @@ import java.util.Set;
* </p>
* <ul>
* <li>
* Rejects HTTP methods that are not allowed. This specified to block
* <a href="https://www.owasp.org/index.php/Test_HTTP_Methods_(OTG-CONFIG-006)">HTTP Verb tampering and XST attacks</a>.
* See {@link #setAllowedHttpMethods(Collection)}
* </li>
* <li>
* Rejects URLs that are not normalized to avoid bypassing security constraints. There is
* no way to disable this as it is considered extremely risky to disable this constraint.
* A few options to allow this behavior is to normalize the request prior to the firewall
@ -66,6 +73,11 @@ import java.util.Set;
* @since 4.2.4
*/
public class StrictHttpFirewall implements HttpFirewall {
/**
* Used to specify to {@link #setAllowedHttpMethods(Collection)} that any HTTP method should be allowed.
*/
private static final Set<String> ALLOW_ANY_HTTP_METHOD = Collections.unmodifiableSet(Collections.emptySet());
private static final String ENCODED_PERCENT = "%25";
private static final String PERCENT = "%";
@ -82,6 +94,8 @@ public class StrictHttpFirewall implements HttpFirewall {
private Set<String> decodedUrlBlacklist = new HashSet<String>();
private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods();
public StrictHttpFirewall() {
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
@ -92,6 +106,39 @@ public class StrictHttpFirewall implements HttpFirewall {
this.decodedUrlBlacklist.add(PERCENT);
}
/**
* Sets if any HTTP method is allowed. If this set to true, then no validation on the HTTP method will be performed.
* This can open the application up to <a href="https://www.owasp.org/index.php/Test_HTTP_Methods_(OTG-CONFIG-006)">
* HTTP Verb tampering and XST attacks</a>
* @param unsafeAllowAnyHttpMethod if true, disables HTTP method validation, else resets back to the defaults. Default is false.
* @see #setAllowedHttpMethods(Collection)
* @since 5.1
*/
public void setUnsafeAllowAnyHttpMethod(boolean unsafeAllowAnyHttpMethod) {
this.allowedHttpMethods = unsafeAllowAnyHttpMethod ? ALLOW_ANY_HTTP_METHOD : createDefaultAllowedHttpMethods();
}
/**
* <p>
* Determines which HTTP methods should be allowed. The default is to allow "DELETE", "GET", "HEAD", "OPTIONS",
* "PATCH", "POST", and "PUT".
* </p>
*
* @param allowedHttpMethods the case-sensitive collection of HTTP methods that are allowed.
* @see #setUnsafeAllowAnyHttpMethod(boolean)
* @since 5.1
*/
public void setAllowedHttpMethods(Collection<String> allowedHttpMethods) {
if (allowedHttpMethods == null) {
throw new IllegalArgumentException("allowedHttpMethods cannot be null");
}
if (allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
this.allowedHttpMethods = ALLOW_ANY_HTTP_METHOD;
} else {
this.allowedHttpMethods = new HashSet<>(allowedHttpMethods);
}
}
/**
* <p>
* Determines if semicolon is allowed in the URL (i.e. matrix variables). The default
@ -242,6 +289,7 @@ public class StrictHttpFirewall implements HttpFirewall {
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
rejectForbiddenHttpMethod(request);
rejectedBlacklistedUrls(request);
if (!isNormalized(request)) {
@ -259,6 +307,18 @@ public class StrictHttpFirewall implements HttpFirewall {
};
}
private void rejectForbiddenHttpMethod(HttpServletRequest request) {
if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
return;
}
if (!this.allowedHttpMethods.contains(request.getMethod())) {
throw new RequestRejectedException("The request was rejected because the HTTP method \"" +
request.getMethod() +
"\" was not included within the whitelist " +
this.allowedHttpMethods);
}
}
private void rejectedBlacklistedUrls(HttpServletRequest request) {
for (String forbidden : this.encodedUrlBlacklist) {
if (encodedUrlContains(request, forbidden)) {
@ -277,6 +337,18 @@ public class StrictHttpFirewall implements HttpFirewall {
return new FirewalledResponse(response);
}
private static Set<String> createDefaultAllowedHttpMethods() {
Set<String> result = new HashSet<>();
result.add(HttpMethod.DELETE.name());
result.add(HttpMethod.GET.name());
result.add(HttpMethod.HEAD.name());
result.add(HttpMethod.OPTIONS.name());
result.add(HttpMethod.PATCH.name());
result.add(HttpMethod.POST.name());
result.add(HttpMethod.PUT.name());
return result;
}
private static boolean isNormalized(HttpServletRequest request) {
if (!isNormalized(request.getRequestURI())) {
return false;

View File

@ -69,7 +69,7 @@ public class FilterChainProxyTests {
fcp = new FilterChainProxy(new DefaultSecurityFilterChain(matcher,
Arrays.asList(filter)));
fcp.setFilterChainValidator(mock(FilterChainProxy.FilterChainValidator.class));
request = new MockHttpServletRequest();
request = new MockHttpServletRequest("GET", "");
request.setServletPath("/path");
response = new MockHttpServletResponse();
chain = mock(FilterChain.class);

View File

@ -16,11 +16,17 @@
package org.springframework.security.web.firewall;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
/**
* @author Rob Winch
*/
@ -31,12 +37,61 @@ public class StrictHttpFirewallTests {
private StrictHttpFirewall firewall = new StrictHttpFirewall();
private MockHttpServletRequest request = new MockHttpServletRequest();
private MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
@Test
public void getFirewalledRequestWhenInvalidMethodThenThrowsRequestRejectedException() {
this.request.setMethod("INVALID");
assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
.isInstanceOf(RequestRejectedException.class);
}
// blocks XST attacks
@Test
public void getFirewalledRequestWhenTraceMethodThenThrowsRequestRejectedException() {
this.request.setMethod(HttpMethod.TRACE.name());
assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
.isInstanceOf(RequestRejectedException.class);
}
@Test
// blocks XST attack if request is forwarded to a Microsoft IIS web server
public void getFirewalledRequestWhenTrackMethodThenThrowsRequestRejectedException() {
this.request.setMethod("TRACK");
assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
.isInstanceOf(RequestRejectedException.class);
}
@Test
// HTTP methods are case sensitive
public void getFirewalledRequestWhenLowercaseGetThenThrowsRequestRejectedException() {
this.request.setMethod("get");
assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
.isInstanceOf(RequestRejectedException.class);
}
@Test
public void getFirewalledRequestWhenAllowedThenNoException() {
List<String> allowedMethods = Arrays.asList("DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT");
for (String allowedMethod : allowedMethods) {
this.request = new MockHttpServletRequest(allowedMethod, "");
assertThatCode(() -> this.firewall.getFirewalledRequest(this.request))
.doesNotThrowAnyException();
}
}
@Test
public void getFirewalledRequestWhenInvalidMethodAndAnyMethodThenNoException() {
this.firewall.setUnsafeAllowAnyHttpMethod(true);
this.request.setMethod("INVALID");
assertThatCode(() -> this.firewall.getFirewalledRequest(this.request))
.doesNotThrowAnyException();
}
@Test
public void getFirewalledRequestWhenRequestURINotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setRequestURI(path);
try {
this.firewall.getFirewalledRequest(this.request);
@ -49,7 +104,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenContextPathNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setContextPath(path);
try {
this.firewall.getFirewalledRequest(this.request);
@ -62,7 +117,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenServletPathNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setServletPath(path);
try {
this.firewall.getFirewalledRequest(this.request);
@ -75,7 +130,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenPathInfoNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
this.request = new MockHttpServletRequest();
this.request = new MockHttpServletRequest("GET", "");
this.request.setPathInfo(path);
try {
this.firewall.getFirewalledRequest(this.request);
@ -352,7 +407,7 @@ public class StrictHttpFirewallTests {
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndLowercaseEncodedPathThenNoException() {
this.firewall.setAllowUrlEncodedSlash(true);
this.firewall.setAllowSemicolon(true);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
@ -365,7 +420,7 @@ public class StrictHttpFirewallTests {
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndUppercaseEncodedPathThenNoException() {
this.firewall.setAllowUrlEncodedSlash(true);
this.firewall.setAllowSemicolon(true);
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI("/context-root/a/b;%2F1/c");
request.setContextPath("/context-root");
request.setServletPath("");