Having problems with your account or logging in?
A lot of changes are happening in the community right now. Some may affect you. READ MORE HERE

Reflected File Download in Spring MVC

alvaro_munoz Trusted Contributor.
Trusted Contributor.
0 0 25.6K

File Reflected Download is a relatively new vulnerability. It was presented to the mainstream at BlackHat 2014 by Trustwave security researcher Oren Hafif. 

As summarized in the BlackHat paper, “RFD is a web attack vector that enables attackers to gain complete control over a victim’s machine by virtually downloading a file from a trusted domain.” To execute an RFD attack, the attacker must convince a user to download a malicious executable file served by a trusted server. When the user clicks on the file, the attack is executed by his operating system, abusing the trust the user has in the trusted server.

In order for an attacker to run this attack, the following requirements must be met: 

  • The target domain must be trusted by the victim.
  • The target application must reflect some content that attacker can control.
  • The target application must allow the attacker to control the file extension in the URL request.
  • The target application must allow the attacker to control the Content-Type or Content-Disposition headers.

If these requirements are met, an attacker will be able to craft a URL pointing to the trusted target application that, when visited by the victim, downloads a malicious file that will run execute a payload in victim’s machine if executed.

It may seem hard for an application to be that permissive and still meet all the requirements, but when we looked into it, it seems it’s actually not that difficult. We found that Spring Web MVC was configured by default to do so.

Spring Web MVC content negotiation 

Spring Web MVC allows developers to dynamically convert responses to the format requested by the user. This is extremely useful for developers, since they only need to implement a single controller method to serve content on different formats such as XML or JSON as required by different clients. In order to do this, Spring implements the HTTP Content Negotiation mechanism. Spring Web MVC implementationuses what it calls Content Negotiation. Setting it up is quite easy to set up, let’sand can be done either programmatically or via configuration files. Let’s take a look at how this is done using XML configuration files (Figure 1) or Java config (Figure 2): 

<mvc:annotation-driven content-negotiation-manager="negotiationManager" />
<bean id="negotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
     <!-- Configure Content Negotiation strategy and defaults -->       
<property name="defaultContentType" value="application/xml" /> </bean>

Figure 1: XML Configuration

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        // Configure Content Negotiation strategy and defaults. Eg:
configurer.defaultContentType(MediaType.APPLICATION_XML); } }

Figure 2: Java Config

According to Spring’s documentation, the Web MVC supports several conventions for selecting the response format: URL suffixes, a URL parameter, and/or Accept headers. As a result, the content-type can be requested in any of three ways:

  • Using a path extension (suffix) in the URL. If the incoming URL is something like http://myserver/myapp/accounts/list.html , HTML is required. For a spreadsheet the URL should be http://myserver/myapp/accounts/list.xls.http://myserver/myapp/accounts/list.xls. The suffix to media-type mapping is automatically defined via the JavaBeans Activation Framework or JAF (so activation.jar must be on the class path) or by Servlet Context.
  • With a URL parameter like this: http://myserver/myapp/accounts/list?format=xls. The name of the parameter is “format” by default, but this may be changed. Use of a parameter is disabled by default, but when enabled, it is checked second.
  • Finally, by checking the Accept HTTP header property. This is how HTTP is actually defined to work, but as previously mentioned, it can be problematic to use.

Note that the order of checking is always path extension, parameter, “Accept” header, but there are several properties that can be configured in the ContentNegotationManagerFactoryBean to tweak the negotiation process:

 

Parameter Default Description
mediaTypes When this mapping is not set or when an extension is not found, the Java Action Framework Mappings from file extensions to media types, represented as strings
defaultContentType   Sets the default content type to use when no content type is specified.
favorParameter The default value is false. If set to to true, a request for /hotels?format=pdf will be interpreted as a request for "application/pdf" regardless of the Accept header. Indicates whether a request parameter should be used to determine the requested media type with the second-highest priority; i.e., after path extensions but before the Accept header.
favorPathExtension By default this value is set to true, in which case a request for /hotels.pdf will be interpreted as a request for "application/pdf" regardless of the Accept header. Indicates whether the extension of the request path should be used to determine the requested media type with the highest priority.
ignoreAcceptHeader By default this value is set to false. Indicates whether the HTTP Accept header should be ignored altogether. If set, the Accept header is checked at the 3rd highest priority; that is, after the request path extension and possibly a request parameter if configured.
ignoreUnknownPathExtensions By default this is set to true. Indicates whether to ignore requests that have a file extension that does not match any mapped media types
useJaf The default value is true. Indicates whether to use the Java Activation Framework as a fallback option to map from file extensions to media types. This is used only when setFavorPathExtension(boolean) is set to true.

  

