Skip to content

Commit ff58a69

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

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

src/wp-includes/functions.php

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,17 +2341,52 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
23412341
$real_mime = finfo_file( $finfo, $file );
23422342
finfo_close( $finfo );
23432343

2344+
// fileinfo often misidentifies obscure files as one of these types
2345+
$nonspecific_types = array(
2346+
'application/octet-stream',
2347+
'application/encrypted',
2348+
'application/CDFV2-encrypted',
2349+
'application/zip',
2350+
);
2351+
23442352
/*
2345-
* If $real_mime doesn't match what we're expecting, we need to do some extra
2346-
* vetting of application mime types to make sure this type of file is allowed.
2347-
* Other mime types are assumed to be safe, but should be considered unverified.
2353+
* If $real_mime doesn't match the content type we're expecting from the file's extension,
2354+
* we need to do some additional vetting. Media types and those listed in $nonspecific_types are
2355+
* allowed some leeway, but anything else must exactly match the real content type.
23482356
*/
2349-
if ( $real_mime && ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) {
2350-
$allowed = get_allowed_mime_types();
2357+
if ( in_array( $real_mime, $nonspecific_types, true ) ) {
2358+
// File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
2359+
if ( !in_array( substr( $type, 0, strcspn( $type, '/' ) ), array( 'application', 'video', 'audio' ) ) ) {
2360+
$type = $ext = false;
2361+
}
2362+
} elseif ( 0 === strpos( $real_mime, 'video/' ) || 0 === strpos( $real_mime, 'audio/' ) ) {
2363+
/*
2364+
* For these types, only the major type must match the real value.
2365+
* This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
2366+
* and some media files are commonly named with the wrong extension (.mov instead of .mp4)
2367+
*/
23512368

2352-
if ( ! in_array( $real_mime, $allowed ) ) {
2369+
if ( substr( $real_mime, 0, strcspn( $real_mime, '/' ) ) !== substr( $type, 0, strcspn( $type, '/' ) ) ) {
2370+
$type = $ext = false;
2371+
}
2372+
} else {
2373+
if ( $type !== $real_mime ) {
2374+
/*
2375+
* Everything else including image/* and application/*:
2376+
* If the real content type doesn't match the file extension, assume it's dangerous.
2377+
*/
23532378
$type = $ext = false;
23542379
}
2380+
2381+
}
2382+
}
2383+
2384+
// The mime type must be allowed
2385+
if ( $type ) {
2386+
$allowed = get_allowed_mime_types();
2387+
2388+
if ( ! in_array( $type, $allowed ) ) {
2389+
$type = $ext = false;
23552390
}
23562391
}
23572392

tests/phpunit/tests/functions.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,8 +1115,8 @@ public function _wp_check_filetype_and_ext_data() {
11151115
DIR_TESTDATA . '/formatting/big5.txt',
11161116
'big5.jpg',
11171117
array(
1118-
'ext' => 'jpg',
1119-
'type' => 'image/jpeg',
1118+
'ext' => false,
1119+
'type' => false,
11201120
'proper_filename' => false,
11211121
),
11221122
),
@@ -1130,6 +1130,26 @@ public function _wp_check_filetype_and_ext_data() {
11301130
'proper_filename' => false,
11311131
),
11321132
),
1133+
// Non-image file not allowed even if it's named like one.
1134+
array(
1135+
DIR_TESTDATA . '/export/crazy-cdata.xml',
1136+
'crazy-cdata.jpg',
1137+
array(
1138+
'ext' => false,
1139+
'type' => false,
1140+
'proper_filename' => false,
1141+
),
1142+
),
1143+
// Non-image file not allowed if it's named like something else.
1144+
array(
1145+
DIR_TESTDATA . '/export/crazy-cdata.xml',
1146+
'crazy-cdata.doc',
1147+
array(
1148+
'ext' => false,
1149+
'type' => false,
1150+
'proper_filename' => false,
1151+
),
1152+
),
11331153
);
11341154

11351155
// Test a few additional file types on single sites.

0 commit comments

Comments
 (0)