Skip to content

Commit 0127179

Browse files
committed
Media: Improve verification of MIME file types.
Merges [43988] to the 4.5 branch. git-svn-id: https://develop.svn.wordpress.org/branches/4.5@43993 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 35f2f3a commit 0127179

2 files changed

Lines changed: 71 additions & 6 deletions

File tree

src/wp-includes/functions.php

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,14 +2324,59 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
23242324
$type = $ext = false;
23252325
}
23262326
}
2327-
} elseif ( function_exists( 'finfo_file' ) ) {
2328-
// Use finfo_file if available to validate non-image files.
2327+
}
2328+
2329+
// Validate files that didn't get validated during previous checks.
2330+
if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
23292331
$finfo = finfo_open( FILEINFO_MIME_TYPE );
23302332
$real_mime = finfo_file( $finfo, $file );
23312333
finfo_close( $finfo );
23322334

2333-
// If the extension does not match the file's real type, return false.
2334-
if ( $real_mime !== $type ) {
2335+
// fileinfo often misidentifies obscure files as one of these types
2336+
$nonspecific_types = array(
2337+
'application/octet-stream',
2338+
'application/encrypted',
2339+
'application/CDFV2-encrypted',
2340+
'application/zip',
2341+
);
2342+
2343+
/*
2344+
* If $real_mime doesn't match the content type we're expecting from the file's extension,
2345+
* we need to do some additional vetting. Media types and those listed in $nonspecific_types are
2346+
* allowed some leeway, but anything else must exactly match the real content type.
2347+
*/
2348+
if ( in_array( $real_mime, $nonspecific_types, true ) ) {
2349+
// File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
2350+
if ( !in_array( substr( $type, 0, strcspn( $type, '/' ) ), array( 'application', 'video', 'audio' ) ) ) {
2351+
$type = $ext = false;
2352+
}
2353+
} elseif ( 0 === strpos( $real_mime, 'video/' ) || 0 === strpos( $real_mime, 'audio/' ) ) {
2354+
/*
2355+
* For these types, only the major type must match the real value.
2356+
* This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
2357+
* and some media files are commonly named with the wrong extension (.mov instead of .mp4)
2358+
*/
2359+
2360+
if ( substr( $real_mime, 0, strcspn( $real_mime, '/' ) ) !== substr( $type, 0, strcspn( $type, '/' ) ) ) {
2361+
$type = $ext = false;
2362+
}
2363+
} else {
2364+
if ( $type !== $real_mime ) {
2365+
/*
2366+
* Everything else including image/* and application/*:
2367+
* If the real content type doesn't match the file extension, assume it's dangerous.
2368+
*/
2369+
$type = $ext = false;
2370+
}
2371+
2372+
}
2373+
}
2374+
2375+
// The mime type must be allowed
2376+
if ( $type ) {
2377+
$allowed = get_allowed_mime_types();
2378+
2379+
if ( ! in_array( $type, $allowed ) ) {
23352380
$type = $ext = false;
23362381
}
23372382
}

tests/phpunit/tests/functions.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,12 +461,12 @@ function data_device_can_upload() {
461461
'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25',
462462
true,
463463
),
464-
// Android 2.2, Android Webkit Browser
464+
// Android 2.2, Android Webkit Browser
465465
array(
466466
'Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4',
467467
true,
468468
),
469-
// BlackBerry 9900, BlackBerry browser
469+
// BlackBerry 9900, BlackBerry browser
470470
array(
471471
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+',
472472
true,
@@ -481,6 +481,26 @@ function data_device_can_upload() {
481481
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0',
482482
true,
483483
),
484+
// Non-image file not allowed even if it's named like one.
485+
array(
486+
DIR_TESTDATA . '/export/crazy-cdata.xml',
487+
'crazy-cdata.jpg',
488+
array(
489+
'ext' => false,
490+
'type' => false,
491+
'proper_filename' => false,
492+
),
493+
),
494+
// Non-image file not allowed if it's named like something else.
495+
array(
496+
DIR_TESTDATA . '/export/crazy-cdata.xml',
497+
'crazy-cdata.doc',
498+
array(
499+
'ext' => false,
500+
'type' => false,
501+
'proper_filename' => false,
502+
),
503+
),
484504
);
485505
}
486506

0 commit comments

Comments
 (0)