fix CVE-2021-29425
This commit is contained in:
parent
24a8588eb5
commit
8308c6716f
182
CVE-2021-29425-1.patch
Normal file
182
CVE-2021-29425-1.patch
Normal file
@ -0,0 +1,182 @@
|
||||
From 2736b6fe0b3fa22ec8e2b4184897ecadb021fc78 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Bodewig <stefan.bodewig@innoq.com>
|
||||
Date: Thu, 21 Dec 2017 13:49:06 +0100
|
||||
Subject: [PATCH 1/4] IO-559 verify hostname part of suspected UNC paths in
|
||||
FileNameUtils
|
||||
|
||||
---
|
||||
.../org/apache/commons/io/FilenameUtils.java | 147 +++++++++++++++++-
|
||||
1 files changed, 146 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
index 9cddebb6..cdbc41c2 100644
|
||||
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
@@ -19,8 +19,12 @@ package org.apache.commons.io;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
+import java.util.List;
|
||||
import java.util.Stack;
|
||||
+import java.util.regex.Matcher;
|
||||
+import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* General filename and filepath manipulation utilities.
|
||||
@@ -679,7 +683,9 @@ public class FilenameUtils {
|
||||
}
|
||||
posUnix = posUnix == NOT_FOUND ? posWin : posUnix;
|
||||
posWin = posWin == NOT_FOUND ? posUnix : posWin;
|
||||
- return Math.min(posUnix, posWin) + 1;
|
||||
+ int pos = Math.min(posUnix, posWin) + 1;
|
||||
+ String hostnamePart = filename.substring(2, pos - 1);
|
||||
+ return isValidHostName(hostnamePart) ? pos : NOT_FOUND;
|
||||
} else {
|
||||
return isSeparator(ch0) ? 1 : 0;
|
||||
}
|
||||
@@ -1450,4 +1456,143 @@ public class FilenameUtils {
|
||||
return list.toArray( new String[ list.size() ] );
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Checks whether a given string is a valid host name according to
|
||||
+ * RFC 3986.
|
||||
+ *
|
||||
+ * <p>Accepted are IP addresses (v4 and v6) as well as what the
|
||||
+ * RFC calls a "reg-name". Percent encoded names don't seem to be
|
||||
+ * valid names in UNC paths.</p>
|
||||
+ *
|
||||
+ * @see "https://tools.ietf.org/html/rfc3986#section-3.2.2"
|
||||
+ * @param name the hostname to validate
|
||||
+ * @return true if the given name is a valid host name
|
||||
+ */
|
||||
+ private static boolean isValidHostName(String name) {
|
||||
+ return isIPv4Address(name) || isIPv6Address(name) || isRFC3986HostName(name);
|
||||
+ }
|
||||
+
|
||||
+ private static final Pattern IPV4_PATTERN =
|
||||
+ Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
|
||||
+ private static final int IPV4_MAX_OCTET_VALUE = 255;
|
||||
+
|
||||
+ // mostly copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet4Address
|
||||
+ private static boolean isIPv4Address(String name) {
|
||||
+ Matcher m = IPV4_PATTERN.matcher(name);
|
||||
+ if (!m.matches() || m.groupCount() != 4) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // verify that address subgroups are legal
|
||||
+ for (int i = 1; i < 5; i++) {
|
||||
+ String ipSegment = m.group(i);
|
||||
+ if (ipSegment == null || ipSegment.length() == 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ int iIpSegment = 0;
|
||||
+
|
||||
+ try {
|
||||
+ iIpSegment = Integer.parseInt(ipSegment);
|
||||
+ } catch(NumberFormatException e) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private static final int IPV6_MAX_HEX_GROUPS = 8;
|
||||
+ private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4;
|
||||
+ private static final int MAX_UNSIGNED_SHORT = 0xffff;
|
||||
+ private static final int BASE_16 = 16;
|
||||
+
|
||||
+ // copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet6Address
|
||||
+ private static boolean isIPv6Address(String inet6Address) {
|
||||
+ boolean containsCompressedZeroes = inet6Address.contains("::");
|
||||
+ if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::"))
|
||||
+ || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ String[] octets = inet6Address.split(":");
|
||||
+ if (containsCompressedZeroes) {
|
||||
+ List<String> octetList = new ArrayList<String>(Arrays.asList(octets));
|
||||
+ if (inet6Address.endsWith("::")) {
|
||||
+ // String.split() drops ending empty segments
|
||||
+ octetList.add("");
|
||||
+ } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) {
|
||||
+ octetList.remove(0);
|
||||
+ }
|
||||
+ octets = octetList.toArray(new String[octetList.size()]);
|
||||
+ }
|
||||
+ if (octets.length > IPV6_MAX_HEX_GROUPS) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ int validOctets = 0;
|
||||
+ int emptyOctets = 0; // consecutive empty chunks
|
||||
+ for (int index = 0; index < octets.length; index++) {
|
||||
+ String octet = octets[index];
|
||||
+ if (octet.length() == 0) {
|
||||
+ emptyOctets++;
|
||||
+ if (emptyOctets > 1) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ emptyOctets = 0;
|
||||
+ // Is last chunk an IPv4 address?
|
||||
+ if (index == octets.length - 1 && octet.contains(".")) {
|
||||
+ if (!isIPv4Address(octet)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ validOctets += 2;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ int octetInt = 0;
|
||||
+ try {
|
||||
+ octetInt = Integer.parseInt(octet, BASE_16);
|
||||
+ } catch (NumberFormatException e) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ validOctets++;
|
||||
+ }
|
||||
+ if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private static final Pattern REG_NAME_PART_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9-]*$");
|
||||
+
|
||||
+ private static boolean isRFC3986HostName(String name) {
|
||||
+ String[] parts = name.split("\\.", -1);
|
||||
+ for (int i = 0; i < parts.length; i++) {
|
||||
+ if (parts[i].length() == 0) {
|
||||
+ // trailing dot is legal, otherwise we've hit a .. sequence
|
||||
+ return i == parts.length - 1;
|
||||
+ }
|
||||
+ if (!REG_NAME_PART_PATTERN.matcher(parts[i]).matches()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
}
|
||||
57
CVE-2021-29425-2.patch
Normal file
57
CVE-2021-29425-2.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 71639e041876e4dca28785ac3e61d80ecc33db44 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Bodewig <stefan.bodewig@innoq.com>
|
||||
Date: Wed, 16 May 2018 08:49:15 +0200
|
||||
Subject: [PATCH 2/4] checkstyle requires javadocs on private methods?
|
||||
|
||||
---
|
||||
.../org/apache/commons/io/FilenameUtils.java | 20 +++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
index cdbc41c2..a829f8c7 100644
|
||||
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
@@ -1476,6 +1476,12 @@ public class FilenameUtils {
|
||||
Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
|
||||
private static final int IPV4_MAX_OCTET_VALUE = 255;
|
||||
|
||||
+ /**
|
||||
+ * Checks whether a given string represents a valid IPv4 address.
|
||||
+ *
|
||||
+ * @param name the name to validate
|
||||
+ * @return true if the given name is a valid IPv4 address
|
||||
+ */
|
||||
// mostly copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet4Address
|
||||
private static boolean isIPv4Address(String name) {
|
||||
Matcher m = IPV4_PATTERN.matcher(name);
|
||||
@@ -1517,6 +1523,12 @@ public class FilenameUtils {
|
||||
private static final int BASE_16 = 16;
|
||||
|
||||
// copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet6Address
|
||||
+ /**
|
||||
+ * Checks whether a given string represents a valid IPv6 address.
|
||||
+ *
|
||||
+ * @param inet6Address the name to validate
|
||||
+ * @return true if the given name is a valid IPv6 address
|
||||
+ */
|
||||
private static boolean isIPv6Address(String inet6Address) {
|
||||
boolean containsCompressedZeroes = inet6Address.contains("::");
|
||||
if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
|
||||
@@ -1582,6 +1594,14 @@ public class FilenameUtils {
|
||||
|
||||
private static final Pattern REG_NAME_PART_PATTERN = Pattern.compile("^[a-zA-Z0-9][a-zA-Z0-9-]*$");
|
||||
|
||||
+ /**
|
||||
+ * Checks whether a given string is a valid host name according to
|
||||
+ * RFC 3986 - not accepting IP addresses.
|
||||
+ *
|
||||
+ * @see "https://tools.ietf.org/html/rfc3986#section-3.2.2"
|
||||
+ * @param name the hostname to validate
|
||||
+ * @return true if the given name is a valid host name
|
||||
+ */
|
||||
private static boolean isRFC3986HostName(String name) {
|
||||
String[] parts = name.split("\\.", -1);
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
--
|
||||
2.23.0
|
||||
|
||||
26
CVE-2021-29425-3.patch
Normal file
26
CVE-2021-29425-3.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From bb388f116290c3e3ff244082fd5c376a45a5c798 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Bodewig <stefan.bodewig@innoq.com>
|
||||
Date: Thu, 17 May 2018 21:03:26 +0200
|
||||
Subject: [PATCH 3/4] isRFC3986HostName applies to IPv4 addresses so we can
|
||||
safe the test
|
||||
|
||||
---
|
||||
src/main/java/org/apache/commons/io/FilenameUtils.java | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
index a829f8c7..b93476bb 100644
|
||||
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
@@ -1469,7 +1469,7 @@ public class FilenameUtils {
|
||||
* @return true if the given name is a valid host name
|
||||
*/
|
||||
private static boolean isValidHostName(String name) {
|
||||
- return isIPv4Address(name) || isIPv6Address(name) || isRFC3986HostName(name);
|
||||
+ return isIPv6Address(name) || isRFC3986HostName(name);
|
||||
}
|
||||
|
||||
private static final Pattern IPV4_PATTERN =
|
||||
--
|
||||
2.23.0
|
||||
|
||||
40
CVE-2021-29425-4.patch
Normal file
40
CVE-2021-29425-4.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 0842e1f60a1ca36c8db76a00c6001a38174de21b Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Bodewig <stefan.bodewig@innoq.com>
|
||||
Date: Thu, 17 May 2018 21:04:34 +0200
|
||||
Subject: [PATCH 4/4] remove IPv4 checks that are unnnecessary due to matching
|
||||
regex
|
||||
|
||||
---
|
||||
.../java/org/apache/commons/io/FilenameUtils.java | 15 ++-------------
|
||||
1 file changed, 2 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
index b93476bb..5da8f786 100644
|
||||
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
|
||||
@@ -1490,20 +1490,9 @@ public class FilenameUtils {
|
||||
}
|
||||
|
||||
// verify that address subgroups are legal
|
||||
- for (int i = 1; i < 5; i++) {
|
||||
+ for (int i = 1; i <= 4; i++) {
|
||||
String ipSegment = m.group(i);
|
||||
- if (ipSegment == null || ipSegment.length() == 0) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- int iIpSegment = 0;
|
||||
-
|
||||
- try {
|
||||
- iIpSegment = Integer.parseInt(ipSegment);
|
||||
- } catch(NumberFormatException e) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
+ int iIpSegment = Integer.parseInt(ipSegment);
|
||||
if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
|
||||
return false;
|
||||
}
|
||||
--
|
||||
2.23.0
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
Name: apache-commons-io
|
||||
Epoch: 1
|
||||
Version: 2.6
|
||||
Release: 6
|
||||
Release: 7
|
||||
Summary: A library of utilities for developing IO functionality.
|
||||
License: ASL 2.0
|
||||
URL: http://commons.apache.org/proper/commons-io
|
||||
Source0: http://archive.apache.org/dist/commons/io/source/commons-io-%{version}-src.tar.gz
|
||||
Patch0000: CVE-2021-29425-1.patch
|
||||
Patch0001: CVE-2021-29425-2.patch
|
||||
Patch0002: CVE-2021-29425-3.patch
|
||||
Patch0003: CVE-2021-29425-4.patch
|
||||
Patch9000: Ignore-some-test-because-bep.patch
|
||||
BuildArch: noarch
|
||||
BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin) maven-local
|
||||
@ -46,6 +50,9 @@ xmvn test --batch-mode --offline verify
|
||||
%doc RELEASE-NOTES.txt
|
||||
|
||||
%changelog
|
||||
* Sat May 8 2021 wangxiao <wangxiao65@huawei.com> - 1:2.6-7
|
||||
- Fix CVE-2021-29425
|
||||
|
||||
* Mon Apr 26 2021 maminjie <maminjie1@huawei.com> - 1:2.6-6
|
||||
- Move the test to the %check stage
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user