WordPress.org

Make WordPress Core

Changeset 44007 for branches/4.1


Ignore:
Timestamp:
12/12/2018 11:39:10 PM (2 years ago)
Author:
jeremyfelt
Message:

Media: Improve verification of MIME file types.

Merges [43988] to the 4.1 branch.

Location:
branches/4.1
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/4.1

  • branches/4.1/src/wp-includes/functions.php

    r43401 r44007  
    21562156            }
    21572157        }
    2158     } elseif ( function_exists( 'finfo_file' ) ) {
    2159         // Use finfo_file if available to validate non-image files.
     2158    }
     2159
     2160    // Validate files that didn't get validated during previous checks.
     2161    if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
    21602162        $finfo = finfo_open( FILEINFO_MIME_TYPE );
    21612163        $real_mime = finfo_file( $finfo, $file );
    21622164        finfo_close( $finfo );
    21632165
    2164         // If the extension does not match the file's real type, return false.
    2165         if ( $real_mime !== $type ) {
     2166        // fileinfo often misidentifies obscure files as one of these types
     2167        $nonspecific_types = array(
     2168            'application/octet-stream',
     2169            'application/encrypted',
     2170            'application/CDFV2-encrypted',
     2171            'application/zip',
     2172        );
     2173
     2174        /*
     2175         * If $real_mime doesn't match the content type we're expecting from the file's extension,
     2176         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
     2177         * allowed some leeway, but anything else must exactly match the real content type.
     2178         */
     2179        if ( in_array( $real_mime, $nonspecific_types, true ) ) {
     2180            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
     2181            if ( !in_array( substr( $type, 0, strcspn( $type, '/' ) ), array( 'application', 'video', 'audio' ) ) ) {
     2182                $type = $ext = false;
     2183            }
     2184        } elseif ( 0 === strpos( $real_mime, 'video/' ) || 0 === strpos( $real_mime, 'audio/' ) ) {
     2185            /*
     2186             * For these types, only the major type must match the real value.
     2187             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
     2188             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
     2189             */
     2190
     2191            if ( substr( $real_mime, 0, strcspn( $real_mime, '/' ) ) !== substr( $type, 0, strcspn( $type, '/' ) ) ) {
     2192                $type = $ext = false;
     2193            }
     2194        } else {
     2195            if ( $type !== $real_mime ) {
     2196                /*
     2197                 * Everything else including image/* and application/*:
     2198                 * If the real content type doesn't match the file extension, assume it's dangerous.
     2199                 */
     2200                $type = $ext = false;
     2201            }
     2202
     2203        }
     2204    }
     2205
     2206    // The mime type must be allowed
     2207    if ( $type ) {
     2208        $allowed = get_allowed_mime_types();
     2209
     2210        if ( ! in_array( $type, $allowed ) ) {
    21662211            $type = $ext = false;
    21672212        }
Note: See TracChangeset for help on using the changeset viewer.