WordPress.org

Make WordPress Core

Ticket #15134: fix-symlinks.diff

File fix-symlinks.diff, 2.6 KB (added by Dreamsorcerer, 2 years ago)

Fix symlink security flaw

  • wp-admin/includes/class-wp-filesystem-direct.php

    old new  
    297297                        return false;
    298298                $file = str_replace( '\\', '/', $file ); // for win32, occasional problems deleting files otherwise
    299299
    300                 if ( 'f' == $type || $this->is_file($file) )
    301                         return @unlink($file);
     300                if ( 'f' == $type || $this->is_file($file) || $this->is_link($file) )
     301                        // rtrim() needed to remove symlinks successfully.
     302                        return @unlink(rtrim($file, '/'));
    302303                if ( ! $recursive && $this->is_dir($file) )
    303304                        return @rmdir($file);
    304305
     
    340341        /**
    341342         * @access public
    342343         *
     344         * @param string $file
     345         * @return bool
     346         */
     347        public function is_link($file) {
     348                // Strip trailing slashes, to avoid directory symlinks resolving.
     349                return @is_link(rtrim($file, '/'));
     350        }
     351        /**
     352         * @access public
     353         *
    343354         * @param string $path
    344355         * @return bool
    345356         */
     
    461472         * @return bool|array
    462473         */
    463474        public function dirlist($path, $include_hidden = true, $recursive = false) {
    464                 if ( $this->is_file($path) ) {
     475                if ( $this->is_dir($path) && $this->is_link($path) ) {
     476                        // Directory is symlink, therefore return no listing.
     477                        return array();
     478                } elseif ( $this->is_file($path) || $this->is_link($path) ) {
    465479                        $limit_file = basename($path);
    466480                        $path = dirname($path);
    467481                } else {
     
    501515                        $struc['time']          = date('h:i:s',$struc['lastmodunix']);
    502516                        $struc['type']          = $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
    503517
    504                         if ( 'd' == $struc['type'] ) {
     518                        if ( 'd' == $struc['type'] && !$this->is_link($path . '/' . $struc['name']) ) {
    505519                                if ( $recursive )
    506520                                        $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $include_hidden, $recursive);
    507521                                else
  • wp-admin/includes/class-wp-upgrader.php

    old new  
    377377
    378378                                // Attempt to alter permissions to allow writes and try again.
    379379                                $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' == $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) );
    380                                 if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
     380                                // is_writable() returns false on symlinks for some reason.
     381                                if ( ! $wp_filesystem->is_writable( $remote_destination . $filename )
     382                                         && ! $wp_filesystem->is_link( $remote_destination . $filename ) ) {
    381383                                        $unwritable_files[] = $filename;
    382384                                }
    383385                        }