Bug 1355695 - (CVE-2016-1238) CVE-2016-1238 perl: loading of modules from current directory
CVE-2016-1238 perl: loading of modules from current directory
Status: CLOSED WONTFIX
Product: Security Response
Classification: Other
Component: vulnerability (Show other bugs)
unspecified
All Linux
medium Severity medium
: ---
: ---
Assigned To: Red Hat Product Security
impact=moderate,public=20160725,repor...
: Security
Depends On: 1411436 1360425
Blocks: 1354390 1355696
  Show dependency treegraph
 
Reported: 2016-07-12 05:37 EDT by Martin Prpič
Modified: 2017-08-02 13:25 EDT (History)
19 users (show)

See Also:
Fixed In Version: perl 5.22.3, perl 5.24.1
Doc Type: If docs needed, set a value
Doc Text:
It was found that perl can load modules from the current directory if not found in the module directories, via the @INC path. A local, authenticated attacker could create a specially crafted module in a writable directory and trick a user into running a perl program from that directory; if the module is not found in previous @INC paths, it will load and execute the attacker's module.
Story Points: ---
Clone Of:
Environment:
Last Closed: 2017-08-02 10:55:34 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
CVE-2016-1238 maint-5.22-dot-in-inc.patch (130.37 KB, text/plain)
2016-07-12 05:38 EDT, Martin Prpič
no flags Details
CVE-2016-1238 maint-5.24-dot-in-inc.patch (132.74 KB, text/plain)
2016-07-12 05:38 EDT, Martin Prpič
no flags Details
CVE-2016-1238 maint-5.22-dot-in-inc.patch v2 (132.60 KB, text/plain)
2016-07-22 03:28 EDT, Martin Prpič
no flags Details
CVE-2016-1238 maint-5.24-dot-in-inc.patch v2 (138.33 KB, text/plain)
2016-07-22 03:29 EDT, Martin Prpič
no flags Details

  None (edit)
Description Martin Prpič 2016-07-12 05:37:10 EDT
The following issue was reported by Perl upstream:

The problem relates to Perl 5 ("perl") loading modules from the includes directory array ("@INC") in which the last element is the current directory ("."). That means that, when "perl" wants to load a module (during first compilation or during lazy loading of a module in run-time), perl will look for the module in the current directory at the end, since '.' is the last include directory in its array of include directories to seek. The issue is with requiring libraries that are in "." but are not otherwise installed.

The major problem with this behavior is that it unexpectedly puts a user at risk whenever they execute any Perl scripts from a directory that is writable by other accounts on the system. For instance, if a user is logged in as root and changes directory into /tmp or an account's home directory, it is possible to now run any shell commands that are written in C, Python or Ruby without fear.

The same isn't true for any shell commands that are written in Perl, since a significant proportion of Perl scripts will execute code in the current working directory whenever they are run. For example, if a user on a shared system creates the file /tmp/Pod/Perldoc/Toterm.pm, and then I log in as root, change directory to /tmp, and run "perldoc perlrun", it will execute the code they have placed in the file.

The most severe example discovered on Debian is that apt-get will load and execute the /tmp/Log/Agent.pm file regardless of the directory it is started from since it automatically changes directory to /tmp.

This is present in perl versions 5.24 and below. We will be making additional maintenance releases of 5.24, 5.22 (current supported versions), and (as an exception, probably) 5.20 (which is no longer officially supported) which will include the fix for it.

The fix, supplied in the attached patches, is to check if the last entry of @INC is "." and if so, to remove it as an included path.
Comment 1 Martin Prpič 2016-07-12 05:38 EDT
Created attachment 1178819 [details]
CVE-2016-1238 maint-5.22-dot-in-inc.patch
Comment 2 Martin Prpič 2016-07-12 05:38 EDT
Created attachment 1178820 [details]
CVE-2016-1238 maint-5.24-dot-in-inc.patch
Comment 3 Martin Prpič 2016-07-12 05:44:59 EDT
Acknowledgments:

Name: the Perl project
Upstream: John Lightsey (cPanel Security Team), Todd Rinaldo (cPanel Security Team)
Comment 4 Martin Prpič 2016-07-22 03:28 EDT
Created attachment 1182725 [details]
CVE-2016-1238 maint-5.22-dot-in-inc.patch v2
Comment 5 Martin Prpič 2016-07-22 03:29 EDT
Created attachment 1182726 [details]
CVE-2016-1238 maint-5.24-dot-in-inc.patch v2
Comment 6 Tomas Hoger 2016-07-26 09:00:53 EDT
Upstream bug report, which remains private for now:

https://rt.perl.org/Public/Bug/Display.html?id=127834

However, the issue is already public via other places including:

http://www.gossamer-threads.com/lists/perl/porters/329911
https://www.debian.org/security/2016/dsa-3628
Comment 7 Tomas Hoger 2016-07-26 13:14:52 EDT
Created perl tracking bugs for this issue:

Affects: fedora-all [bug 1360425]
Comment 8 Petr Pisar 2016-07-27 02:32:17 EDT
Please note that the fix does not fix the real cause -- having "." in Perl module search path list (@INC variable). It only patches every module bundled with upstream Perl (i.e. core modules) that loads another module which is deemed not to be delivered within upstream Perl (i.e. non-core modules).

