From cf4344d9e031d2e0bf70b8d8f75ab27ecf8d29ad Mon Sep 17 00:00:00 2001 From: David Mehren Date: Sun, 27 Dec 2020 11:31:01 +0100 Subject: Improve MIME-type checks of uploaded files This commit adds a check if the MIME-type of the uploaded file (detected using the magic bytes) matches the file extension. Signed-off-by: David Mehren --- lib/web/imageRouter/index.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/web/imageRouter/index.js b/lib/web/imageRouter/index.js index b6ace4a6..5861a2bc 100644 --- a/lib/web/imageRouter/index.js +++ b/lib/web/imageRouter/index.js @@ -2,6 +2,8 @@ const Router = require('express').Router const formidable = require('formidable') +const path = require('path') +const FileType = require('file-type') const config = require('../../config') const logger = require('../../logger') @@ -9,6 +11,23 @@ const errors = require('../../errors') const imageRouter = module.exports = Router() +async function checkUploadType (filePath) { + const typeFromMagic = await FileType.fromFile(filePath) + if (typeFromMagic === undefined) { + logger.error(`Image upload error: Could not determine MIME-type`) + return false + } + if (path.extname(filePath) !== '.' + typeFromMagic.ext) { + logger.error(`Image upload error: Provided file extension does not match MIME-type`) + return false + } + if (!config.allowedUploadMimeTypes.includes(typeFromMagic.mime)) { + logger.error(`Image upload error: MIME-type "${typeFromMagic.mime}" of uploaded file not allowed, only "${config.allowedUploadMimeTypes.join(', ')}" are allowed`) + return false + } + return true +} + // upload image imageRouter.post('/uploadimage', function (req, res) { var form = new formidable.IncomingForm() @@ -19,18 +38,17 @@ imageRouter.post('/uploadimage', function (req, res) { form.uploadDir = config.uploadsPath } - form.parse(req, function (err, fields, files) { + form.parse(req, async function (err, fields, files) { if (err) { logger.error(`Image upload error: formidable error: ${err}`) return errors.errorForbidden(res) - } else if (!req.isAuthenticated() && !config.allowAnonymous && !config.allowAnonymousEdits) { + } else if (!req.isAuthenticated() && !config.allowAnonymous && !config.allowAnonymousEdits) { logger.error(`Image upload error: Anonymous edits and therefore uploads are not allowed)`) return errors.errorForbidden(res) } else if (!files.image || !files.image.path) { logger.error(`Image upload error: Upload didn't contain file)`) return errors.errorBadRequest(res) - } else if (!config.allowedUploadMimeTypes.includes(files.image.type)) { - logger.error(`Image upload error: MIME-type "${files.image.type}" of uploaded file not allowed, only "${config.allowedUploadMimeTypes.join(', ')}" are allowed)`) + } else if (!await checkUploadType(files.image.path)) { return errors.errorBadRequest(res) } else { logger.debug(`SERVER received uploadimage: ${JSON.stringify(files.image)}`) -- cgit v1.2.3