Przeglądaj źródła

Merge branch '5.8.x'

Steve Riesenberg 2 lat temu
rodzic
commit
7c3cc1e386

+ 10 - 0
config/src/main/java/org/springframework/security/config/http/HeadersBeanDefinitionParser.java

@@ -101,6 +101,8 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
 
 	private static final String ATT_POLICY_DIRECTIVES = "policy-directives";
 
+	private static final String ATT_HEADER_VALUE = "header-value";
+
 	private static final String CACHE_CONTROL_ELEMENT = "cache-control";
 
 	private static final String HPKP_ELEMENT = "hpkp";
@@ -595,6 +597,14 @@ public class HeadersBeanDefinitionParser implements BeanDefinitionParser {
 				}
 				builder.addPropertyValue("block", block);
 			}
+			XXssProtectionHeaderWriter.HeaderValue headerValue = XXssProtectionHeaderWriter.HeaderValue
+					.from(xssElt.getAttribute(ATT_HEADER_VALUE));
+			if (headerValue != null) {
+				if (disabled) {
+					attrNotAllowed(parserContext, ATT_HEADER_VALUE, ATT_DISABLED, xssElt);
+				}
+				builder.addPropertyValue("headerValue", headerValue);
+			}
 			if (disabled) {
 				return;
 			}

+ 3 - 0
config/src/main/resources/org/springframework/security/config/spring-security-5.8.rnc

@@ -1299,6 +1299,9 @@ xss-protection.attlist &=
 xss-protection.attlist &=
 	## Add mode=block to the header or not, default is on.
 	attribute block {xsd:boolean}?
+xss-protection.attlist &=
+	## Specify the value for the X-Xss-Protection header. When set, overrides both enabled and block attributes.
+	attribute header-value {"0"|"1"|"1; mode=block"}?
 
 content-type-options =
 	## Add a X-Content-Type-Options header to the resopnse. Value is always 'nosniff'.

+ 14 - 0
config/src/main/resources/org/springframework/security/config/spring-security-5.8.xsd

@@ -3652,6 +3652,20 @@
                 </xs:documentation>
          </xs:annotation>
       </xs:attribute>
+      <xs:attribute name="header-value">
+         <xs:annotation>
+            <xs:documentation>Specify the value for the X-Xss-Protection header. When set, overrides both enabled and
+                block attributes.
+                </xs:documentation>
+         </xs:annotation>
+         <xs:simpleType>
+            <xs:restriction base="xs:token">
+               <xs:enumeration value="0"/>
+               <xs:enumeration value="1"/>
+               <xs:enumeration value="1; mode=block"/>
+            </xs:restriction>
+         </xs:simpleType>
+      </xs:attribute>
   </xs:attributeGroup>
   <xs:element name="content-type-options">
       <xs:annotation>

+ 59 - 0
config/src/test/java/org/springframework/security/config/http/HttpHeadersConfigTests.java

@@ -384,6 +384,58 @@ public class HttpHeadersConfigTests {
 		// @formatter:on
 	}
 
