[wp-trac] [WordPress Trac] #21251: Media uploads ignore FS_CHMOD_FILE

WordPress Trac wp-trac at lists.automattic.com
Fri Jul 13 03:19:41 UTC 2012


#21251: Media uploads ignore FS_CHMOD_FILE
--------------------------+------------------------------
 Reporter:  mikewolf53    |       Owner:
     Type:  defect (bug)  |      Status:  new
 Priority:  normal        |   Milestone:  Awaiting Review
Component:  Upload        |     Version:  3.4.1
 Severity:  normal        |  Resolution:
 Keywords:                |
--------------------------+------------------------------
Changes (by dd32):

 * component:  Media => Upload


Old description:

> = To Reproduce: =
>
> 1.  Have Apache configured such that secure permissions are as follows:
> * 0710 directories
> * 0600 PHP files
> * 0640 All other files (anything that must be read by Apache rather than
> PHP)
>
> 2.  Set permissions on all files and directories as described above.
>
> 3.  Set the following in your wp-config.php
> {{{
> define('FS_CHMOD_DIR', (0710 & ~ umask()));
> define('FS_CHMOD_FILE', (0640 & ~ umask()));
> }}}
>
> 4.  Upload a file using your media library.
>
> 5.  Notice that the uploaded file has permissions of 0600 instead of 640.
>
> = Expected Result =
> Files uploaded should obey the FS_CHMOD_FILE directive, and the uploaded
> file should have permissions of 0640.
>
> = Actual Result =
> Wikipedia sets permissions of the file by taking its parent directory's
> permissions and stripping the executable bits, leaving the file
> unreadable to Apache.  The result is 0600.
>
> = Relevant Info =
>
> These files (and likely more) ignore FS_CHMOD_FILE when uploading files
> to the server:
>
> /wp-includes/functions.php
> {{{
>         // Set correct file permissions
>         $stat = @ stat( dirname( $new_file ) );
>         $perms = $stat['mode'] & 0007777;
>         $perms = $perms & 0000666;
>         @ chmod( $new_file, $perms );
> }}}
>
> /wp-includes/media.php
> {{{
>         // Set correct file permissions
>         $stat = stat( dirname( $destfilename ));
>         $perms = $stat['mode'] & 0000666; //same permissions as parent
> folder, strip off the executable bits
>         @ chmod( $destfilename, $perms );
> }}}
>

> /wp-admin/includes/file.php
> {{{
>         // Set correct file permissions
>         $stat = stat( dirname( $new_file ));
>         $perms = $stat['mode'] & 0000666;
>         @ chmod( $new_file, $perms );
> }}}
>
> This is problematic in the case where suEXEC+fcgid or suPHP are being
> used and Apache has group ownership on files/directories.  In this case,
> the secure permissions would be:
> * 0710 directories
> * 0600 PHP files
> * 0640 All other files (anything that must be read by Apache rather than
> PHP)
>
> The code in each of the files above causes files to be uploaded with
> permissions of 600, which is unreadable by Apache.

New description:

 = To Reproduce: =

 1.  Have Apache configured such that secure permissions are as follows:
 * 0710 directories
 * 0600 PHP files
 * 0640 All other files (anything that must be read by Apache rather than
 PHP)

 2.  Set permissions on all files and directories as described above.

 3.  Set the following in your wp-config.php
 {{{
 define('FS_CHMOD_DIR', (0710 & ~ umask()));
 define('FS_CHMOD_FILE', (0640 & ~ umask()));
 }}}

 4.  Upload a file using your media library.

 5.  Notice that the uploaded file has permissions of 0600 instead of 640.

 = Expected Result =
 Files uploaded should obey the FS_CHMOD_FILE directive, and the uploaded
 file should have permissions of 0640.

 = Actual Result =
 !WordPress sets permissions of the file by taking its parent directory's
 permissions and stripping the executable bits, leaving the file unreadable
 to Apache.  The result is 0600.

 = Relevant Info =

 These files (and likely more) ignore FS_CHMOD_FILE when uploading files to
 the server:

 /wp-includes/functions.php
 {{{
         // Set correct file permissions
         $stat = @ stat( dirname( $new_file ) );
         $perms = $stat['mode'] & 0007777;
         $perms = $perms & 0000666;
         @ chmod( $new_file, $perms );
 }}}

 /wp-includes/media.php
 {{{
         // Set correct file permissions
         $stat = stat( dirname( $destfilename ));
         $perms = $stat['mode'] & 0000666; //same permissions as parent
 folder, strip off the executable bits
         @ chmod( $destfilename, $perms );
 }}}


 /wp-admin/includes/file.php
 {{{
         // Set correct file permissions
         $stat = stat( dirname( $new_file ));
         $perms = $stat['mode'] & 0000666;
         @ chmod( $new_file, $perms );
 }}}

 This is problematic in the case where suEXEC+fcgid or suPHP are being used
 and Apache has group ownership on files/directories.  In this case, the
 secure permissions would be:
 * 0710 directories
 * 0600 PHP files
 * 0640 All other files (anything that must be read by Apache rather than
 PHP)

 The code in each of the files above causes files to be uploaded with
 permissions of 600, which is unreadable by Apache.

--

Comment:

 The `FS_CHMOD_FILE` and `FS_CHMOD_DIR` constants are specifically used by
 the `WP_Filesystem` classes,  and may not always compare directly to what
 the files should be set to when written directly to disk (as they're
 designed with the FTP subsystem in mind, something the Uploads do not
 utilise at all) - As a result, using these same constants for file uploads
 could cause more harm than good.

 For example, Files are set to 644 by default, this would be correct when
 uploaded via FTP (as WP_Filesystem) will be doing, however, when written
 to disk by apache running in an insecure mode (u/g apache/apache for
 example) requires the folder to be 777, and as a result, files as 666).
 I'm not saying it's not wrong to have a secure server, simply showing why
 re-using of those constants is not in the best interest.

 > 0710 directories
 It seems to me, that setting this to 0750 would result in !WordPress
 uploads working correctly (purely as a point of reference for a working
 configuration), and is the scenario that one would expect to find the
 directories configured for (Apache can Read the folder list, as well as
 change into the directory).

 for the less informed on the results of a 710:
 {{{
 7 - Owner - Read/Write/List folder contents/change into
 1 - Groups - Change into (But not list files)
 0 - Everyone - No access
 }}}

 Setting directories to 710 seems overkill to me, although, one which can
 be seen as a "highly secure" (in other words, highly limiting) permission
 level, I would argue that it should be Apache who should be configured to
 not allow directory listings in this case.

 Also, for what it's worth: I'm sure there are filters in the upload
 process which can be used to change the permissions of the created files,
 although, I don't know them off the top of my head (I'd check CDN plugins
 if you can't spot it in the code)

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/21251#comment:1>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list