Simple Machines Community Forum

Customizing SMF => Tips and Tricks => Topic started by: GL700Wing on November 03, 2020, 03:28:25 AM

Title: Only allow specific mime types for attachments
Post by: GL700Wing 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>';
Title: Re: Only allow specific mime types for attachments
Post by: Arantor on November 03, 2020, 02:26:24 PM
Note this only works if you have the finfo extension installed.
Title: Re: Only allow specific mime types for attachments
Post by: GL700Wing 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).
Title: Re: Only allow specific mime types for attachments
Post by: Arantor 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)