+	@Test
+	public void requestWhenSettingXssProtectionHeaderValueToZeroThenDefaultsToZero() throws Exception {
+		Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
+		excludedHeaders.remove("X-XSS-Protection");
+		this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueZero")).autowire();
+		// @formatter:off
+		this.mvc.perform(get("/"))
+				.andExpect(status().isOk())
+				.andExpect(header().string("X-XSS-Protection", "0"))
+				.andExpect(excludes(excludedHeaders));
+		// @formatter:on
+	}
+
+	@Test
+	public void requestWhenSettingXssProtectionHeaderValueToOneThenDefaultsToOne() throws Exception {
+		Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
+		excludedHeaders.remove("X-XSS-Protection");
+		this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueOne")).autowire();
+		// @formatter:off
+		this.mvc.perform(get("/"))
+				.andExpect(status().isOk())
+				.andExpect(header().string("X-XSS-Protection", "1"))
+				.andExpect(excludes(excludedHeaders));
+		// @formatter:on
+	}
+
+	@Test
+	public void requestWhenSettingXssProtectionHeaderValueToOneModeBlockThenDefaultsToOneModeBlock() throws Exception {
+		Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
+		excludedHeaders.remove("X-XSS-Protection");
+		this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionHeaderValueOneModeBlock")).autowire();
+		// @formatter:off
+		this.mvc.perform(get("/"))
+				.andExpect(status().isOk())
+				.andExpect(header().string("X-XSS-Protection", "1; mode=block"))
+				.andExpect(excludes(excludedHeaders));
+		// @formatter:on
+	}
+
+	@Test
+	public void requestWhenSettingXssProtectionDisabledHeaderValueToOneThenDefaultsToOne() throws Exception {
+		Set<String> excludedHeaders = new HashSet<>(defaultHeaders.keySet());
+		excludedHeaders.remove("X-XSS-Protection");
+		this.spring.configLocations(this.xml("DefaultsDisabledWithXssProtectionDisabledAndHeaderValueOne")).autowire();
+		// @formatter:off
+		this.mvc.perform(get("/"))
+				.andExpect(status().isOk())
+				.andExpect(header().string("X-XSS-Protection", "1"))
+				.andExpect(excludes(excludedHeaders));
+		// @formatter:on
+	}
+
 	@Test
 	public void configureWhenXssProtectionDisabledAndBlockSetThenAutowireFails() {
 		/*
@@ -656,6 +708,13 @@ public class HttpHeadersConfigTests {
 				.withMessageContaining("block");
 	}
 
+	@Test
+	public void configureWhenXssProtectionDisabledAndHeaderValueSpecifiedThenAutowireFails() {
+		assertThatExceptionOfType(BeanDefinitionParsingException.class).isThrownBy(
+				() -> this.spring.configLocations(this.xml("XssProtectionDisabledSpecifyingHeaderValue")).autowire())
+				.withMessageContaining("header-value");
+	}
+
 	@Test
 	public void configureWhenFrameOptionsDisabledAndPolicySpecifiedThenAutowireFails() {
 		assertThatExceptionOfType(BeanDefinitionParsingException.class)

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/HttpHeadersConfigTests-DefaultsDisabledWithXssProtectionDisabledAndHeaderValueOne.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2022 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<headers defaults-disabled="true">
+			<xss-protection enabled="false" header-value="1"/>
+		</headers>
+	</http>
+
+	<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/HttpHeadersConfigTests-DefaultsDisabledWithXssProtectionHeaderValueOne.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2022 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<headers defaults-disabled="true">
+			<xss-protection header-value="1"/>
+		</headers>
+	</http>
+
+	<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/HttpHeadersConfigTests-DefaultsDisabledWithXssProtectionHeaderValueOneModeBlock.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2022 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<headers defaults-disabled="true">
+			<xss-protection header-value="1; mode=block"/>
+		</headers>
+	</http>
+
+	<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/HttpHeadersConfigTests-DefaultsDisabledWithXssProtectionHeaderValueZero.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2022 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<headers defaults-disabled="true">
+			<xss-protection header-value="0"/>
+		</headers>
+	</http>
+
+	<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/HttpHeadersConfigTests-XssProtectionDisabledSpecifyingHeaderValue.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2022 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<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"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			https://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			https://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<headers>
+			<xss-protection disabled="true" header-value="1"/>
+		</headers>
+	</http>
+
+	<b:bean name="simple" class="org.springframework.security.config.http.HttpHeadersConfigTests.SimpleController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 6 - 0
docs/modules/ROOT/pages/servlet/appendix/namespace/http.adoc

@@ -577,6 +577,12 @@ This indicates to the browser that the page should not be loaded at all.
 When false and xss-protection-enabled is true, the page will still be rendered when an reflected attack is detected but the response will be modified to protect against the attack.
 Note that there are sometimes ways of bypassing this mode which can often times make blocking the page more desirable.
 
+[[nsa-xss-protection-header-value]]
+* **xss-protection-header-value**
+Explicitly set the value for https://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / Type-1 Cross-Site Scripting (XSS)] header.
+One of: "0", "1", "1; mode=block".
+When set, overrides both enabled and block attributes.
+
 
 [[nsa-xss-protection-parents]]
 === Parent Elements of <xss-protection>

+ 9 - 0
web/src/main/java/org/springframework/security/web/header/writers/XXssProtectionHeaderWriter.java

@@ -149,6 +149,15 @@ public final class XXssProtectionHeaderWriter implements HeaderWriter {
 			this.value = value;
 		}
 
+		public static HeaderValue from(String headerValue) {
+			for (HeaderValue value : values()) {
+				if (value.toString().equals(headerValue)) {
+					return value;
+				}
+			}
+			return null;
+		}
+
 		@Override
 		public String toString() {
 			return this.value;