diff --git a/Common/sources/constants.js b/Common/sources/constants.js index 92006390..c754e0e8 100644 --- a/Common/sources/constants.js +++ b/Common/sources/constants.js @@ -33,6 +33,8 @@ 'use strict'; exports.DOC_ID_PATTERN = '0-9-.a-zA-Z_='; +exports.DOC_ID_REGEX = new RegExp("^[" + exports.DOC_ID_PATTERN + "]*$", 'i'); +exports.EXTENTION_REGEX = /^[a-zA-Z0-9]*$/; exports.CHAR_DELIMITER = String.fromCharCode(5); exports.OUTPUT_NAME = 'output'; exports.ONLY_OFFICE_URL_PARAM = 'ooname'; diff --git a/Common/sources/utils.js b/Common/sources/utils.js index 6513c1d4..57483b5b 100644 --- a/Common/sources/utils.js +++ b/Common/sources/utils.js @@ -758,6 +758,17 @@ exports.forwarded = forwarded; exports.getIndexFromUserId = function(userId, userIdOriginal){ return parseInt(userId.substring(userIdOriginal.length)); }; +exports.checkPathTraversal = function(docId, rootDirectory, filename) { + if (filename.indexOf('\0') !== -1) { + logger.warn('checkPathTraversal Poison Null Bytes docId=%s filename=%s', docId, filename); + return false; + } + if (!filename.startsWith(rootDirectory)) { + logger.warn('checkPathTraversal Path Traversal docId=%s filename=%s', docId, filename); + return false; + } + return true; +}; exports.getConnectionInfo = function(conn){ var user = conn.user; var data = { diff --git a/DocService/sources/converterservice.js b/DocService/sources/converterservice.js index 8af82801..5111e227 100644 --- a/DocService/sources/converterservice.js +++ b/DocService/sources/converterservice.js @@ -187,9 +187,20 @@ function convertRequest(req, res, isJson) { utils.fillResponse(req, res, undefined, authRes.code, isJson); return; } + if (params.key && !constants.DOC_ID_REGEX.test(params.key)) { + logger.warn('convertRequest unexpected key = %s: docId = %s', params.key, docId); + utils.fillResponse(req, res, undefined, constants.CONVERT_PARAMS, isJson); + return; + } + if (params.filetype && !constants.EXTENTION_REGEX.test(params.filetype)) { + logger.warn('convertRequest unexpected filetype = %s: docId = %s', params.filetype, docId); + utils.fillResponse(req, res, undefined, constants.CONVERT_PARAMS, isJson); + return; + } let outputtype = params.outputtype || ''; let outputFormat = formatChecker.getFormatFromString(outputtype); if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === outputFormat) { + logger.warn('convertRequest unexpected outputtype = %s: docId = %s', outputtype, docId); utils.fillResponse(req, res, undefined, constants.CONVERT_PARAMS, isJson); return; } diff --git a/DocService/sources/server.js b/DocService/sources/server.js index a1ebb1b6..db085bb8 100644 --- a/DocService/sources/server.js +++ b/DocService/sources/server.js @@ -161,9 +161,8 @@ docsCoServer.install(server, () => { app.get('/FileUploader.ashx', utils.checkClientIp, rawFileParser, fileUploaderService.uploadTempFile); app.post('/FileUploader.ashx', utils.checkClientIp, rawFileParser, fileUploaderService.uploadTempFile); - const docIdRegExp = new RegExp("^[" + constants.DOC_ID_PATTERN + "]*$", 'i'); app.param('docid', (req, res, next, val) => { - if (docIdRegExp.test(val)) { + if (constants.DOC_ID_REGEX.test(val)) { next(); } else { res.sendStatus(403); diff --git a/FileConverter/sources/converter.js b/FileConverter/sources/converter.js index c723608a..67dc66c4 100644 --- a/FileConverter/sources/converter.js +++ b/FileConverter/sources/converter.js @@ -331,6 +331,9 @@ function* processDownloadFromStorage(dataConvert, cmd, task, tempDirs, authorPro dataConvert.fileFrom = path.join(tempDirs.source, 'Editor.bin'); needConcatFiles = true; } + if (!utils.checkPathTraversal(dataConvert.key, tempDirs.source, dataConvert.fileFrom)) { + return constants.CONVERT_PARAMS; + } //mail merge let mailMergeSend = cmd.getMailMergeSend(); if (mailMergeSend) { @@ -591,10 +594,14 @@ function* ExecuteTask(task) { let authorProps = {lastModifiedBy: null, modified: null}; if (cmd.getUrl()) { dataConvert.fileFrom = path.join(tempDirs.source, dataConvert.key + '.' + cmd.getFormat()); - error = yield* downloadFile(dataConvert.key, cmd.getUrl(), dataConvert.fileFrom, cmd.getWithAuthorization()); - if(clientStatsD) { - clientStatsD.timing('conv.downloadFile', new Date() - curDate); - curDate = new Date(); + if (utils.checkPathTraversal(dataConvert.key, tempDirs.source, dataConvert.fileFrom)) { + error = yield* downloadFile(dataConvert.key, cmd.getUrl(), dataConvert.fileFrom, cmd.getWithAuthorization()); + if(clientStatsD) { + clientStatsD.timing('conv.downloadFile', new Date() - curDate); + curDate = new Date(); + } + } else { + error = constants.CONVERT_PARAMS; } } else if (cmd.getSaveKey()) { yield* downloadFileFromStorage(cmd.getDocId(), cmd.getDocId(), tempDirs.source);