@@ -30656,23 +30656,74 @@ configuration. For more information on placeholders, see the javadocs of the
3065630656
3065730657
3065830658
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>>.
3066930709
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:
3067530715
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+ ====
3067630727
3067730728
3067830729[[mvc-ann-matrix-variables]]
@@ -34208,26 +34259,19 @@ And in XML use the `<mvc:interceptors>` element:
3420834259
3420934260[[mvc-config-content-negotiation]]
3421034261==== 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.
3422534267
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).
3422834273
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:
3423134275
3423234276[source,java,indent=0]
3423334277[subs="verbatim,quotes"]
@@ -34238,7 +34282,7 @@ config:
3423834282
3423934283 @Override
3424034284 public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
34241- configurer.favorPathExtension(false).favorParameter(true );
34285+ configurer.mediaType("json", MediaType.APPLICATION_JSON );
3424234286 }
3424334287 }
3424434288----
@@ -34253,8 +34297,6 @@ that in turn can be created with a `ContentNegotiationManagerFactoryBean`:
3425334297 <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
3425434298
3425534299 <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
34256- <property name="favorPathExtension" value="false"/>
34257- <property name="favorParameter" value="true"/>
3425834300 <property name="mediaTypes" >
3425934301 <value>
3426034302 json=application/json
0 commit comments