debian/0000775000000000000000000000000013316713726007201 5ustar debian/rules0000775000000000000000000000033012156112500010235 0ustar #!/usr/bin/make -f PACKAGE = $(shell dh_listpackages) TMP = $(CURDIR)/debian/$(PACKAGE) %: dh $@ override_dh_auto_test: cp $(CURDIR)/debian/t/data/jar.zip $(CURDIR)/t/data/ AUTOMATED_TESTING=1 dh_auto_test debian/source/0000775000000000000000000000000013316713610010471 5ustar debian/source/format0000664000000000000000000000001412156112500011667 0ustar 3.0 (quilt) debian/source/include-binaries0000664000000000000000000000015213316713610013627 0ustar debian/t/data/jar.zip t/data/dotdot-from-unexistant-path.zip t/data/link-dir.zip t/data/link-samename.zip debian/libarchive-zip-perl.manpages0000664000000000000000000000001712156112500014544 0ustar debian/crc32.1 debian/watch0000664000000000000000000000016312156112500010212 0ustar version=3 https://metacpan.org/release/Archive-Zip/ .*/Archive-Zip-v?(\d[\d.-]+)\.(?:tar(?:\.gz|\.bz2)?|tgz|zip) debian/control0000664000000000000000000000321213316713733010600 0ustar Source: libarchive-zip-perl Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Debian Perl Group Uploaders: Ernesto Hernández-Novich (USB) , Matthias Klose , Salvatore Bonaccorso Section: perl Priority: optional Build-Depends: debhelper (>= 8) Build-Depends-Indep: libperl-minimumversion-perl, libtest-cpan-meta-perl, libtest-minimumversion-perl, libtest-pod-perl, perl, unzip, zip Standards-Version: 3.9.4 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-perl/packages/libarchive-zip-perl.git Vcs-Git: git://anonscm.debian.org/pkg-perl/packages/libarchive-zip-perl.git Homepage: https://metacpan.org/release/Archive-Zip/ Package: libarchive-zip-perl Architecture: all Depends: ${misc:Depends}, ${perl:Depends} Description: Perl module for manipulation of ZIP archives The Archive::Zip module allows a Perl program to create, manipulate, read, and write Zip archive files. . Zip archives can be created, or you can read from existing zip files. Once created, they can be written to files, streams, or strings. . Members can be added, removed, extracted, replaced, rearranged, and enumerated. They can also be renamed or have their dates, comments, or other attributes queried or modified. Their data can be compressed or uncompressed as needed. Members can be created from members in existing Zip files, or from existing directories, files, or strings. debian/copyright0000664000000000000000000000254512156112500011122 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Archive-Zip Upstream-Contact: Adam Kennedy Source: https://metacpan.org/release/Archive-Zip/ Files: * Copyright: 2000-2004, Ned Konz 2005, Steve Peters 2006-2009, Adam Kennedy License: Artistic or GPL-1+ Files: debian/* Copyright: 2001-2003, Ivo Timmermans 2004, Matthias Klose 2005, 2007, Ben Burton 2009-2012, Salvatore Bonaccorso 2009-2011, Ernesto Hernández-Novich (USB) 2010-2013, gregor herrmann License: Artistic or GPL-1+ License: Artistic This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License, which comes with Perl. . On Debian systems, the complete text of the Artistic License can be found in `/usr/share/common-licenses/Artistic'. License: GPL-1+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. . On Debian systems, the complete text of version 1 of the GNU General Public License can be found in `/usr/share/common-licenses/GPL-1'. debian/clean0000664000000000000000000000001712156112500010164 0ustar t/data/jar.zip debian/compat0000664000000000000000000000000212156112500010357 0ustar 8 debian/TODO0000664000000000000000000000017112156112500007650 0ustar possible improvements for t/common.pl cf. #654899 especially http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=654899#128 debian/libarchive-zip-perl.examples0000664000000000000000000000001312156112500014563 0ustar examples/* debian/patches/0000775000000000000000000000000013316715311010620 5ustar debian/patches/fix_example_shebangs.patch0000664000000000000000000000541612156112500016012 0ustar Description: The module provides several example scripts written in Perl that have missing or incorrect shebang lines. This patch adds or changes shebangs to #!/usr/bin/perl in order to comply with Debian Policy. Bug-Debian: http://bugs.debian.org/543659 Forwarded: not-needed Author: Ernesto Hernández-Novich Last-Update: 2010-05-06 --- a/examples/calcSizes.pl +++ b/examples/calcSizes.pl @@ -1,3 +1,4 @@ +#!/usr/bin/perl # Example of how to compute compressed sizes # $Revision: 1.2 $ use strict; --- a/examples/copy.pl +++ b/examples/copy.pl @@ -1,3 +1,4 @@ +#!/usr/bin/perl # Copies a zip file to another. # Usage: # perl copy.pl input.zip output.zip --- a/examples/extract.pl +++ b/examples/extract.pl @@ -1,4 +1,4 @@ -#!/bin/perl -w +#!/usr/bin/perl -w # Extracts the named files into 'extractTest' subdir # usage: # perl extract.pl [-j] zipfile.zip filename [...] --- a/examples/mfh.pl +++ b/examples/mfh.pl @@ -1,3 +1,4 @@ +#!/usr/bin/perl # Prints messages on every chunk write. # Usage: # perl mfh.pl zipfile.zip --- a/examples/selfex.pl +++ b/examples/selfex.pl @@ -1,4 +1,4 @@ -#/usr/bin/perl -w +#!/usr/bin/perl -w # # Shows one way to write a self-extracting archive file. # This is not intended for production use, and it always extracts to a @@ -46,7 +46,7 @@ # below the __DATA__ line is the extraction stub: __DATA__ -#!/usr/local/bin/perl +#!/usr/bin/perl # Self-extracting Zip file extraction stub # Copyright (C) 2002 Ned Konz --- a/examples/unzipAll.pl +++ b/examples/unzipAll.pl @@ -1,4 +1,4 @@ -#!/bin/perl -w +#!/usr/bin/perl -w # Extracts all files from the given zip # $Revision: 1.3 $ # usage: --- a/examples/updateTree.pl +++ b/examples/updateTree.pl @@ -1,3 +1,4 @@ +#!/usr/bin/perl # Shows how to update a Zip in place using a temp file. # # usage: --- a/examples/updateZip.pl +++ b/examples/updateZip.pl @@ -1,3 +1,4 @@ +#!/usr/bin/perl # Shows how to update a Zip in place using a temp file. # $Revision: 1.1 $ # --- a/examples/zipcheck.pl +++ b/examples/zipcheck.pl @@ -1,4 +1,4 @@ -#!/bin/perl -w +#!/usr/bin/perl -w # usage: valid zipname.zip # exits with non-zero status if invalid zip # status = 1: invalid arguments --- a/examples/zipinfo.pl +++ b/examples/zipinfo.pl @@ -1,4 +1,4 @@ -#! /usr/bin/perl -w +#!/usr/bin/perl -w # Print out information about a ZIP file. # Note that this buffers the entire file into memory! # usage: --- a/examples/zip.pl +++ b/examples/zip.pl @@ -1,4 +1,4 @@ -#!/bin/perl -w +#!/usr/bin/perl -w # Creates a zip file, adding the given directories and files. # Usage: # perl zip.pl zipfile.zip file [...] --- a/examples/ziptest.pl +++ b/examples/ziptest.pl @@ -1,4 +1,4 @@ -#!/bin/perl -w +#!/usr/bin/perl -w # $Revision: 1.7 $ # Lists the zipfile given as a first argument and tests CRC's. # Usage: debian/patches/series0000664000000000000000000000051513316715311012036 0ustar fix_example_shebangs.patch fix_META.yml_min_required_perl_version.patch fix-spelling-error.patch 0001-Make-the-embedded-File-Which-which-work-in-BEGIN-blo.patch 0002-TODO-test-for-rt.cpan.org-73797-deflated-empty-file-.patch 0003-Fix-for-rt.cpan.org-73797-deflated-empty-file-direct.patch fix_clean_target.patch CVE-2018-10860.patch debian/patches/fix_META.yml_min_required_perl_version.patch0000664000000000000000000000135312156112500021361 0ustar Description: libarchive-zip-perl FTBFS with Perl::MinimumVersion >= 1.22. libarchive-zip-perl uses functions in tests which requires Perl >= 5.6. Bump required version of Perl in META.yml. Origin: vendor Bug: http://rt.cpan.org/Public/Bug/Display.html?id=52696 Bug-Debian: http://bugs.debian.org/560632 Forwarded: yes Author: Salvatore Bonaccorso Last-Update: 2010-05-06 Applied-Upstream: yes, http://svn.ali.as/cpan/trunk/Archive-Zip/ --- a/META.yml +++ b/META.yml @@ -21,7 +21,7 @@ IO::File: 0 IO::Handle: 0 IO::Seekable: 0 - perl: 5.00396 + perl: 5.006 Test::More: 0.42 Time::Local: 0 no_index: debian/patches/0003-Fix-for-rt.cpan.org-73797-deflated-empty-file-direct.patch0000664000000000000000000000314412156112500023443 0ustar From 92b2b67dd4728d10b053f172063be6ad1d14da8f Mon Sep 17 00:00:00 2001 From: Niko Tyni Date: Wed, 11 Jan 2012 21:47:46 +0200 Subject: [PATCH 3/3] Fix for [rt.cpan.org #73797]: deflated empty file / directory gets corrupted The output header needs to be refreshed also in the case where uncompressed size is 0 but the compressed size is > 0 (deflation of an empty file.) --- lib/Archive/Zip/Member.pm | 2 +- t/17_bug_73797.t | 3 --- 2 files changed, 1 insertions(+), 4 deletions(-) diff --git a/lib/Archive/Zip/Member.pm b/lib/Archive/Zip/Member.pm index f86ef75..d4d709a 100644 --- a/lib/Archive/Zip/Member.pm +++ b/lib/Archive/Zip/Member.pm @@ -1011,7 +1011,7 @@ sub _writeToFileHandle { # I need to do this if I can't refresh the header # and I don't know compressed size or crc32 fields. my $headerFieldsUnknown = ( - ( $self->uncompressedSize() > 0 ) + ( $self->uncompressedSize() > 0 or $self->compressedSize > 0 ) and ($self->compressionMethod() == COMPRESSION_STORED or $self->desiredCompressionMethod() == COMPRESSION_DEFLATED ) ); diff --git a/t/17_bug_73797.t b/t/17_bug_73797.t index 9280d84..8cacf54 100644 --- a/t/17_bug_73797.t +++ b/t/17_bug_73797.t @@ -23,7 +23,4 @@ is($zip->writeToFileNamed(OUTPUTZIP), AZ_OK, 'Wrote file'); my ($status, $zipout) = testZip(); # STDERR->print("status= $status, out=$zipout\n"); skip( "test zip doesn't work", 1 ) if $testZipDoesntWork; -TODO: { - local $TODO = "deflated empty files/directories corrupt the output"; is( $status, 0, "output zip isn't corrupted" ); -} -- 1.7.8.2 debian/patches/fix_clean_target.patch0000664000000000000000000000075212156112500015133 0ustar Description: fix clean target Mangling all filenames into one long string is not what we want. Origin: vendor Bug: https://rt.cpan.org/Ticket/Display.html?id=75197 Forwarded: https://rt.cpan.org/Ticket/Display.html?id=75197 Author: gregor herrmann Last-Update: 2012-02-21 --- a/Makefile.PL +++ b/Makefile.PL @@ -28,7 +28,7 @@ 'Time::Local' => 0, }, clean => { - FILES => join( '', qw{ + FILES => join( ' ', qw{ test.log testdir/* testdir/ debian/patches/fix-spelling-error.patch0000664000000000000000000000074112156112500015363 0ustar Description: Fix spelling error in manpage reported by lintian. Origin: vendor Bug: https://rt.cpan.org/Public/Bug/Display.html?id=59102 Forwarded: yes Author: Salvatore Bonaccorso Last-Update: 2010-07-05 --- a/lib/Archive/Zip.pm +++ b/lib/Archive/Zip.pm @@ -2014,7 +2014,7 @@ * Handle tainted paths correctly -* Work on better compatability with other IO:: modules +* Work on better compatibility with other IO:: modules =head1 SUPPORT debian/patches/0002-TODO-test-for-rt.cpan.org-73797-deflated-empty-file-.patch0000664000000000000000000000351412156112500023244 0ustar From b8adb151fbc48f2cd7b5bb3b95a8e4d8152225e6 Mon Sep 17 00:00:00 2001 From: Niko Tyni Date: Tue, 10 Jan 2012 20:40:04 +0200 Subject: [PATCH 2/3] TODO test for [rt.cpan.org #73797]: deflated empty file / directory gets corrupted When reading a zip with a deflated empty file / directory and then writing it out, the output gets corrupted. 'unzip -t' outputs: Archive: testout.zip META-INF/: ucsize 0 <> csize 2 for STORED entry continuing with "compressed" size value testing: META-INF/ bad CRC 1a6cd7b3 (should be 00000000) Add a TODO test for this. The test file was created with 'jar' from OpenJDK 6: mkdir empty && /usr/lib/jvm/java-6-openjdk/bin/jar c empty/ > empty.jar --- t/17_bug_73797.t | 29 +++++++++++++++++++++++++++++ t/data/jar.zip | Bin 0 -> 427 bytes 2 files changed, 29 insertions(+), 0 deletions(-) create mode 100644 t/17_bug_73797.t create mode 100644 t/data/jar.zip diff --git a/t/17_bug_73797.t b/t/17_bug_73797.t new file mode 100644 index 0000000..9280d84 --- /dev/null +++ b/t/17_bug_73797.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +use strict; + +BEGIN { + $| = 1; + $^W = 1; +} +use Archive::Zip qw( :ERROR_CODES ); +use Test::More tests => 4; + +BEGIN { + unshift @INC, "t/"; + require( File::Spec->catfile('t', 'common.pl') ) + or die "Can't load t/common.pl"; +} + +my $zip = Archive::Zip->new(); +isa_ok( $zip, 'Archive::Zip' ); +is( $zip->read('t/data/jar.zip'), AZ_OK, 'Read file' ); +is($zip->writeToFileNamed(OUTPUTZIP), AZ_OK, 'Wrote file'); + +my ($status, $zipout) = testZip(); +# STDERR->print("status= $status, out=$zipout\n"); +skip( "test zip doesn't work", 1 ) if $testZipDoesntWork; +TODO: { + local $TODO = "deflated empty files/directories corrupt the output"; +is( $status, 0, "output zip isn't corrupted" ); +} -- 1.7.8.2 debian/patches/CVE-2018-10860.patch0000664000000000000000000003617313316715260013337 0ustar From 5c79b9faae0f1dd67cc8288964c72c12e03884f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= Date: Fri, 15 Jun 2018 14:49:47 +0200 Subject: [PATCH] Prevent from traversing symlinks and parent directories when extracting If an attacker-supplied archive contains symbolic links and files that referes to the symbolic links in their path components, the user can be tricked into overwriting any arbitrary file. The same issue is with archives whose members refer to a parent directory (..) in their path components. This patch fixes it by aborting an extraction (extractTree(), extractMember(), extractMemberWithoutPaths()) in those cases by not traversing the dangerous paths and returning AZ_ERORR instead. However, if a user supplies a local file name, the security checks are not performed. This is based on the assumption that a user knows what's on his local file system. CVE-2018-10860 https://bugzilla.redhat.com/show_bug.cgi?id=1591449 --- MANIFEST | 3 + lib/Archive/Zip.pm | 8 + lib/Archive/Zip/Archive.pm | 37 +++++ t/25_traversal.t | 194 +++++++++++++++++++++++++ t/data/dotdot-from-unexistant-path.zip | Bin 0 -> 245 bytes t/data/link-dir.zip | Bin 0 -> 260 bytes t/data/link-samename.zip | Bin 0 -> 257 bytes 7 files changed, 242 insertions(+) create mode 100644 t/25_traversal.t create mode 100644 t/data/dotdot-from-unexistant-path.zip create mode 100644 t/data/link-dir.zip create mode 100644 t/data/link-samename.zip diff --git a/MANIFEST b/MANIFEST index 5420b29..fa96191 100644 --- a/MANIFEST +++ b/MANIFEST @@ -47,6 +47,7 @@ t/09_output_record_sep.t t/10_chmod.t t/11_explorer.t t/12_bug_47223.t +t/25_traversal.t t/97_meta.t t/98_pod.t t/99_pmv.t @@ -57,4 +58,6 @@ t/data/chmod.zip t/data/linux.zip t/data/perl.zip t/data/winzip.zip +t/data/dotdot-from-unexistant-path.zip +t/data/link-dir.zip META.yml Module meta-data (added by MakeMaker) diff --git a/lib/Archive/Zip.pm b/lib/Archive/Zip.pm index 3560a39..bab2221 100644 --- a/lib/Archive/Zip.pm +++ b/lib/Archive/Zip.pm @@ -1088,6 +1088,9 @@ member is used as the name of the extracted file or directory. If you pass C<$extractedName>, it should be in the local file system's format. +If you do not pass C<$extractedName> and the internal filename traverses +a parent directory or a symbolic link, the extraction will be aborted with +C for security reason. All necessary directories will be created. Returns C on success. @@ -1102,6 +1105,9 @@ extracted member (its paths will be deleted too). Otherwise, the internal filename of the member (minus paths) is used as the name of the extracted file or directory. Returns C on success. +If you do not pass C<$extractedName> and the internal filename is equalled +to a local symbolic link, the extraction will be aborted with C for +security reason. =item addMember( $member ) @@ -1539,6 +1545,8 @@ a/x to f:\d\e\x a/b/c to f:\d\e\b\c and ignore ax/d/e and d/e +If the path to the extracted file traverses a parent directory or a symbolic +link, the extraction will be aborted with C for security reason. Returns an error code or AZ_OK if everything worked OK. =back diff --git a/lib/Archive/Zip/Archive.pm b/lib/Archive/Zip/Archive.pm index d9fd02e..23d7c0d 100644 --- a/lib/Archive/Zip/Archive.pm +++ b/lib/Archive/Zip/Archive.pm @@ -184,6 +184,8 @@ sub extractMember { } else { $name = $member->fileName(); + if ((my $ret = _extractionNameIsSafe($name)) + != AZ_OK) { return $ret; } ( $dirName = $name ) =~ s{[^/]*$}{}; $dirName = Archive::Zip::_asLocalName($dirName); $name = Archive::Zip::_asLocalName($name); @@ -218,6 +220,8 @@ sub extractMemberWithoutPaths { unless ($name) { $name = $member->fileName(); $name =~ s{.*/}{}; # strip off directories, if any + if ((my $ret = _extractionNameIsSafe($name)) + != AZ_OK) { return $ret; } $name = Archive::Zip::_asLocalName($name); } my $rc = $member->extractToFileNamed( $name, @_ ); @@ -791,6 +795,37 @@ sub addTreeMatching { return $self->addTree( $root, $dest, $matcher, $compressionLevel ); } +# Check if one of the components of a path to the file or the file name +# itself is an already existing symbolic link. If yes then return an +# error. Continuing and writing to a file traversing a link posseses +# a security threat, especially if the link was extracted from an +# attacker-supplied archive. This would allow writing to an arbitrary +# file. The same applies when using ".." to escape from a working +# directory. +sub _extractionNameIsSafe { + my $name = shift; + my ($volume, $directories) = File::Spec->splitpath($name, 1); + my @directories = File::Spec->splitdir($directories); + if (grep '..' eq $_, @directories) { + return _error( + "Could not extract $name safely: a parent directory is used"); + } + my @path; + my $path; + for my $directory (@directories) { + push @path, $directory; + $path = File::Spec->catpath($volume, File::Spec->catdir(@path), ''); + if (-l $path) { + return _error( + "Could not extract $name safely: $path is an existing symbolic link"); + } + if (!-e $path) { + last; + } + } + return AZ_OK; +} + # $zip->extractTree( $root, $dest [, $volume] ); # # $root and $dest are Unix-style. @@ -819,6 +854,8 @@ sub extractTree { $fileName =~ s{$pattern}{$dest}; # in Unix format # convert to platform format: $fileName = Archive::Zip::_asLocalName( $fileName, $volume ); + if ((my $ret = _extractionNameIsSafe($fileName)) + != AZ_OK) { return $ret; } my $status = $member->extractToFileNamed($fileName); return $status if $status != AZ_OK; } diff --git a/t/25_traversal.t b/t/25_traversal.t new file mode 100644 index 0000000..15fb119 --- /dev/null +++ b/t/25_traversal.t @@ -0,0 +1,194 @@ +use strict; +use warnings; + +use Archive::Zip qw( :ERROR_CODES ); +use File::Spec; +use File::Path; +use lib 't'; +#use common; + +use Test::More tests => 41; + +BEGIN { + unshift @INC, "t/"; + require(File::Spec->catfile('t', 'common.pl') ) + or die "Cant't load t/common.pl"; +} +# These tests check for CVE-2018-10860 vulnerabilities. +# If an archive contains a symlink and then a file that traverses that symlink, +# extracting the archive tree could write into an abitrary file selected by +# the symlink value. +# Another issue is if an archive contains a file whose path component refers +# to a parent direcotory. Then extracting that file could write into a file +# out of current working directory subtree. +# These tests check extracting of these files is refuses and that they are +# indeed not created. + +# Suppress croaking errors, the tests produce some. +Archive::Zip::setErrorHandler(sub {}); +my ($existed, $ret, $zip, $allowed_file, $forbidden_file); + +# Change working directory to a temporary directory because some tested +# functions operarates there and we need prepared symlinks there. +my @data_path = (File::Spec->splitdir(File::Spec->rel2abs('.')), 't', 'data'); +ok(chdir TESTDIR, "Working directory changed"); + +# Case 1: +# link-dir -> /tmp +# link-dir/gotcha-linkdir +# writes into /tmp/gotcha-linkdir file. +SKIP: { + # Symlink tests make sense only if a file system supports them. + my $link = 'trylink'; + $ret = eval { symlink('.', $link)}; + skip 'Symbolic links are not supported', 12 if $@; + unlink $link; + + # Extracting an archive tree must fail + $zip = Archive::Zip->new(); + isa_ok($zip, 'Archive::Zip'); + is($zip->read(File::Spec->catfile(@data_path, 'link-dir.zip')), AZ_OK, + 'Archive read'); + $existed = -e File::Spec->catfile('', 'tmp', 'gotcha-linkdir'); + $ret = eval { $zip->extractTree() }; + is($ret, AZ_ERROR, 'Tree extraction aborted'); + SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e File::Spec->catfile('link-dir', 'gotcha-linkdir'), + 'A file was not created in a symlinked directory'); + } + ok(unlink(File::Spec->catfile('link-dir')), 'link-dir removed'); + + # The same applies to extracting an archive member without an explicit + # local file name. It must abort. + $link = 'link-dir'; + ok(symlink('.', $link), 'A symlink to a directory created'); + $forbidden_file = File::Spec->catfile($link, 'gotcha-linkdir'); + $existed = -e $forbidden_file; + $ret = eval { $zip->extractMember('link-dir/gotcha-linkdir') }; + is($ret, AZ_ERROR, 'Member extraction without a local name aborted'); + SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e $forbidden_file, + 'A file was not created in a symlinked directory'); + } + + # But allow extracting an archive member into a supplied file name + $allowed_file = File::Spec->catfile($link, 'file'); + $ret = eval { $zip->extractMember('link-dir/gotcha-linkdir', $allowed_file) }; + is($ret, AZ_OK, 'Member extraction passed'); + ok(-e $allowed_file, 'File created'); + ok(unlink($allowed_file), 'File removed'); + ok(unlink($link), 'A symlink to a directory removed'); +} + +# Case 2: +# unexisting/../../../../../tmp/gotcha-dotdot-unexistingpath +# writes into ../../../../tmp/gotcha-dotdot-unexistingpath, that is +# /tmp/gotcha-dotdot-unexistingpath file if CWD is not deeper than +# 4 directories. +$zip = Archive::Zip->new(); +isa_ok($zip, 'Archive::Zip'); +is($zip->read(File::Spec->catfile(@data_path, + 'dotdot-from-unexistant-path.zip')), AZ_OK, 'Archive read'); +$forbidden_file = File::Spec->catfile('..', '..', '..', '..', 'tmp', + 'gotcha-dotdot-unexistingpath'); +$existed = -e $forbidden_file; +$ret = eval { $zip->extractTree() }; +is($ret, AZ_ERROR, 'Tree extraction aborted'); +SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e $forbidden_file, 'A file was not created in a parent directory'); +} + +# The same applies to extracting an archive member without an explicit local +# file name. It must abort. +$existed = -e $forbidden_file; +$ret = eval { $zip->extractMember( + 'unexisting/../../../../../tmp/gotcha-dotdot-unexistingpath', + ) }; +is($ret, AZ_ERROR, 'Member extraction without a local name aborted'); +SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e $forbidden_file, 'A file was not created in a parent directory'); +} + +# But allow extracting an archive member into a supplied file name +ok(mkdir('directory'), 'Directory created'); +$allowed_file = File::Spec->catfile('directory', '..', 'file'); +$ret = eval { $zip->extractMember( + 'unexisting/../../../../../tmp/gotcha-dotdot-unexistingpath', + $allowed_file + ) }; +is($ret, AZ_OK, 'Member extraction passed'); +ok(-e $allowed_file, 'File created'); +ok(unlink($allowed_file), 'File removed'); + +# Case 3: +# link-file -> /tmp/gotcha-samename +# link-file +# writes into /tmp/gotcha-samename. It must abort. (Or replace the symlink in +# more relaxed mode in the future.) +$zip = Archive::Zip->new(); +isa_ok($zip, 'Archive::Zip'); +is($zip->read(File::Spec->catfile(@data_path, 'link-samename.zip')), AZ_OK, + 'Archive read'); +$existed = -e File::Spec->catfile('', 'tmp', 'gotcha-samename'); +$ret = eval { $zip->extractTree() }; +is($ret, AZ_ERROR, 'Tree extraction aborted'); +SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e File::Spec->catfile('', 'tmp', 'gotcha-samename'), + 'A file was not created through a symlinked file'); +} +ok(unlink(File::Spec->catfile('link-file')), 'link-file removed'); + +# The same applies to extracting an archive member using extractMember() +# without an explicit local file name. It must abort. +my $link = 'link-file'; +my $target = 'target'; +ok(symlink($target, $link), 'A symlink to a file created'); +$forbidden_file = File::Spec->catfile($target); +$existed = -e $forbidden_file; +# Select a member by order due to same file names. +my $member = ${[$zip->members]}[1]; +ok($member, 'A member to extract selected'); +$ret = eval { $zip->extractMember($member) }; +is($ret, AZ_ERROR, + 'Member extraction using extractMember() without a local name aborted'); +SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e $forbidden_file, + 'A symlinked target file was not created'); +} + +# But allow extracting an archive member using extractMember() into a supplied +# file name. +$allowed_file = $target; +$ret = eval { $zip->extractMember($member, $allowed_file) }; +is($ret, AZ_OK, 'Member extraction using extractMember() passed'); +ok(-e $allowed_file, 'File created'); +ok(unlink($allowed_file), 'File removed'); + +# The same applies to extracting an archive member using +# extractMemberWithoutPaths() without an explicit local file name. +# It must abort. +$existed = -e $forbidden_file; +# Select a member by order due to same file names. +$ret = eval { $zip->extractMemberWithoutPaths($member) }; +is($ret, AZ_ERROR, + 'Member extraction using extractMemberWithoutPaths() without a local name aborted'); +SKIP: { + skip 'A canary file existed before the test', 1 if $existed; + ok(! -e $forbidden_file, + 'A symlinked target file was not created'); +} + +# But allow extracting an archive member using extractMemberWithoutPaths() +# into a supplied file name. +$allowed_file = $target; +$ret = eval { $zip->extractMemberWithoutPaths($member, $allowed_file) }; +is($ret, AZ_OK, 'Member extraction using extractMemberWithoutPaths() passed'); +ok(-e $allowed_file, 'File created'); +ok(unlink($allowed_file), 'File removed'); +ok(unlink($link), 'A symlink to a file removed'); #diff --git a/t/data/dotdot-from-unexistant-path.zip b/t/data/dotdot-from-unexistant-path.zip #new file mode 100644 #index 0000000000000000000000000000000000000000..faaa5bb95c4310ad3dfa8ea7bbad6850da3f2095 #GIT binary patch #literal 245 #zcmWIWW@Zs#0D%jBS9~Vyb&-_^vO(Aih)eTQD>92qGV{{)_4H6sNp69DdVWcAMxt&? #zehCoiBGeWnmSjNWtQ7S06v{J8G87Q93LxnKZ$>5&X51D7?FNHwjUWo48O04iClPW+ #TfHx}}$OJ|p%mC8mAPxfn{*XXp # #literal 0 #HcmV?d00001 # #diff --git a/t/data/link-dir.zip b/t/data/link-dir.zip #new file mode 100644 #index 0000000000000000000000000000000000000000..99fbb437ec0bd694b8122cdb1ce8221a3da2e453 #GIT binary patch #literal 260 #zcmWIWW@Zs#0D Date: Tue, 10 Jan 2012 20:28:48 +0200 Subject: [PATCH 1/3] Make the embedded File::Which::which() work in BEGIN blocks The File::Which::which() subroutine uses a lexical variable @path_ext, which used to be uninitialized when the subroutine was called from BEGIN blocks. This included the 'use constant' lines, making both HAVEZIP and HAVEUNZIP constants unconditionally false and disabling 'testzip' functionality in for instance t/02_main.t: ok 132 # skip No 'unzip' program to test against --- t/common.pl | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/t/common.pl b/t/common.pl index 808d6b8..1560fd2 100644 --- a/t/common.pl +++ b/t/common.pl @@ -7,6 +7,7 @@ use constant OUTPUTZIP => 'testout.zip'; # Do we have the 'zip' and 'unzip' programs? # Embed a copy of the module, rather than adding a dependency +BEGIN { SCOPE: { package File::Which; @@ -103,6 +104,7 @@ SCOPE: { } } } +} use constant HAVEZIP => !! File::Which::which('zip'); use constant HAVEUNZIP => !! File::Which::which('unzip'); -- 1.7.8.2 debian/crc32.10000664000000000000000000000140412156112500010156 0ustar .TH CRC32 1 "June 21, 2005" .SH NAME crc32 \- compute CRC-32 checksums for the given files .SH SYNOPSIS .B crc32 \fIfilename\fP [ \fIfilename\fP ... ] .SH DESCRIPTION \fBcrc32\fP is a simple utility that calculates the CRC-32 checksum for each of the given files. .PP Note that the CRC-32 checksum is merely used for error detection in transmission and storage. It is not intended to guard against the malicious modification of files (i.e., it is not a cryptographic hash). .PP This utility is supplied with the \fBArchive::Zip\fP module for Perl. .SH SEE ALSO .BR Archive::Zip (3pm). .SH AUTHOR The Archive::Zip module was written by Ned Konz. .br This manual page was prepared by Ben Burton for the Debian GNU/Linux system (but may be used by others). debian/changelog0000664000000000000000000002076613316713726011066 0ustar libarchive-zip-perl (1.30-7ubuntu0.1) trusty-security; urgency=medium * SECURITY UPDATE: Traversal path vulnerability - debian/patches/CVE-2018-10860.patch: fix in lib/Archive/Zip/Archive.pm and add test in t/25_traversal.t and some .zip files for test. - CVE-2018-10860 -- Leonidas S. Barbosa Tue, 03 Jul 2018 12:35:32 -0300 libarchive-zip-perl (1.30-7) unstable; urgency=low * Team upload. [ Salvatore Bonaccorso ] * Change Vcs-Git to canonical URI (git://anonscm.debian.org) * Change search.cpan.org based URIs to metacpan.org based URIs [ gregor herrmann ] * Put test file jar.zip into debian/ instead of creating it with quilt. Newer versions of patch don't apply git binary patches. Thanks to Jakub Wilk for the bug report. (Closes: #711951) * debian/copyright: switch formatting to Copyright-Format 1.0. * Update {versioned,alternative} (build) dependencies. * Set Standards-Version to 3.9.4 (no further changes). -- gregor herrmann Wed, 12 Jun 2013 17:34:30 +0200 libarchive-zip-perl (1.30-6) unstable; urgency=low * Team upload. * Add debian/patches/000* to debian/patches/series. Additionally extract t/data/jar.zip manually from debian/patches/0002-* and add it to debian/source/include-binaries (quilt silently ignores the binary part in the patch). Thanks to Niko Tyni (Closes: #654899) * Add build dependency on unzip and zip, used in the test suite. * Add patch fix_clean_target.patch to make upstream's clean target work. Remove override from debian/rules. (Cf. #654901) -- gregor herrmann Wed, 22 Feb 2012 18:14:36 +0100 libarchive-zip-perl (1.30-5) unstable; urgency=low * Team upload. [ Ansgar Burchardt ] * debian/control: Convert Vcs-* fields to Git. [ Damyan Ivanov ] * rules: remove test-created files on clean Thanks to Wookey for the patch. (Closes: #654901) [ gregor herrmann ] * Add new patches 0001-Make-the-embedded-File-Which-which-work-in-BEGIN- blo.patch, 0002-TODO-test-for-rt.cpan.org-73797-deflated-empty- file-.patch, 0003-Fix-for-rt.cpan.org-73797-deflated-empty-file- direct.patch: keep empty file deflated. Thanks to Niko Tyni for analyzing the tricky issue and providing patches. (Closes: #654899) * Update years of packaging copyright. * Bump Standards-Version to 3.9.2 (no further changes). * debian/copyright: update header section. -- gregor herrmann Thu, 12 Jan 2012 23:15:49 +0100 libarchive-zip-perl (1.30-4) unstable; urgency=low [ gregor herrmann ] * Update patch fix_example_shebangs.patch to include yet another hashbang (closes: #601402). [ Ernesto Hernández-Novich (USB) ] * debian/control: updated Standards-Version; upgrade to DH8. * debian/compat: upgrade to DH8. * debian/copyright: update to DEP5; add and update copyright dates; set Upstream-Contact to current CPAN maintainer. [ Salvatore Bonaccorso ] * Email change: Salvatore Bonaccorso -> carnil@debian.org * debian/control: Make Build-Depends-Indep on libtest-cpan-meta-perl unversioned. -- Ernesto Hernández-Novich (USB) Tue, 01 Mar 2011 07:54:20 -0430 libarchive-zip-perl (1.30-3) unstable; urgency=low [ gregor herrmann ] * Remove Ben Burton from Uploaders on request of the MIA team (closes: #577665). [ Salvatore Bonaccorso ] * Convert to '3.0 (quilt)' package source format. Drop quilt framework for packaging. * Refresh debian/copyright file. * debian/control: Re-oder the Build-Depends-Indep control file field. * Bump Standards-Version to 3.9.0 (no changes needed). * Add fix-spelling-error.patch patch to fix a small spelling error reported by lintian. -- Salvatore Bonaccorso Mon, 05 Jul 2010 10:25:32 +0200 libarchive-zip-perl (1.30-2) unstable; urgency=low * Add patch bumping required Perl minimum version in META.yml. Some tests for libarchive-zip-perl require 5.006, and the tests fail with newer libperl-minimumversion-perl (>= 1.22). Thanks to Lucas Nussbaum reporting the FTBFS (Closes: #560632). * Add myself to Uploaders. * debian/copyright: Update to the current revision of the DEP5 machine readable format-specification proposal. -- Salvatore Bonaccorso Sun, 13 Dec 2009 10:08:11 +0100 libarchive-zip-perl (1.30-1) unstable; urgency=low * New upstream release (Closes: 548963). * debian/control: Added: Vcs-Svn field (source stanza); Vcs-Browser field (source stanza); Homepage field (source stanza); ${misc:Depends} to Depends: field. Changed: Maintainer set to Debian Perl Group (was: Ben Burton ); Ben Burton moved to Uploaders. Updated Standards-Version. Added myself in Uploaders. Added quilt to Build-Depends: field. * debian/watch: use dist-based URL. * debian/rules: delete /usr/lib/perl5 only if it exists. * Added versioned dependencies on libcompress-raw-zlib-perl. * Remove unneeded dependencies on libfile-which-perl. * Added quilt patch to fix shebangs on example scripts (Closes: 543659). -- Ernesto Hernández-Novich (USB) Thu, 01 Oct 2009 10:46:15 -0430 libarchive-zip-perl (1.18-2) unstable; urgency=low * Take over for the Debian Perl Group on maintainer's request (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=548963#10) -- Ernesto Hernández-Novich (USB) Tue, 29 Sep 2009 19:22:49 -0430 libarchive-zip-perl (1.18-1) unstable; urgency=low * New upstream release. * Added build-depends on libfile-which-perl, which is now used in the test suite. * Removed Appnote.txt and appnote.iz from the source tarball, since these appear to be non-free. * Switched from debhelper compatibility level 3 to 5. Moved debhelper dependency to Build-Depends (not Build-Depends-Indep) to support the clean target (thanks lintian). * Bumped standards-version to 3.7.2.2 (no changes required). -- Ben Burton Sun, 20 May 2007 09:04:44 +1000 libarchive-zip-perl (1.16-1) unstable; urgency=low * New upstream release (closes: #329494). * Run the test suite during the package build. This requires an extra build-depends on libcompress-zlib-perl. * Bumped standards-version to 3.6.2.1 (no changes required). -- Ben Burton Wed, 5 Oct 2005 19:08:56 +1000 libarchive-zip-perl (1.14-2) unstable; urgency=low * Adopted by Ben Burton (closes: #314850). Thanks to Ivo Timmermans and Matthias Klose for all their work on this package. * Clarified the copyright file by explicitly including the Perl license terms. * Changed double hyphen to a single hyphen in Tree.pm to avoid bad formatting in POD manpage (closes: #303022). * Added a manpage for /usr/bin/crc32. -- Ben Burton Mon, 20 Jun 2005 09:21:56 +1000 libarchive-zip-perl (1.14-1) unstable; urgency=high * New upstream version. - Fixes: Archive::Zip is fooled by manipulated ZIP directory Closes: #277773. -- Matthias Klose Sat, 30 Oct 2004 22:19:15 +0200 libarchive-zip-perl (1.13-2) unstable; urgency=low * Add watch file. -- Matthias Klose Sun, 19 Sep 2004 19:44:59 +0200 libarchive-zip-perl (1.13-1) unstable; urgency=high * NMU (needed as a dependency for mailscanner). -- Matthias Klose Sat, 28 Aug 2004 19:37:13 +0200 libarchive-zip-perl (1.12-0.1) unstable; urgency=low * NMU (needed as a dependency for mailscanner). Closes: #258198. -- Matthias Klose Fri, 9 Jul 2004 07:48:06 +0200 libarchive-zip-perl (1.10-0.1) unstable; urgency=low * NMU (needed as a dependency for mailscanner). * New upstream version (closes: #235788). - Better handling of broken archives (closes: #218932). -- Matthias Klose Mon, 28 Jun 2004 18:31:23 +0200 libarchive-zip-perl (1.05-1) unstable; urgency=low * New upstream release. (Closes: #192051) * debian/control: - Update Standards-Version; - Set Section to perl. -- Ivo Timmermans Mon, 5 May 2003 23:54:26 +0200 libarchive-zip-perl (1.01-1) unstable; urgency=low * New upstream release. (Closes: #145273) * Renamed Build-Depends to Build-Depends-Indep. -- Ivo Timmermans Sun, 19 May 2002 00:39:23 +0200 libarchive-zip-perl (0.11-1) unstable; urgency=low * Initial Release. (Closes: #99768) -- Ivo Timmermans Mon, 18 Jun 2001 14:36:39 +0200 debian/t/0000775000000000000000000000000012156112500007424 5ustar debian/t/data/0000775000000000000000000000000012156112500010335 5ustar debian/t/data/jar.zip0000664000000000000000000000065312156112500011641 0ustar PKr*@ META-INF/PKPKr*@META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMu (h)f&W+x%irrPKo9GGPK r*@tg/PKr*@ META-INF/PKr*@o9GG=META-INF/MANIFEST.MFPK r*@tg/PKt/data/dotdot-from-unexistant-path.zip0000664000000000000000000000036513316713463015251 0ustar PKNLD:unexisting/../../../../../tmp/gotcha-dotdot-unexistingpathgotcha: .. with unexisting pathPKNLD:unexisting/../../../../../tmp/gotcha-dotdot-unexistingpathPKhwt/data/link-dir.zip0000664000000000000000000000040413316713501011355 0ustar PKYL.Ļ link-dir/tmpPKYLW.link-dir/gotcha-linkdirgotcha via dir link PKYL.Ļ link-dirPKYLW.*link-dir/gotcha-linkdirPK{st/data/link-samename.zip0000664000000000000000000000040113316713523012366 0ustar PKYLv link-file/tmp/gotcha-samenamePKYLk link-filegotcha via same-named link PKYLv link-filePKYLk ;link-filePKn}