Improper Limitation of a Pathname to a Restricted Directory in Spring Framework
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
3.0.0 → fixed in 3.2.94.0.0 → fixed in 4.0.5
Details
Directory traversal vulnerability in Pivotal Spring Framework 3.x before 3.2.9 and 4.0 before 4.0.5 allows remote attackers to read arbitrary files via a crafted URL.
The fix
Improve StringUtils.cleanPath
spring-core/src/main/java/org/springframework/util/StringUtils.java+6 −1
@@ -622,7 +622,12 @@ public static String cleanPath(String path) {String prefix = "";if (prefixIndex != -1) {prefix = pathToUse.substring(0, prefixIndex + 1);-pathToUse = pathToUse.substring(prefixIndex + 1);+if (prefix.contains("/")) {+prefix = "";+}+else {+pathToUse = pathToUse.substring(prefixIndex + 1);+}}if (pathToUse.startsWith(FOLDER_SEPARATOR)) {prefix = prefix + FOLDER_SEPARATOR;
spring-core/src/test/java/org/springframework/util/StringUtilsTests.java+2 −0
@@ -299,6 +299,8 @@ public void testCleanPath() {assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/../mypath/myfile"));assertEquals("../mypath/myfile", StringUtils.cleanPath("mypath/../../mypath/myfile"));assertEquals("/../mypath/myfile", StringUtils.cleanPath("/../mypath/myfile"));+assertEquals("/mypath/myfile", StringUtils.cleanPath("/a/:b/../../mypath/myfile"));+assertEquals("file:///c:/path/to/the%20file.txt", StringUtils.cleanPath("file:///c:/some/../path/to/the%20file.txt"));}public void testPathEquals() {
Improve StringUtils.cleanPath
spring-core/src/main/java/org/springframework/util/StringUtils.java+6 −1
@@ -622,7 +622,12 @@ public static String cleanPath(String path) {String prefix = "";if (prefixIndex != -1) {prefix = pathToUse.substring(0, prefixIndex + 1);-pathToUse = pathToUse.substring(prefixIndex + 1);+if (prefix.contains("/")) {+prefix = "";+}+else {+pathToUse = pathToUse.substring(prefixIndex + 1);+}}if (pathToUse.startsWith(FOLDER_SEPARATOR)) {prefix = prefix + FOLDER_SEPARATOR;
spring-core/src/test/java/org/springframework/util/StringUtilsTests.java+2 −0
@@ -299,6 +299,8 @@ public void testCleanPath() {assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/../mypath/myfile"));assertEquals("../mypath/myfile", StringUtils.cleanPath("mypath/../../mypath/myfile"));assertEquals("/../mypath/myfile", StringUtils.cleanPath("/../mypath/myfile"));+assertEquals("/mypath/myfile", StringUtils.cleanPath("/a/:b/../../mypath/myfile"));+assertEquals("file:///c:/path/to/the%20file.txt", StringUtils.cleanPath("file:///c:/some/../path/to/the%20file.txt"));}public void testPathEquals() {
Improve StringUtils.cleanPath
spring-core/src/main/java/org/springframework/util/StringUtils.java+6 −1
@@ -621,7 +621,12 @@ public static String cleanPath(String path) {String prefix = "";if (prefixIndex != -1) {prefix = pathToUse.substring(0, prefixIndex + 1);-pathToUse = pathToUse.substring(prefixIndex + 1);+if (prefix.contains("/")) {+prefix = "";+}+else {+pathToUse = pathToUse.substring(prefixIndex + 1);+}}if (pathToUse.startsWith(FOLDER_SEPARATOR)) {prefix = prefix + FOLDER_SEPARATOR;
spring-core/src/test/java/org/springframework/util/StringUtilsTests.java+2 −0
@@ -299,6 +299,8 @@ public void testCleanPath() {assertEquals("../mypath/myfile", StringUtils.cleanPath("../mypath/../mypath/myfile"));assertEquals("../mypath/myfile", StringUtils.cleanPath("mypath/../../mypath/myfile"));assertEquals("/../mypath/myfile", StringUtils.cleanPath("/../mypath/myfile"));+assertEquals("/mypath/myfile", StringUtils.cleanPath("/a/:b/../../mypath/myfile"));+assertEquals("file:///c:/path/to/the%20file.txt", StringUtils.cleanPath("file:///c:/some/../path/to/the%20file.txt"));}public void testPathEquals() {
References
- ADVISORYhttps://nvd.nist.gov/vuln/detail/CVE-2014-3578
- WEBhttps://github.com/spring-projects/spring-framework/issues/16414
- WEBhttps://github.com/spring-projects/spring-framework/commit/748167bfa33c3c69db2d8dbdc3a0e9da692da3a0
- WEBhttps://github.com/spring-projects/spring-framework/commit/8ee465103850a3dca018273fe5952e40d5c45a66
- WEBhttps://github.com/spring-projects/spring-framework/commit/f6fddeb6eb7da625fd711ab371ff16512f431e8d
- WEBhttps://bugzilla.redhat.com/show_bug.cgi?id=1131882
- PACKAGEhttps://github.com/spring-projects/spring-framework
- WEBhttps://lists.debian.org/debian-lts-announce/2019/07/msg00012.html
- WEBhttps://rhn.redhat.com/errata/RHSA-2015-0234.html
- WEBhttps://rhn.redhat.com/errata/RHSA-2015-0235.html
- WEBhttp://jvn.jp/en/jp/JVN49154900/index.html
- WEBhttp://jvndb.jvn.jp/jvndb/JVNDB-2014-000054