Make WordPress Core

Opened 8 years ago

Closed 6 years ago

#37978 closed defect (bug) (wontfix)

Warning: posix_getpwuid() has been disabled for security reasons

Reported by: andydegroo's profile AndyDeGroo Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.6.1
Component: Filesystem API Keywords:
Focuses: Cc:

Description

Another one of those "great" "security reasons". I've noticed these warnings since upgrading to 4.6 but it might as well be caused by hosting provider adding posix_getpwuid to the disable_functions recently.

PHP Warning:  posix_getpwuid() has been disabled for security reasons in [...]/wp-admin/includes/class-wp-filesystem-direct.php on line 210

This seems to be happening during any update - plugins, themes or core. Latest block of warning messages starts at 07-Sep-2016 17:39:01 UTC when my site was auto-updating to 4.6.1.

I can confirm that posix_getpwuid is added to disable_functions but I'm puzzled by the function_exists('posix_getpwuid') two line prior not returning false.

PHP: 5.6.25 (FastCGI)

Change History (9)

#1 @AndyDeGroo
8 years ago

I create a test script to see if function_exists() really returns true for disabled funtions:

<?php
$disabled_functions = ini_get('disable_functions');

echo "disable_functions = $disabled_functions\n\n";

$disabled_functions = explode(",", $disabled_functions);

foreach( $disabled_functions as $function ) {
        $function = trim($function);
        printf( "function_exists('%s') => %s\n", $function, ( function_exists($function) ? 'true' : 'false' ) );
}

The results are even more confusing. Same host, same configuration but all checks return false:

disable_functions = exec, passthru, shell_exec, system, proc_open, popen, apache_child_terminate, apache_setenv, define_syslog_variables, pcntl_exec, openlog, posix_getpwuid, posix_kill, posix_setpgid, posix_setsid, posix_setuid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_open, proc_terminate, syslog

function_exists('exec') => false
function_exists('passthru') => false
function_exists('shell_exec') => false
function_exists('system') => false
function_exists('proc_open') => false
function_exists('popen') => false
function_exists('apache_child_terminate') => false
function_exists('apache_setenv') => false
function_exists('define_syslog_variables') => false
function_exists('pcntl_exec') => false
function_exists('openlog') => false
function_exists('posix_getpwuid') => false
function_exists('posix_kill') => false
function_exists('posix_setpgid') => false
function_exists('posix_setsid') => false
function_exists('posix_setuid') => false
function_exists('posix_setuid') => false
function_exists('posix_uname') => false
function_exists('proc_close') => false
function_exists('proc_get_status') => false
function_exists('proc_open') => false
function_exists('proc_terminate') => false
function_exists('syslog') => false

#2 follow-up: @dd32
8 years ago

@AndyDeGroo Can you check to see if your host is running some extra security/hardening extensions on PHP?

Via https://core.trac.wordpress.org/ticket/37680#comment:18 apparently you can use suhosin.executor.func.blacklist which disables the function in every way, except that function_exists() continues to incorrectly return true.
I wonder if maybe it correctly applies to is_callable()?
(Edit: After reading suhosin/issues/18 I believe function_exists() works correctly under suhosin now)

Last edited 8 years ago by dd32 (previous) (diff)

#3 in reply to: ↑ 2 @AndyDeGroo
8 years ago

Replying to dd32:

Can you check to see if your host is running some extra security/hardening extensions on PHP?

Via https://core.trac.wordpress.org/ticket/37680#comment:18 apparently you can use suhosin.executor.func.blacklist which disables the function in every way, except that function_exists() continues to incorrectly return true.

I had read #37680 and comments before creating this one. No, Suhosin is not present on this host. However, there is this line in phpinfo output:
ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured)
I'm no familiar with ionCube intrusion protection.

There is also Zend Guard Loader but that should not be interfering.

Loaded PHP extensions:

Core, date, ereg, libxml, openssl, pcre, sqlite3, zlib, bz2, calendar, ctype, curl, hash, filter, ftp, gettext, gmp, SPL, iconv, pcntl, readline, Reflection, session, standard, shmop, SimpleXML, mbstring, tokenizer, xml, cgi-fcgi, apcu, bcmath, dom, fileinfo, gd, imap, jsmin, json, exif, mcrypt, mysql, mysqli, mysqlnd, PDO, pdo_mysql, pdo_sqlite, Phar, posix, sockets, tidy, xmlreader, xmlwriter, xsl, zip, mhash, apc, ionCube Loader, Zend OPcache, Zend Guard Loader

I wonder if maybe it correctly applies to is_callable()?

Unfortunately, is_callable() returns true for all disabled functions.

I guess the only failsafe option is to check ini_get('disable_functions') like it is done in functions.php

<?php
strpos( ini_get( 'disable_functions' ), 'posix_getpwuid' )

#4 follow-up: @dd32
8 years ago

I'm not against a wp_function_exists() which wraps all that logic up.. as much as I hate having to.. something like..

function wp_function_exists( $func ) {
    static $disabled_funcs;
    if ( ! function_exists( $func ) ) {
        return false;
    }
    return $func NOT in statically-cached ini_get( 'disable_functions' );
}

#5 in reply to: ↑ 4 @AndyDeGroo
8 years ago

Replying to dd32:

I'm not against a wp_function_exists() which wraps all that logic up.. as much as I hate having to.. something like..

function wp_function_exists( $func ) {
    static $disabled_funcs;
    if ( ! function_exists( $func ) ) {
        return false;
    }
    return $func NOT in statically-cached ini_get( 'disable_functions' );
}

Caching the result makes sense because the code might be called repeatedly in during an update.

I see 4806 repeated error messages in PHP error log after updating Jetpack, all within 8 seconds.
There are 1021 files in Jetpack 4.3.1, which correlates with the number of error messages, if update process calls WP_Filesystem_Direct::owner() 4 times for each file and twice for a directory.

However, I can't understand why function_exists('posix_getpwuid') returns true in class-wp-filesystem-direct.php but false in my test.

#6 @SergeyBiryukov
8 years ago

  • Keywords needs-patch added

#7 follow-up: @desrosj
6 years ago

@AndyDeGroo are you interested in creating a patch for this?

@dd32 do you still feel this is worth tackling?

#8 in reply to: ↑ 7 @dd32
6 years ago

Replying to desrosj:

do you still feel this is worth tackling?

I'd like to think that disable_functions would stop being used by hosts, but it's probably going to stick around..

I see no harm in doing this, adding extra cover for the various functions hosts disable for some strange reason, etc

But I also see no rush in doing it (as evidenced by the age of these and similar tickets, and limited reports of running into disable_function warnings)

Personally I'd maybelater/wontfix it, encourage hosts to set display_errors to false for production sites unless debugging is enabled or something (although I believe most hosts would disagree, as otherwise customers would never see the errors)

#9 @johnbillion
6 years ago

  • Keywords needs-patch removed
  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed
Note: See TracTickets for help on using tickets.