From 04df4b70b51248d075746336d0deae372a2f3343 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Tue, 26 Jun 2018 14:05:16 +0200 Subject: [PATCH] Backport fix for arbitrary file write vulnerability - Resolves: rhbz#1584407 --- ...x-arbitrary-file-write-vulnerability.patch | 244 ++++++++++++++++++ ant.spec | 10 +- 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 0001-Fix-arbitrary-file-write-vulnerability.patch diff --git a/0001-Fix-arbitrary-file-write-vulnerability.patch b/0001-Fix-arbitrary-file-write-vulnerability.patch new file mode 100644 index 0000000..b46a948 --- /dev/null +++ b/0001-Fix-arbitrary-file-write-vulnerability.patch @@ -0,0 +1,244 @@ +From 6a0f7b1514cf6163aea998bef6367127abcf413b Mon Sep 17 00:00:00 2001 +From: Stefan Bodewig +Date: Sat, 21 Apr 2018 19:55:02 +0200 +Subject: [PATCH] Fix arbitrary file write vulnerability + +Original commit messages: + +unzip and friends could monitor where they write more closely + +forgot to update the manual + +and forgot two words, oh my + +change stripAbsolutePathSpec's default, credit Snyk +--- + WHATSNEW | 15 ++++++ + manual/Tasks/unzip.html | 12 ++++- + .../org/apache/tools/ant/taskdefs/Expand.java | 37 ++++++++++++-- + src/tests/antunit/taskdefs/unzip-test.xml | 46 ++++++++++++++++++ + .../taskdefs/zip/direscape-absolute.zip | Bin 0 -> 332 bytes + src/tests/antunit/taskdefs/zip/direscape.zip | Bin 0 -> 332 bytes + 6 files changed, 106 insertions(+), 4 deletions(-) + create mode 100644 src/tests/antunit/taskdefs/zip/direscape-absolute.zip + create mode 100644 src/tests/antunit/taskdefs/zip/direscape.zip + +diff --git a/WHATSNEW b/WHATSNEW +index 11e5babf6..472aaa21a 100644 +--- a/WHATSNEW ++++ b/WHATSNEW +@@ -1,6 +1,21 @@ + Changes from Ant 1.10.0 TO Ant 1.10.1 + ===================================== + ++Changes that could break older environments: ++------------------------------------------- ++ ++ * , and will no longer extract entries whose ++ names would make the created files be placed outside of the ++ destination directory anymore by default. A new attribute ++ allowFilesToEscapeDest can be used to override the behavior. ++ Another special case is when stripAbsolutePathSpec is false (which ++ no longer is the default) and the entry's name starts with a ++ (back)slash and allowFilesToEscapeDest hasn't been specified ++ explicitly, in this case the file may be created outside of the ++ dest directory as well. ++ In addition stripAbsolutePathSpec is now true by default. ++ Based on a recommendation by the Snyk Security Research Team. ++ + Fixed bugs: + ----------- + +diff --git a/manual/Tasks/unzip.html b/manual/Tasks/unzip.html +index 8d93b7041..856b50f09 100644 +--- a/manual/Tasks/unzip.html ++++ b/manual/Tasks/unzip.html +@@ -126,7 +126,8 @@

Parameters

+ Note that this changes the entry's name before applying + include/exclude patterns and before using the nested mappers (if + any). since Ant 1.8.0 +- No, defaults to false ++ No, defaults to true since 1.9.12 ++ (used to defaukt to false prior to that) + + + scanForUnicodeExtraFields +@@ -138,6 +139,15 @@

Parameters

+ zip task page + No, defaults to true + ++ ++ allowFilesToEscapeDest ++ Whether to allow the extracted file or directory ++ to be outside of the dest directory. ++ since Ant 1.9.12 ++ No, defaults to false unless ++ stripAbsolutePathSpec is true and the entry's name starts with a leading ++ path spec. ++ + +

Examples

