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
This commit is contained in:
Jeremy Felt 2018-12-12 23:10:04 +00:00
parent 35f2f3acc0
commit 0127179f66
2 changed files with 71 additions and 6 deletions

View File

@ -2324,14 +2324,59 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
$type = $ext = false;
}
}
} elseif ( function_exists( 'finfo_file' ) ) {
// Use finfo_file if available to validate non-image files.
}
// Validate files that didn't get validated during previous checks.
if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
$finfo = finfo_open( FILEINFO_MIME_TYPE );
$real_mime = finfo_file( $finfo, $file );
finfo_close( $finfo );
// If the extension does not match the file's real type, return false.
if ( $real_mime !== $type ) {
// fileinfo often misidentifies obscure files as one of these types
$nonspecific_types = array(
'application/octet-stream',
'application/encrypted',
'application/CDFV2-encrypted',
'application/zip',
);
/*
* If $real_mime doesn't match the content type we're expecting from the file's extension,
* we need to do some additional vetting. Media types and those listed in $nonspecific_types are
* allowed some leeway, but anything else must exactly match the real content type.
*/
if ( in_array( $real_mime, $nonspecific_types, true ) ) {
// File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
if ( !in_array( substr( $type, 0, strcspn( $type, '/' ) ), array( 'application', 'video', 'audio' ) ) ) {
$type = $ext = false;
}
} elseif ( 0 === strpos( $real_mime, 'video/' ) || 0 === strpos( $real_mime, 'audio/' ) ) {
/*
* For these types, only the major type must match the real value.
* This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
* and some media files are commonly named with the wrong extension (.mov instead of .mp4)
*/
if ( substr( $real_mime, 0, strcspn( $real_mime, '/' ) ) !== substr( $type, 0, strcspn( $type, '/' ) ) ) {
$type = $ext = false;
}
} else {
if ( $type !== $real_mime ) {
/*
* Everything else including image/* and application/*:
* If the real content type doesn't match the file extension, assume it's dangerous.
*/
$type = $ext = false;
}
}
}
// The mime type must be allowed
if ( $type ) {
$allowed = get_allowed_mime_types();
if ( ! in_array( $type, $allowed ) ) {
$type = $ext = false;
}
}

View File

@ -461,12 +461,12 @@ class Tests_Functions extends WP_UnitTestCase {
'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',
true,
),
// Android 2.2, Android Webkit Browser
// Android 2.2, Android Webkit Browser
array(
'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',
true,
),
// BlackBerry 9900, BlackBerry browser
// BlackBerry 9900, BlackBerry browser
array(
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+',
true,
@ -481,6 +481,26 @@ class Tests_Functions extends WP_UnitTestCase {
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:41.0) Gecko/20100101 Firefox/41.0',
true,
),
// Non-image file not allowed even if it's named like one.
array(
DIR_TESTDATA . '/export/crazy-cdata.xml',
'crazy-cdata.jpg',
array(
'ext' => false,
'type' => false,
'proper_filename' => false,
),
),
// Non-image file not allowed if it's named like something else.
array(
DIR_TESTDATA . '/export/crazy-cdata.xml',
'crazy-cdata.doc',
array(
'ext' => false,
'type' => false,
'proper_filename' => false,
),
),
);
}