The default procedure is to check the path extension in the URL (eg: foo.json) and use the extension to determine the content type. If the extension is not present, it will try to look for a query parameter that specifies the content type (eg:foo?format=json) and if that fails it will try to use the request “Accept” header to configure the response content type. All good, except that by default if the specified extension is not specified in the mediaType property, it will use Java Activation Framework (JAF) (if present in the classpath) or the Application Server ServletContext to find the right one. 

Content negotiation enables Reflected File Download 

In this example, Spring will use the path extension in the URL (.bat) to determine the response content-type. Since “bat” is unknown to the default configuration, it will use JAF (if available in the classpath as activation.jar) or the Application Server ServletContext to figure out the content type. It turns out that the default content type for .bat (batch) files is “application/x-msdownload” which will instruct the browser to download the file. 

Notice that this is just an example and that there are other scenarios that were also vulnerable to RFD,. fFor example, if path extension strategy is disabled (favorPathExtension = false) and controller is mapped to a URL that contains a path parameter at the end (eg: some/resource/{foo}), attackers will be able to set foo parameter to anything and thus control the filename extension for the browser download (eg: foo.bat). They will also be able to control the response content-type by using any of the other two strategies (parameter or Accept header). 

Disclosure

The Security Research team worked closely with Spring teams to report and help fix this issue. We would like to thank the whole team but especially Rossen Stoyanchev for the prompt response and great work.  

During the bug investigation it was found that not only the content negotiation was affected, but also any controller method returning an application/json response (since Internet Explorer 8 and 9 download these responses by default) and also JSONP endpoints and StringHttpMessageConverters. 

Mitigation 

The issue is now fixed on the following Spring Web MVC versions:

    • For 3.2.x upgrade to 3.2.15+.
    • For4.0.x and 4.1.x upgrade to 4 .1.8+.
    • For 4.2.x upgrade to 4 .2.2+.

Spring team fixed the affected components by checking the requested URL extension against a list of expected extensions (those configured in the content negotiation plus those associated with the HttpMessageConverter being used). More importantly, the solution accepts that a server cannot prevent browsers from downloading server responses on its own soIn addition, Spring Web MVC will now add a “Content-Disposition” response header to control browser behavior. Before writing any content to the body of the response, ifwhen the extension requested is not in this list of expected extensions, a “Content-Disposition” response header will be used to forceforcing a safe file name. 

Further Recommendations 

Although Spring defaults are secure in the versions mentioned above, Security Research and Spring recommend the following practices:

  • Encode, rather than escape, JSON responses. This is also an OWASP XSS recommendation. For an example of how to do that with Spring, see this Github page.​
  • Use Spring Security to add security headers such as "X-Content-Type-Options: nosniff" by default.
  • Configure suffix pattern matching ​to be turned off or restricted to explicitly registered suffixes only.
  • Configure content negotiation to your application needs:
    1. Decide what your content-type strategy should be and make it as simple as possible. Use only the path extension strategy if that works for you, and disable the options for parameter or Accept header if your clients are not using them.
      • Using the path extension strategy, Spring will treat the extension as an indicator of what content type to use and not as part of any path parameters, preventing other attack scenarios. For this reason, we recommend this as the only strategy to use.
    2. Disable JAF by setting setUseJaf to false.
    3. Ignore unknown path extensions by setting ignoreUnknownPathExtension to false.This may not be an option if application is expecting a dot towards the end of the URL.
    4. Set the mediaTypes property with a list of all the media types that the application knows how to handle -- no more, no less.
    5. Set a defaultMediaType so that the response Content-Type header for unknown media types is always controlled.
    6. Set ignoreAcceptHeader to true so an attacker cannot enforce the response Content-Type header value.

CVE 

CVE-­2015-5211 “RFD Attack in Spring Framework” has been assigned to this issue. 

Detection 

If you are a Fortify user, both WebInspect and SCA will be able to detect this vulnerability in your content-negotiated Spring Applications. 

Stay secure!

 

 

 

The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.