Author：Badcode@Knownsec 404 Team
Date: August 14, 2018
Chinese Version: https://paper.seebug.org/665/
On April 5, 2018, Pivotal released a Directory Traversal vulnerability in Spring MVC (CVE-2018-1271). Spring Framework versions 5.0 to 5.0.4, 4.3 to 4.3.14, and older unsupported versions allow applications to configure Spring MVC to serve static resources (e.g. CSS, JS, images). When static resources are served from a file system on Windows (as opposed to the classpath, or the ServletContext), a malicious user can send a request using a specially crafted URL that can lead a directory traversal attack.
- Spring Framework 5.0 to 5.0.4.
- Spring Framework 4.3 to 4.3.14
- Older unsupported versions are also affected
- Server runs on a Windows system
- To open the resource file directory using the file protocol
Windows Operating system
web code spring-mvc-showcase
git clone https://github.com/spring-projects/spring-mvc-showcase.git
pom.xml to use Spring Framework 5.0.0.
2.Modify Spring MVC static resource configuration. You can refer to official documentation
According to the official documentation, there are two ways to configure it. Add a new resource file path here by overriding the
addResourceHandlers method in
WebMvcConfigurer. Add the following code to
org.springframework.samples.mvc.config.WebMvcConfig. It uses the
file:// protocol to specify
resources as the static file directory.
3.Start the Project with Jetty
Now the environment has been completed.
Recurring and the Results
Visit the link below:
You can see the contents of the
win.ini successfully read.
When the external access to the static resource, it will call
org.springframework.web.servlet.resource.ResourceHttpRequestHandler:handleRequest to handle the breakpoint debugging here.
Follow up with
The path saved in
/spring-mvc-showcase/resources/%255c%255c..%255c/..%255c/..%255c/..%255c/..%255c/.. %255c/..%255c/..%255c/..%255c/windows/win.ini. The url decode operation is performed when the
request.getAttribute() function runs. The
%5c%5c..%5c/..%5c/..%5c/..%5c /..%5c/..%5c/..%5c/..%5c/..%5c/windows/win.ini. Next, the path will be checked twice, and the decoded values of
path will be checked by the
isInvalidPath function. Let's look at this function.
cleanPath function is called to handle
path. Follow up with:
The purpose of this function is to convert this relative path containing
.. into an absolute path. For example,
/foo/bar/../ will become
/foo/ after being processed by
The problem with
String pathArray = delimitedListToStringArray(pathToUse, "/");. This allows empty elements to exist, that is,
cleanPath will treat
// as a directory, while the operating system does not. Quote an image from @Orange.
The above said that the path will be checked twice. When first calling
%5c%5c..%5c/..%5c/..% 5c/..%5c/..%5c/..%5c/..%5c/..%5c/..%5c/windows/win.ini. Since there is no element equals to
path is separated by
path will not change after being processed by
cleanPath. In the next judgment, the
path does not contain
../, so it finally returns
false, which means it passes the check.
isInvalidPath(URLDecoder.decode(path, "UTF-8")) for the second time, the parameter is
\\..\/..\/..\/..\/..\/ ..\/..\/..\/..\/windows/win.ini. Its value after being processed by
//windows/win.ini. In the next judgment, the
path does not contain
../. It finally returns false and also passes the check.
Continue and get a
path has not changed.
getLocations() gets the path
file:./src/main/resources/ that was previously configured in the configuration file. Follow up.
resolveResource of the
At this time,
resourcePath is the previous
location is the value obtained by
getLocations(). Continue to follow up with
location.createRelativ to get the absolute path of the file and return a
Return to the
resource is a
UrlResource object, and you can see its value is
file:src/main/resources/%5c%5c..%5c/..%5c/..%5c/..%5c /..%5c/..%5c/..%5c/..%5c/..%5c/windows/win.ini. Then call
exists() method to check if the file exists, and call
isReadable () method to detect whether the file is readable. Go into the
Here we will call
isFileURL to determine whether the
url reads the file with the
file:// protocol, which is why the
file:// protocol is used when configuring the static directory.
After the judgment,
this.getFile() will be called to get this file object. This method is in the method class of
org.springframework.util.ResourceUtils. Follow up with:
Here is the judgment of whether it is the
file:// protocol, and then
new File(toURI(resourceUrl).getSchemeSpecificPart()); to convert
resourceUrl to a URL object. Finally call
getSchemeSpecificPart() of the
URI class to get the file path. There is a
decode operation in
getSchemeSpecificPart(), which is to decode
\. Follow up with:
It finally returns to
exists() and returns
true, which means file exists.
Later when calling the
isReadable() method to check if the file is readable, the
getFile will also be called. It will return
true, which means the file is readable.
At this point, the judgment for
resource is over and we will go back to
org.springframework.web.servlet.resource.ResourceHttpRequestHandler:handleRequest(). After getting
resource that has passed the check, we should start preparing the response content, including getting the type of the file (for the content of response) -type), the size of the file (for Content-length of response), etc.. Finally call
this.resourceHttpMessageConverter.write(resource, mediaType, outputMessage); to get the contents of the file and return it to the user.
Follow up with
Follow up with
writeInternal and jump to
Follow up with
As you can see, here you create a
URLConnection instance with
openConnection. In the
openConnection method, it decodes
\ and returns the
InputStream object of the file
decode . And it finnaly reads the content and returns it to the user.
This vulnerability can be triggered under Tomcat because of the double URL encoding of the payload.
In the Spring Framework version greater than 5.0.1 (my test environment is 5.0.4), double URL encoding payload will not work, but a single URL encoded payload works. In this case the vulnerability can not be triggered under Tomcat, because by default when Tomcat encounters a URL containing
%5c(\), it directly returns http400, which can be triggered under jetty.
As for why double URL encoding is not working, it is because
org.springframework.web.servlet.resource.PathResourceResolver has an extra
If it is a double URL encoding payload, decode it once when getting
path. After the
isInvalidPath judgment, then enter the
PathResourceResolver as the picture shows. There it will be coded again and returns to double encoding. Finally, when the file determines whether the
exists() method exists,
getSchemeSpecificPart() can only be decoded once, and then the file cannot be read, which means the file does not exist.
So here you have to use a single encoding.
Look at the official patches which is rewritten up by
processPath to process
path before entering
isInvalidPath. Replace the backslash with a slash, and remove the extra slash, prevent it from passing the check in
isInvalidPath. If you use the double encoding method, it will pass
isInvalidEncodedPath, which will first decode
path, then call
processPath, and finally pass
isInvalidPath, which will not pass the check either.
- 5.0.x users should upgrade to 5.0.5
- 4.3.x users should upgrade to 4.3.15
- Older versions should upgrade to a supported branch
- CVE-2018-1271: Directory Traversal with Spring MVC on Windows
- Breaking Parser Logic! Take Your Path Normalization Off and Pop 0days Out
- Directory Traversal with Spring MVC on Windows
About Knownsec & 404 Team
Beijing Knownsec Information Technology Co., Ltd. was established by a group of high-profile international security experts. It has over a hundred frontier security talents nationwide as the core security research team to provide long-term internationally advanced network security solutions for the government and enterprises.
Knownsec's specialties include network attack and defense integrated technologies and product R&D under new situations. It provides visualization solutions that meet the world-class security technology standards and enhances the security monitoring, alarm and defense abilities of customer networks with its industry-leading capabilities in cloud computing and big data processing. The company's technical strength is strongly recognized by the State Ministry of Public Security, the Central Government Procurement Center, the Ministry of Industry and Information Technology (MIIT), China National Vulnerability Database of Information Security (CNNVD), the Central Bank, the Hong Kong Jockey Club, Microsoft, Zhejiang Satellite TV and other well-known clients.
404 Team, the core security team of Knownsec, is dedicated to the research of security vulnerability and offensive and defensive technology in the fields of Web, IoT, industrial control, blockchain, etc. 404 team has submitted vulnerability research to many well-known vendors such as Microsoft, Apple, Adobe, Tencent, Alibaba, Baidu, etc. And has received a high reputation in the industry.
本文由 Seebug Paper 发布，如需转载请注明来源。本文地址：https://paper.seebug.org/991/