From 4729ff0812c1f3d06d98524e2fec232d3bf90513 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 28 Jul 2016 09:50:09 +0100 Subject: [PATCH] Exclude working directory from library path (CVE-2016-1238) Current Perl versions put '.' at the end of the library search path @INC, although this will be fixed in a future Perl release. This means that when software loads an optionally-present module, it will be looked for in the current working directory before giving up. An attacker could use this to execute arbitrary Perl code from ikiwiki's current working directory. Removing '.' from the library search path in Perl is the correct fix for this vulnerability, but is not trivial to do due to backwards-compatibility concerns. Mitigate this (even if ikiwiki is run with a vulnerable Perl version) by explicitly removing '.' from the search path, and instead looking for ikiwiki's own modules relative to the absolute path of the executable when run from the source directory. In tests that specifically want to use the current working directory, use "-I".getcwd instead of "-I." so we use its absolute path, which is immune to the removal of ".". --- ikiwiki-calendar.in | 3 ++- ikiwiki-comment.in | 3 ++- ikiwiki-mass-rebuild | 1 + ikiwiki-transition.in | 3 ++- ikiwiki-update-wikilist | 1 + ikiwiki.in | 3 ++- pm_filter | 2 +- t/basewiki_brokenlinks.t | 5 +++-- t/comments.t | 5 +++-- t/conflicts.t | 5 +++-- t/img.t | 5 +++-- t/inline.t | 5 +++-- t/meta.t | 5 +++-- t/permalink.t | 5 +++-- t/podcast.t | 4 ++-- t/relativity.t | 4 ++-- t/trail.t | 5 +++-- t/wrapper-environ.t | 5 +++-- 18 files changed, 42 insertions(+), 27 deletions(-) diff --git a/ikiwiki-calendar.in b/ikiwiki-calendar.in index 74e100be2..d3e31b6db 100755 --- a/ikiwiki-calendar.in +++ b/ikiwiki-calendar.in @@ -1,7 +1,8 @@ #!/usr/bin/perl +no lib '.'; use warnings; use strict; -use lib '.'; # For use in nonstandard directory, munged by Makefile. +use FindBin; use lib $FindBin::Bin; # For use in nonstandard directory, munged by Makefile. use IkiWiki; use IkiWiki::Setup; use Getopt::Long; diff --git a/ikiwiki-comment.in b/ikiwiki-comment.in index 1c7baead0..174647b06 100755 --- a/ikiwiki-comment.in +++ b/ikiwiki-comment.in @@ -1,7 +1,8 @@ #!/usr/bin/perl +no lib '.'; use warnings; use strict; -use lib '.'; # For use in nonstandard directory, munged by Makefile. +use FindBin; use lib $FindBin::Bin; # For use in nonstandard directory, munged by Makefile. use IkiWiki; use IkiWiki::Plugin::comments; use Getopt::Long; diff --git a/ikiwiki-mass-rebuild b/ikiwiki-mass-rebuild index 06a9b512b..ce4e084e8 100755 --- a/ikiwiki-mass-rebuild +++ b/ikiwiki-mass-rebuild @@ -1,4 +1,5 @@ #!/usr/bin/perl +no lib '.'; use warnings; use strict; diff --git a/ikiwiki-transition.in b/ikiwiki-transition.in index e3be645cc..3b617bbfa 100755 --- a/ikiwiki-transition.in +++ b/ikiwiki-transition.in @@ -1,7 +1,8 @@ #!/usr/bin/perl +no lib '.'; use warnings; use strict; -use lib '.'; # For use in nonstandard directory, munged by Makefile. +use FindBin; use lib $FindBin::Bin; # For use in nonstandard directory, munged by Makefile. use IkiWiki; use HTML::Entities; diff --git a/ikiwiki-update-wikilist b/ikiwiki-update-wikilist index 56d6e0731..2807e6be6 100755 --- a/ikiwiki-update-wikilist +++ b/ikiwiki-update-wikilist @@ -1,6 +1,7 @@ #!/usr/bin/perl -t # Add a user to the system wide wikilist. # This script can safely be made suid or put in /etc/sudoers. +no lib '.'; use warnings; use strict; use English; diff --git a/ikiwiki.in b/ikiwiki.in index 1327d70e1..30df628b2 100755 --- a/ikiwiki.in +++ b/ikiwiki.in @@ -1,9 +1,10 @@ #!/usr/bin/perl package IkiWiki; +no lib '.'; use warnings; use strict; -use lib '.'; # For use in nonstandard directory, munged by Makefile. +use FindBin; use lib $FindBin::Bin; # For use in nonstandard directory, munged by Makefile. use IkiWiki 3.00; sub usage () { diff --git a/pm_filter b/pm_filter index 8e1480564..374e9a44f 100755 --- a/pm_filter +++ b/pm_filter @@ -12,7 +12,7 @@ if (/INSTALLDIR_AUTOREPLACE/) { elsif (/VERSION_AUTOREPLACE/) { $_=qq{our \$version="$ver";}; } -elsif (/^use lib/) { +elsif (/^(?:use FindBin; *)?use lib/) { # The idea here is to figure out if the libdir the Makefile.PL # was configured to use is in perl's normal search path. # If not, hard code it into ikiwiki. diff --git a/t/basewiki_brokenlinks.t b/t/basewiki_brokenlinks.t index 26e3859ab..f639d0dd8 100755 --- a/t/basewiki_brokenlinks.t +++ b/t/basewiki_brokenlinks.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; my $installed = $ENV{INSTALLED_TESTS}; @@ -14,10 +15,10 @@ if ($installed) { else { ok(! system("make -s ikiwiki.out")); ok(! system("make underlay_install DESTDIR=`pwd`/t/tmp/install PREFIX=/usr >/dev/null")); - @command = qw(env LC_ALL=C perl -I. ./ikiwiki.out + @command = (qw(env LC_ALL=C perl), "-I".getcwd, qw(./ikiwiki.out --underlaydir=t/tmp/install/usr/share/ikiwiki/basewiki --set underlaydirbase=t/tmp/install/usr/share/ikiwiki - --templatedir=templates); + --templatedir=templates)); } foreach my $plugin ("", "listdirectives") { diff --git a/t/comments.t b/t/comments.t index a5add9701..f2e32c46e 100755 --- a/t/comments.t +++ b/t/comments.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; use IkiWiki; @@ -17,10 +18,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } my $comment; diff --git a/t/conflicts.t b/t/conflicts.t index 07c392cd3..2c2761efb 100755 --- a/t/conflicts.t +++ b/t/conflicts.t @@ -2,6 +2,7 @@ # Tests for bugs relating to conflicting files in the srcdir use warnings; use strict; +use Cwd qw(getcwd); use Test::More tests => 106; my $installed = $ENV{INSTALLED_TESTS}; @@ -13,10 +14,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } # setup diff --git a/t/img.t b/t/img.t index 05a91aff6..228f09a0e 100755 --- a/t/img.t +++ b/t/img.t @@ -13,6 +13,7 @@ package IkiWiki; use warnings; use strict; +use Cwd qw(getcwd); use Test::More; plan(skip_all => "Image::Magick not available") unless eval q{use Image::Magick; 1}; @@ -27,10 +28,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } push @command, qw(--set usedirs=0 --plugin img t/tmp/in t/tmp/out --verbose); diff --git a/t/inline.t b/t/inline.t index 8c0f1c35a..3a4450365 100755 --- a/t/inline.t +++ b/t/inline.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; use IkiWiki; @@ -12,10 +13,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } push @command, qw(--set usedirs=0 --plugin inline diff --git a/t/meta.t b/t/meta.t index d23d9bc71..3b26ee7d2 100755 --- a/t/meta.t +++ b/t/meta.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; use IkiWiki; @@ -16,10 +17,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } push @command, qw(--plugin meta --disable-plugin htmlscrubber); diff --git a/t/permalink.t b/t/permalink.t index edb05a81b..2eb557e1d 100755 --- a/t/permalink.t +++ b/t/permalink.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; my $installed = $ENV{INSTALLED_TESTS}; @@ -11,10 +12,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } ok(! system("rm -rf t/tmp")); diff --git a/t/podcast.t b/t/podcast.t index c698d1835..708ac7640 100755 --- a/t/podcast.t +++ b/t/podcast.t @@ -25,10 +25,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @base_command = qw(perl -I. ./ikiwiki.out + @base_command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } my $tmp = 't/tmp'; diff --git a/t/relativity.t b/t/relativity.t index c67c8ba17..7e382eaa7 100755 --- a/t/relativity.t +++ b/t/relativity.t @@ -24,10 +24,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } sub parse_cgi_content { diff --git a/t/trail.t b/t/trail.t index cac64c366..ed180d35c 100755 --- a/t/trail.t +++ b/t/trail.t @@ -1,6 +1,7 @@ #!/usr/bin/perl use warnings; use strict; +use Cwd qw(getcwd); use Test::More; use IkiWiki; @@ -35,10 +36,10 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(perl -I. ./ikiwiki.out + @command = ("perl", "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } push @command, qw(--set usedirs=0 --plugin trail --plugin inline diff --git a/t/wrapper-environ.t b/t/wrapper-environ.t index ddf5a6e44..d6d34b9d9 100755 --- a/t/wrapper-environ.t +++ b/t/wrapper-environ.t @@ -22,10 +22,11 @@ if ($installed) { } else { ok(! system("make -s ikiwiki.out")); - @command = qw(env PERL5LIB=t/tmp:blib/lib:blib/arch perl -I. ./ikiwiki.out + @command = (qw(env PERL5LIB=t/tmp:blib/lib:blib/arch perl), + "-I".getcwd, qw(./ikiwiki.out --underlaydir=underlays/basewiki --set underlaydirbase=underlays - --templatedir=templates); + --templatedir=templates)); } writefile("test.setup", "t/tmp", <