Advertisement:

Author Topic: Only allow specific mime types for attachments  (Read 1828 times)

Offline GL700Wing

  • Full Member
  • ***
  • Posts: 552
  • Gender: Female
Only allow specific mime types for attachments
« on: November 03, 2020, 03:28:25 AM »
Although it is possible to configure and check for specific attachment file extensions (eg, jpg, jpeg, pdf, png) the file content/mime type is not checked and as a result any file type can be attached by simply changing the file extension to match one of the allowed extensions.

With a new forum I am setting up there is a requirement to only allow files with specific content/mime types to be attached and I've done this by making the following code changes:

In ./Sources/ManageAttachments.php
Find:
Code: [Select]
array('check', 'attachmentRecodeLineEndings'),Add After:
Code: [Select]
array('check', 'attachmentCheckMimes'),
array('text', 'attachmentMimes', 40),


In ./Sources/Subs-Post.php
Find:
Code: [Select]
if (!in_array(strtolower(substr(strrchr($attachmentOptions['name'], '.'), 1)), $allowed))
$attachmentOptions['errors'][] = 'bad_extension';
}
Add After:
Code: [Select]
if (!empty($modSettings['attachmentCheckMimes']))
{
$allowed = explode(',', strtolower($modSettings['attachmentMimes']));
foreach ($allowed as $k => $dummy)
$allowed[$k] = trim($dummy);

if (!in_array(strtolower(substr(strrchr($attachmentOptions['file_type'], '/'), 1)), $allowed))
$attachmentOptions['errors'][] = 'bad_mime';
}


In ./Sources/Post.php
Find:
Code: [Select]
fatal_error($_FILES['attachment']['name'][$n] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
}
Add After
Code: [Select]
if (!empty($modSettings['attachmentCheckMimes']))
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['attachment']['tmp_name'][$n]);
finfo_close($finfo);

if (!in_array($mime, explode(',', strtolower($modSettings['attachmentMimes']))))
fatal_error('<strong>' . $_FILES['attachment']['name'][$n] . '</strong><br /><br />' . sprintf($txt['cant_upload_mime'], $mime) . '</strong>' . $modSettings['attachmentMimes'] . '</strong>', false);
}
Find:
Code: [Select]
fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
}
Add After:
Code: [Select]
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['attachment']['tmp_name'][$n]);
finfo_close($finfo);

Find:
Code: [Select]
'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'),Add After:
Code: [Select]
'file_type' => $mime,
Find:
Code: [Select]
fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
}
Add After:
Code: [Select]
if (in_array('bad_mime', $attachmentOptions['errors']))
{
checkSubmitOnce('free');
fatal_error('<strong>' . $attachmentOptions['name'] . '</strong><br /><br />' . sprintf($txt['cant_upload_mime'], $attachmentOptions['file_type']) . '</strong>' . $modSettings['attachmentMimes'] . '</strong>', false);
}


In ./Themes/default/languages/Post.english.php
Find:
Code: [Select]
$txt['cant_upload_type'] = 'You cannot upload that type of file. The only allowed extensions are';Add After:
Code: [Select]
$txt['cant_upload_mime'] = 'You cannot upload that type of file (ie, "%1$s"). The only allowed file content/mime types are: ';

In ./Themes/default/languages/Admin.english.php
Find:
Code: [Select]
$txt['attachmentRecodeLineEndings'] = 'Recode line endings in textual attachments';Add After:
Code: [Select]
$txt['attachmentCheckMimes'] = 'Check attachment\'s file content/mime type';
$txt['attachmentMimes'] = 'Allowed file content/mime types<div class="smalltext"/>Note: Enter <b>jpeg</b> for JPG and JPEG image files.</div>';
« Last Edit: November 03, 2020, 05:39:29 AM by GL700Wing »
Life doesn't have to be perfect to be wonderful ...

Offline Arantor

  • Resident Overthinker
  • SMF Friend
  • SMF Legend
  • *
  • Posts: 73,189
Re: Only allow specific mime types for attachments
« Reply #1 on: November 03, 2020, 02:26:24 PM »
Note this only works if you have the finfo extension installed.
No good deed goes unpunished
All helpful urges should be circumvented

Offline GL700Wing

  • Full Member
  • ***
  • Posts: 552
  • Gender: Female
Re: Only allow specific mime types for attachments
« Reply #2 on: November 03, 2020, 04:15:04 PM »
Note this only works if you have the finfo extension installed.
Thanks - I should have mentioned that.

Also, and in cPanel on my websites, the PHP extension name is shown as 'fileinfo' and it has been available since PHP 5.2 (and it is enabled by default).
Life doesn't have to be perfect to be wonderful ...

Offline Arantor

  • Resident Overthinker
  • SMF Friend
  • SMF Legend
  • *
  • Posts: 73,189
Re: Only allow specific mime types for attachments
« Reply #3 on: November 03, 2020, 04:25:10 PM »
A surprising number of hosts actually disable this. You'd think they wouldn't but in the same way the JSON encode/decode functions were part of core in 5.2+ and enabled by default, WordPress for years had to backtrack on relying on hosts having it because they just didn't. Some of the worst offenders offload even 'standard' extensions to keep their PHP binaries as lean and efficient as possible.

It's technically both fileinfo and finfo - as per https://www.php.net/manual/en/book.fileinfo.php - I just refer to it as finfo because I write everything using OOP where possible and that's the OOP class name (rather than fileinfo even if it is bundled and activated by ext/fileinfo under the hood)
No good deed goes unpunished
All helpful urges should be circumvented