@@ -30656,23 +30656,74 @@ configuration. For more information on placeholders, see the javadocs of the
30656
30656
30657
30657
30658
30658
30659
- [[mvc-ann-requestmapping-suffix-pattern-match]]
30660
- ===== Path Pattern Matching By Suffix
30661
- By default Spring MVC automatically performs `".*"` suffix pattern matching so
30662
- that a controller mapped to `/person` is also implicitly mapped to `/person.*`.
30663
- This allows indicating content types via file extensions, e.g. `/person.pdf`,
30664
- `/person.xml`, etc. A common pitfall however is when the last path segment of the
30665
- mapping is a URI variable, e.g. `/person/{id}`. While a request for `/person/1.json`
30666
- would correctly result in path variable id=1 and extension ".json", when the id
30667
- naturally contains a dot, e.g. `/person/
[email protected] ` the result does not match
30668
- expectations. Clearly here ".com" is not a file extension.
30659
+ ==== Suffix Pattern Matching
30660
+ By default Spring MVC performs `".{asterisk}"` suffix pattern matching so that a
30661
+ controller mapped to `/person` is also implicitly mapped to `/person.{asterisk}`.
30662
+ This makes it easy to request different representations of a resource through the
30663
+ URL path (e.g. `/person.pdf`, `/person.xml`).
30664
+
30665
+ Suffix pattern matching can be turned off or restricted to a set of path extensions
30666
+ explicitly registered for content negotiation purposes. This is generally
30667
+ recommended to minimize ambiguity with common request mappings such as
30668
+ `/person/{id}` where a dot might not represent a file extension, e.g.
30669
+ `/person/
[email protected] ` vs `/person/
[email protected] `. Furthermore as explained
30670
+ in the note below suffix pattern matching as well as content negotiation may be
30671
+ used in some circumstances to attempt malicious attacks and there are good
30672
+ reasons to restrict them meaningfully.
30673
+
30674
+ See <<mvc-config-path-matching>> for suffix pattern matching configuration and
30675
+ also <<mvc-config-content-negotiation>> for content negotiation configuration.
30676
+
30677
+
30678
+
30679
+ [[mvc-ann-requestmapping-rfd]]
30680
+ ==== Suffix Suffix Pattern Matching and RFD
30681
+
30682
+ Reflected file download (RFD) attack was first described in a
30683
+ https://www.trustwave.com/Resources/SpiderLabs-Blog/Reflected-File-Download---A-New-Web-Attack-Vector/[paper by Trustwave]
30684
+ in 2014. The attack is similar to XSS in that it relies on input
30685
+ (e.g. query parameter, URI variable) being reflected in the response.
30686
+ However instead of inserting JavaScript into HTML, an RFD attack relies on the
30687
+ browser switching to perform a download and treating the response as an executable
30688
+ script if double-clicked based on the file extension (e.g. .bat, .cmd).
30689
+
30690
+ In Spring MVC `@ResponseBody` and `ResponseEntity` methods are at risk because
30691
+ they can render different content types which clients can request including
30692
+ via URL path extensions. Note however that neither disabling suffix pattern matching
30693
+ nor disabling the use of path extensions for content negotiation purposes alone
30694
+ are effective at preventing RFD attacks.
30695
+
30696
+ For comprehensive protection against RFD, prior to rendering the response body
30697
+ Spring MVC adds a `Content-Disposition:attachment;filename=f.txt` header to
30698
+ suggest a fixed and safe download file filename. This is done only if the URL
30699
+ path contains a file extension that is neither whitelisted nor explicitly
30700
+ registered for content negotiation purposes. However it may potentially have
30701
+ side effects when URLs are typed directly into a browser.
30702
+
30703
+ Many common path extensions are whitelisted by
30704
+ default. Furthermore REST API calls are typically not meant to be used as URLs
30705
+ directly in browsers. Nevertheless applications that use custom
30706
+ `HttpMessageConverter` implementations can explicitly register file extensions
30707
+ for content negotiation and the Content-Disposition header will not be added
30708
+ for such extensions. See <<mvc-config-content-negotiation>>.
30669
30709
30670
- The proper way to address this is to configure Spring MVC to only do suffix pattern
30671
- matching against file extensions registered for content negotiation purposes.
30672
- For more on this, first see <<mvc-config-content-negotiation>> and then
30673
- <<mvc-config-path-matching>> showing how to enable suffix pattern matching
30674
- along with how to use registered suffix patterns only.
30710
+ [NOTE]
30711
+ ====
30712
+ This was originally introduced as part of work for
30713
+ http://pivotal.io/security/cve-2015-5211[CVE-2015-5211].
30714
+ Below are additional recommendations from the report:
30675
30715
30716
+ * Encode rather than escape JSON responses. This is also an OWASP XSS recommendation.
30717
+ For an example of how to do that with Spring see https://github.com/rwinch/spring-jackson-owasp[spring-jackson-owasp].
30718
+ * Configure suffix pattern matching to be turned off or restricted to explicitly
30719
+ registered suffixes only.
30720
+ * Configure content negotiation with the properties “useJaf” and “ignoreUknownPathExtension”
30721
+ set to false which would result in a 406 response for URLs with unknown extensions.
30722
+ Note however that this may not be an option if URLs are naturally expected to have
30723
+ a dot towards the end.
30724
+ * Add `X-Content-Type-Options: nosniff` header to responses. Spring Security 4 does
30725
+ this by default.
30726
+ ====
30676
30727
30677
30728
30678
30729
[[mvc-ann-matrix-variables]]
@@ -34208,26 +34259,19 @@ And in XML use the `<mvc:interceptors>` element:
34208
34259
34209
34260
[[mvc-config-content-negotiation]]
34210
34261
==== Content Negotiation
34211
- You can configure how Spring MVC determines the requested media types from the client
34212
- for request mapping as well as for content negotiation purposes. The available options
34213
- are to check the file extension in the request URI, the "Accept" header, a request
34214
- parameter, as well as to fall back on a default content type. By default, file extension
34215
- in the request URI is checked first and the "Accept" header is checked next.
34216
-
34217
- For file extensions in the request URI, the MVC Java config and the MVC namespace,
34218
- automatically register extensions such as `.json`, `.xml`, `.rss`, and `.atom` if the
34219
- corresponding dependencies such as Jackson, JAXB2, or Rome are present on the classpath.
34220
- Additional extensions may be not need to be registered explicitly if they can be
34221
- discovered via `ServletContext.getMimeType(String)` or the __Java Activation Framework__
34222
- (see `javax.activation.MimetypesFileTypeMap`). You can register more extensions with the
34223
- {javadoc-baseurl}/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html#setUseRegisteredSuffixPatternMatch(boolean)[setUseRegisteredSuffixPatternMatch
34224
- method].
34262
+ You can configure how Spring MVC determines the requested media types from the request.
34263
+ The available options are to check the URL path for a file extension, check the
34264
+ "Accept" header, a specific query parameter, or to fall back on a default content
34265
+ type when nothing is requested. By default the path extension in the request URI
34266
+ is checked first and the "Accept" header is checked second.
34225
34267
34226
- The introduction of `ContentNegotiationManager` also enables selective suffix pattern
34227
- matching for incoming requests. For more details, see its javadocs.
34268
+ The MVC Java config and the MVC namespace register `json`, `xml`, `rss`, `atom` by
34269
+ default if corresponding dependencies are on the classpath. Additional
34270
+ path extension-to-media type mappings may also be registered explicitly and that
34271
+ also has the effect of whitelisting them as safe extensions for the purpose of RFD
34272
+ attack detection (see <<mvc-ann-requestmapping-rfd>> for more detail).
34228
34273
34229
- Below is an example of customizing content negotiation options through the MVC Java
34230
- config:
34274
+ Below is an example of customizing content negotiation options through the MVC Java config:
34231
34275
34232
34276
[source,java,indent=0]
34233
34277
[subs="verbatim,quotes"]
@@ -34238,7 +34282,7 @@ config:
34238
34282
34239
34283
@Override
34240
34284
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
34241
- configurer.favorPathExtension(false).favorParameter(true );
34285
+ configurer.mediaType("json", MediaType.APPLICATION_JSON );
34242
34286
}
34243
34287
}
34244
34288
----
@@ -34253,8 +34297,6 @@ that in turn can be created with a `ContentNegotiationManagerFactoryBean`:
34253
34297
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
34254
34298
34255
34299
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
34256
- <property name="favorPathExtension" value="false"/>
34257
- <property name="favorParameter" value="true"/>
34258
34300
<property name="mediaTypes" >
34259
34301
<value>
34260
34302
json=application/json
0 commit comments