Bug#607479: libfcgi-perl: Serious FCGI information leak

Russ Allbery rra at debian.org
Thu Sep 8 03:24:00 UTC 2011


Package: libfcgi-perl
Version: 0.73-1
Followup-For: Bug #607479

This bug just caused a serious security incident for us, and I was able
to work through the cause and the reason why not everyone sees it.  The
problem was introduced in 0.70 and is still present in 0.73.

The following change was added in 0.70:

 sub accept() {
     warn "accept called as a method; you probably wanted to call Accept" if @_;
-    if (defined %FCGI::ENV) {
-       %ENV = %FCGI::ENV;
+    if (%FCGI::ENV) {
+        %ENV = %FCGI::ENV;
     } else {
-       %FCGI::ENV = %ENV;
+        %FCGI::ENV = %ENV;
     }
                
The goal of this code is to save the original environment the first time
into accept() and then restore the environment to the original environment
each time before calling accept() again.  It uses %FCGI::ENV to hold a
copy of the original environment.

The problem is the change to remove defined().  defined() on a hash
returned true if the hash had ever been set, so it could be used as a
sentinel to figure out whether the environment had already been saved.
However, this is deprecated in Perl, so the module was patched to just
check the truth value of the hash.

The problem is that the truth value of the hash is false if the hash has
never been set *or* if the hash has no members, which is not the same
as defined, which was returning true if the assignment from %ENV had
happened, even if it was empty.  So if the environment was completely
empty when accept() was first called, which is the case by default for
an Apache-spawned FCGI process (at least with mod_fastcgi), then the
environment in place the *second* time accept() is called will be saved as
the default environment.  This is the environment produced by the first
request to the server.

Then, later, accept() does:

     for (keys %FCGI::ENV) {
        $ENV{$_} = $FCGI::ENV{$_} unless exists $ENV{$_};
     }
          
so any keys in the environment that are not set in the new incoming
request will be copied over into the new request environment.

The practical effect of this is that any environment variable set in the
first pass through the code by the first processed request that isn't set
in some subsequent request will be added to that subsequent request.
Most notably, this includes the HTTP_COOKIE variable.  This can (and did
for us) constitute a serious security breach, since the HTTP_COOKIE header
may be carrying authentication credentials and the absence of that header
may indicate an unauthenticated access.  The practical effect is that
any unauthenticated user would receive the authentication credentials of
the first user processed after spawning the script.

Thankfully, there is a trivial workaround: set any environment variable
before the first call to accept(), and you will not see this bug.  So
any method of spawning FastCGI processes that doesn't clear the environment
will also not manifest this bug.

I can probably provide a patch in a day or two, but the fix is fairly
obvious: the code needs to stop using the truth value of %FCGI::ENV as
a proxy for whether this is the first or subsequent pass through
accept and instead set a separate scalar variable to true once the
initial environment has been saved into %FCGI::ENV.

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.39-2-686-pae (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages libfcgi-perl depends on:
ii  libc6                         2.13-16    Embedded GNU C Library: Shared lib
ii  perl                          5.12.4-4   Larry Wall's Practical Extraction 
ii  perl-base [perlapi-5.12.3]    5.12.4-4   minimal Perl system

libfcgi-perl recommends no packages.

libfcgi-perl suggests no packages.

-- no debconf information





More information about the pkg-perl-maintainers mailing list