That is instead of not having "." in the default interpreter @INC array (see last lines of "perl -V" output), it changes some modules that do something like this:

eval "require $module";

in this manner:

+    local @INC = @INC;
+    pop @INC if $INC[-1] eq '.';
     eval "require $module";

That has these consequences:

(1) It does not fix any of the thousands of modules distributed from CPAN or another upstream. And many of them are delivered by Fedora.

(2) Applying the patches to perl package in Fedora will keep vulnerable Fedora packages that supersede some Perl core modules (i.e. dual-lived modules). E.g. Locale::Maketext module is delivered from perl-Locale-Maketext source package in Fedora. Not from perl source package. That means cloning this vulnerability to perl component is not enough. It should be cloned to perl-Locale-Maketext too. And probably to tens of other Fedora components.

(3) It's possible that even plain "require Foo::Bar;" code not in the eval argument possess the vulnerability in Fedora. Even if Foo::Bar were core module. That's because Foo::Bar module can be delivered by a binary package that is not required when installing package that does the "require Foo::Bar;". Either on purpose or as a packaging bug. While I consider this case as improbable (upstream worked very hard on the patches, Fedora tries to specify all dependencies between packages), I cannot exclude it.

Fedora maintainers will deliver the upstream patches as part of new perl versions 5.22.3 and 5.24.1 in the beginning of August. Fedora maintainers will patch the dual-lived modules independently.

Due to nature of this bug, Fedora maintainers are pondering removing the "." path from the default @INC globally on the perl interpreter level. At least in F26 and probably F25. And adding the "." to the specific few modules that depends on it (inc::latest, inc::Module::Install).
Comment 9 Tomas Hoger 2016-07-27 03:59:07 EDT
(In reply to Petr Pisar from comment #8)
> Please note that the fix does not fix the real cause -- having "." in Perl
> module search path list (@INC variable). It only patches every module
> bundled with upstream Perl (i.e. core modules) that loads another module
> which is deemed not to be delivered within upstream Perl (i.e. non-core
> modules).

That is correct.  The thing is that "." has been in @INC for way too long, and hence it's relied on, and its removal will cause breakage.  The info we got indicates that upstream may proceed with removing it in the future versions, but it's quite a big change for minor release.  Hence this partial and more complicated fix to address recently-discovered cases where this issue has significant impact.
Comment 10 Chris Travers 2016-07-30 14:11:28 EDT
I think this frankly a bad fix for the wrong problem.  Removing the . may cause problems but doing it at the module level is likely to have very serious side effects.  I am of the view that merely compiling a module should not have side effects.  A patch suggested in most places (i.e Peter's patch above minus the dynamic scoping) adds very strange order-dependent bugs to programs.  At least insisting that @INC should be localized bfore the modification helps.   But changing inc just because a module was compiled strikes me as very, very bad practice and in fact I have been bitten by the order-dependent implications of the Debian approach to this "fix" already.

The problem is not that a Perl module might include stuff from the wrong directories.  The problem is that a perl *script* might.  So I think the security concern here is rather badly scoped.  This is NOT a module vulnerability unless modules are *adding* . to the INC directory.

The right way, I think, to see this problem is that a program might not be written to address the implications of the INC directory.  So if the concern is that if someone has a nightly run of prove running as root in their /tmp directory then the correct solution is to add to bin/prove:

no lib '.';

That fixes the problem nicely and far more completely than the proposed fix here does and it does so without side effects.  Keeping the fix limited to scripts rather than libraries ensures that exploits are prevented and that breakage is not a real problem.  Insisting that one fixes it by removing the current directory from any possible position in @INC also means it cannot be carelessly added back in by using the -I. flag.

So the proposed fix is rather overinclusive (and needlessly breaking) and underinclusive (in no way eliminating the vulnerabilities).
Comment 11 Chris Travers 2016-07-30 14:41:16 EDT
I will give you a good example of the problem of making this the module's responsibility:  use base

Now without this sort of change, you do:

use base 'MyNamespace::Submodule';

And away you go.

With this sort of change, suddenly that breaks unless you do:

use MyNamespace::Submodule;
use base 'MyNamespace::Submodule';

Now you will note this ends up almost exactly equivalent except that the import() routine is run (more opportunity for malicious code if that is what you are worried about).  So you haven't eliminated vulnerabilities.  You have only increased annoyance.

So, really, this is best seen as a script vulnerability, not a module one.  Keep concerns cleanly separated and everyone wins.
Comment 12 Chris Travers 2016-07-31 00:05:50 EDT
As a note, I put together a blog post which includes an exploit of this sort, how administrators can secure their systems and some general guidelines for Perl module developers.  It also discusses a serious bug Debian included with their effort to fix this problem as well as recommendations for what Red Hat and others can do to help mitigate this problem.

http://ledgersmbdev.blogspot.se/2016/07/notes-on-security-separation-of.html

The best option for a resolution from Red Hat would be clear guidelines on Perl module development, an auditing of existing bin/ scripts to add no lib '.' where apropriate, and an option for sysadmins to be able to remove the '.' from @INC globally on a per system basis.

But making the contents of INC the module's responsibility is a very bad idea and a system that cannot be readily understood cannot be readily secured.
Comment 13 Adam Mariš 2016-08-01 04:43:57 EDT
In original patch, a version was renamed to an incorrect one in a single core module distribution in perl (PathTools, carrying Path::Spec)

Fixing commit:

http://perl5.git.perl.org/perl.git/commitdiff/b13c68bf
Comment 14 Fedora Update System 2016-08-04 16:52:21 EDT
perl-5.22.2-362.fc24 has been pushed to the Fedora 24 stable repository. If problems still persist, please make note of it in this bug report.
Comment 15 Fedora Update System 2016-08-19 18:21:20 EDT
perl-5.22.2-354.fc23 has been pushed to the Fedora 23 stable repository. If problems still persist, please make note of it in this bug report.
Comment 21 Peter Ajamian 2016-09-01 17:33:01 EDT
I've worked out what I believe to be a mitigation for this:

Create the file CustomStartupCode.pm with the following content and place it somewhere in your @INC path (I placed it in /usr/lib/perl5/site_perl/5.8.8 for EL5):

package CustomStartupCode;
our $VERSION = 1.00;

BEGIN {
    # CVE-2016-1238 Mitigation
    pop @INC if $INC[-1] eq '.';
}

1;


... Add the following to /etc/profile:
PERL5OPT=-mCustomStartupCode
export PERL5OPT


Close any open shells, open a new one and issue: perl -le 'print "@INC"'
...the resulting list should no longer have the lone "." at the end.
Comment 22 Petr Pisar 2016-09-05 09:30:21 EDT
(In reply to Peter Ajamian from comment #21)
> I've worked out what I believe to be a mitigation for this:
> 
> Create the file CustomStartupCode.pm with the following content and place it
> somewhere in your @INC path (I placed it in /usr/lib/perl5/site_perl/5.8.8
> for EL5):
> 
Since RHEL-6, perl is compiled with -Dusesitecustomize option which provides /usr/local/share/perl5/sitecustomize.pl location for these system-wide initialization code. One can put the "pop @INC if $INC[-1] eq '.';" line there and then any perl invocation will execute it automatically on each Perl interpreter start-up. (One can selectively disable this feature by "-f" perl's run-time option.)

Because all the upstream patches so far fixed only core modules and even they contain controversial changes, like the "base" module lost its ability to load optional modules, I think the most conservative fix would be not to fix it at all and only document that those who feel the urge to change the behavior, they can add the line into the /usr/local/share/perl5/sitecustomize.pl file. Such change will provide complete fix for all Perl modules, including non-core or third-party modules.
Comment 23 Peter Ajamian 2016-09-05 09:36:53 EDT
(In reply to Petr Pisar from comment #22)
> Since RHEL-6, perl is compiled with -Dusesitecustomize option which provides
> /usr/local/share/perl5/sitecustomize.pl location for these system-wide
> initialization code.

Right, I only gave the above mitigation the way I did because it works in RHEL5.  Certainly it is simpler to just use sitecustomize.pl for RHEL6 and 7.
Comment 24 Petr Pisar 2017-03-24 05:41:52 EDT
Current upstream situation is this: Modules bundled with Perl are sanitized to remove the trailing '.' from @INC before loading optional modules. 'base' module was reverted to original state, i.e. it does not sanitize @INC at all. Next Perl release, 5.26.0, will not have the '.' in @INC.
Comment 25 nupur priya 2017-04-26 03:27:08 EDT
When will the rpm with the real fix be released?
Comment 26 Petr Pisar 2017-04-26 03:47:52 EDT
The real fix is not have "." in the default @INC array at all. As the removal constitutes a serious change in the behavior (e.g. it breaks 8 % of CPAN distributions <http://cpan.simcop2387.info/failed.html>), I do not believe it's reasonable to deliver this fix in a frame of already released products like RHEL-7. You can definitely count with the fix in RHEL-8 or rh-perl526 software collection.
Comment 27 Jeffery J Stone 2017-06-22 12:22:41 EDT
Just to confirm, a remediation will not be provided via a patch to the package and the vendor recommended remediation for RHEL5 using Perl5 is Comment 21?  Just to confirm as external auditors are asking.
Comment 28 Jeffery J Stone 2017-06-22 12:29:31 EDT
Apologies, we're RHEL6 so Comment #22 but same basic confirmation that a backport fix via the package won't be be provided based on the concerns expressed in Comment #26.
Comment 29 Cedric Buissart 2017-08-02 10:55:51 EDT
Mitigation:

The following examples will remove '.' from the module path :

RHEL6 and above :
Create a file /usr/local/share/perl5/sitecustomize.pl containing the line "pop @INC if $INC[-1] eq '.';"

RHEL5:
Create a perl module with the same code in a BEGIN block, and use the 'PERL5OPT=-m<module-name>' environment variable to load it before execution of a perl program.

Note You need to log in before you can comment on or make changes to this bug.