+
+diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java
+index 0ec233308..744ef63a2 100644
+--- a/src/main/org/apache/tools/ant/taskdefs/Expand.java
++++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java
+@@ -67,8 +67,9 @@ public class Expand extends Task {
+     private Union resources = new Union();
+     private boolean resourcesSpecified = false;
+     private boolean failOnEmptyArchive = false;
+-    private boolean stripAbsolutePathSpec = false;
++    private boolean stripAbsolutePathSpec = true;
+     private boolean scanForUnicodeExtraFields = true;
++    private Boolean allowFilesToEscapeDest = null;
+ 
+     public static final String NATIVE_ENCODING = "native-encoding";
+ 
+@@ -256,14 +257,17 @@ public class Expand extends Task {
+                                boolean isDirectory, FileNameMapper mapper)
+                                throws IOException {
+ 
+-        if (stripAbsolutePathSpec && entryName.length() > 0
++        final boolean entryNameStartsWithPathSpec = entryName.length() > 0
+             && (entryName.charAt(0) == File.separatorChar
+                 || entryName.charAt(0) == '/'
+-                || entryName.charAt(0) == '\\')) {
++                || entryName.charAt(0) == '\\');
++        if (stripAbsolutePathSpec && entryNameStartsWithPathSpec) {
+             log("stripped absolute path spec from " + entryName,
+                 Project.MSG_VERBOSE);
+             entryName = entryName.substring(1);
+         }
++        boolean allowedOutsideOfDest = Boolean.TRUE == getAllowFilesToEscapeDest()
++            || null == getAllowFilesToEscapeDest() && !stripAbsolutePathSpec && entryNameStartsWithPathSpec;
+ 
+         if (patternsets != null && patternsets.size() > 0) {
+             String name = entryName.replace('/', File.separatorChar)
+@@ -329,6 +333,12 @@ public class Expand extends Task {
+             mappedNames = new String[] {entryName};
+         }
+         File f = fileUtils.resolveFile(dir, mappedNames[0]);
++        if (!allowedOutsideOfDest && !fileUtils.isLeadingPath(dir, f)) {
++            log("skipping " + entryName + " as its target " + f + " is outside of "
++                + dir + ".", Project.MSG_VERBOSE);
++                return;
++        }
++
+         try {
+             if (!overwrite && f.exists()
+                 && f.lastModified() >= entryDate.getTime()) {
+@@ -524,4 +534,25 @@ public class Expand extends Task {
+         return scanForUnicodeExtraFields;
+     }
+ 
++    /**
++     * Whether to allow the extracted file or directory to be outside of the dest directory.
++     *
++     * @param b the flag
++     * @since Ant 1.9.12
++     */
++    public void setAllowFilesToEscapeDest(boolean b) {
++        allowFilesToEscapeDest = b;
++    }
++
++    /**
++     * Whether to allow the extracted file or directory to be outside of the dest directory.
++     *
++     * @return {@code null} if the flag hasn't been set explicitly,
++     * otherwise the value set by the user.
++     * @since Ant 1.9.12
++     */
++    public Boolean getAllowFilesToEscapeDest() {
++        return allowFilesToEscapeDest;
++    }
++
+ }
+diff --git a/src/tests/antunit/taskdefs/unzip-test.xml b/src/tests/antunit/taskdefs/unzip-test.xml
+index b2c2105dd..bdf5f61e1 100644
+--- a/src/tests/antunit/taskdefs/unzip-test.xml
++++ b/src/tests/antunit/taskdefs/unzip-test.xml
+@@ -24,6 +24,10 @@
+     
+   
+ 
++  
++    
++  
++
+   
+     
+@@ -67,4 +71,46 @@
+     
+     
+   
++
++  
++    
++    
++    
++    
++  
++
++  
++    
++    
++    
++    
++  
++
++  
++    
++    
++    
++    
++    
++    
++  
++
++  
++    
++    
++  
++
++  
++    
++    
++  
+ 
+diff --git a/src/tests/antunit/taskdefs/zip/direscape-absolute.zip b/src/tests/antunit/taskdefs/zip/direscape-absolute.zip
+new file mode 100644
+index 000000000..0bae4aaf1
+--- /dev/null
++++ b/src/tests/antunit/taskdefs/zip/direscape-absolute.zip
+@@ -0,0 +1,5 @@
++PK
++L
/tmp/testdir/UT	7lZnZuxPK
++L/tmp/testdir/aUT	7lZJlZuxPK
++L
A/tmp/testdir/UT7lZuxPK
++LG/tmp/testdir/aUT7lZuxPK
+\ No newline at end of file
+diff --git a/src/tests/antunit/taskdefs/zip/direscape.zip b/src/tests/antunit/taskdefs/zip/direscape.zip
+new file mode 100644
+index 000000000..63cefd2d8
+--- /dev/null
++++ b/src/tests/antunit/taskdefs/zip/direscape.zip
+@@ -0,0 +1,5 @@
++PK
++L
../testinput/UT	7lZnZuxPK
++L../testinput/aUT	7lZJlZuxPK
++L
A../testinput/UT7lZuxPK
++LG../testinput/aUT7lZuxPK
+\ No newline at end of file
+-- 
+2.17.1
+
diff --git a/ant.spec b/ant.spec
index 8eab41c..5e08518 100644
--- a/ant.spec
+++ b/ant.spec
@@ -35,7 +35,7 @@
 
 Name:           ant
 Version:        1.10.1
-Release:        9%{?dist}
+Release:        10%{?dist}
 Epoch:          0
 Summary:        Java build tool
 Summary(it):    Tool per la compilazione di programmi java
@@ -45,6 +45,8 @@ URL:            http://ant.apache.org/
 Source0:        http://www.apache.org/dist/ant/source/apache-ant-%{version}-src.tar.bz2
 Source2:        apache-ant-1.8.ant.conf
 
+Patch1:         0001-Fix-arbitrary-file-write-vulnerability.patch
+
 # Fix some places where copies of classes are included in the wrong jarfiles
 Patch4:         apache-ant-class-path-in-manifest.patch
 
@@ -322,6 +324,8 @@ Javadoc pour %{name}.
 #Fixup version
 find -name build.xml -o -name pom.xml | xargs sed -i -e s/-SNAPSHOT//
 
+%patch1 -p1
+
 # Fix class-path-in-manifest rpmlint warning
 %patch4
 
@@ -595,6 +599,10 @@ cp -pr build/javadocs/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}
 # -----------------------------------------------------------------------------
 
 %changelog
+* Tue Jun 26 2018 Michael Simacek  - 0:1.10.1-10
+- Backport fix for arbitrary file write vulnerability
+- Resolves: rhbz#1584407
+
 * Wed Feb 07 2018 Fedora Release Engineering  - 0:1.10.1-9
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild