From ddca05a4de09f71af124b0871b487d05bb2bf2f1 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Fri, 31 Jan 2025 23:14:43 +0100 Subject: [PATCH] [mirotalksfu] - improve path traversal, update dep --- app/src/Server.js | 7 +++++-- app/src/Validator.js | 34 ++++++++++++++++++++++++++++++---- cloud/server.js | 32 +++++++++++++++++++++++++++++--- package.json | 4 ++-- public/js/Brand.js | 2 +- public/js/Common.js | 2 +- public/js/Room.js | 4 ++-- public/js/RoomClient.js | 2 +- tests/test-Validator.js | 36 +++++++++++++++++++++++++++++++++++- 9 files changed, 106 insertions(+), 17 deletions(-) diff --git a/app/src/Server.js b/app/src/Server.js index 4d7f3bc8..1372ac88 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -11,8 +11,8 @@ prod dependencies: { @mattermost/client : https://www.npmjs.com/package/@mattermost/client @sentry/node : https://www.npmjs.com/package/@sentry/node axios : https://www.npmjs.com/package/axios - compression : https://www.npmjs.com/package/compression colors : https://www.npmjs.com/package/colors + compression : https://www.npmjs.com/package/compression cors : https://www.npmjs.com/package/cors crypto-js : https://www.npmjs.com/package/crypto-js discord.js : https://www.npmjs.com/package/discord.js @@ -21,6 +21,7 @@ prod dependencies: { express-openid-connect : https://www.npmjs.com/package/express-openid-connect fluent-ffmpeg : https://www.npmjs.com/package/fluent-ffmpeg he : https://www.npmjs.com/package/he + helmet : https://www.npmjs.com/package/helmet httpolyglot : https://www.npmjs.com/package/httpolyglot js-yaml : https://www.npmjs.com/package/js-yaml jsdom : https://www.npmjs.com/package/jsdom @@ -28,8 +29,10 @@ prod dependencies: { mediasoup : https://www.npmjs.com/package/mediasoup mediasoup-client : https://www.npmjs.com/package/mediasoup-client ngrok : https://www.npmjs.com/package/ngrok + nodemailer : https://www.npmjs.com/package/nodemailer openai : https://www.npmjs.com/package/openai qs : https://www.npmjs.com/package/qs + sanitize-filename : https://www.npmjs.com/package/sanitize-filename socket.io : https://www.npmjs.com/package/socket.io swagger-ui-express : https://www.npmjs.com/package/swagger-ui-express uuid : https://www.npmjs.com/package/uuid @@ -55,7 +58,7 @@ dev dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.7.20 + * @version 1.7.21 * */ diff --git a/app/src/Validator.js b/app/src/Validator.js index b114d18f..075a07eb 100644 --- a/app/src/Validator.js +++ b/app/src/Validator.js @@ -1,9 +1,11 @@ 'use strict'; +const path = require('path'); + const checkXSS = require('./XSS.js'); function isValidRoomName(input) { - if (typeof input !== 'string') { + if (!input || typeof input !== 'string') { return false; } const room = checkXSS(input); @@ -11,18 +13,42 @@ function isValidRoomName(input) { } function isValidRecFileNameFormat(input) { - if (typeof input !== 'string') { + if (!input || typeof input !== 'string') { return false; } - if (!input.startsWith('Rec_') || !input.endsWith('.webm')) { + const validPattern = /^Rec_[a-zA-Z0-9_-]+\.webm$/; + if (!validPattern.test(input)) { return false; } return !hasPathTraversal(input); } function hasPathTraversal(input) { + if (!input || typeof input !== 'string') { + return false; + } + + let decodedInput = input; + try { + decodedInput = decodeURIComponent(input); + decodedInput = decodeURIComponent(decodedInput); + } catch (err) {} + const pathTraversalPattern = /(\.\.(\/|\\))+/; - return pathTraversalPattern.test(input); + const excessiveDotsPattern = /(\.{4,}\/+|\.{4,}\\+)/; + const complexTraversalPattern = /(\.{2,}(\/+|\\+))/; + + if (complexTraversalPattern.test(decodedInput)) { + return true; + } + + const normalizedPath = path.normalize(decodedInput); + + if (pathTraversalPattern.test(normalizedPath) || excessiveDotsPattern.test(normalizedPath)) { + return true; + } + + return false; } module.exports = { diff --git a/cloud/server.js b/cloud/server.js index c983643f..d0cba7aa 100644 --- a/cloud/server.js +++ b/cloud/server.js @@ -118,16 +118,42 @@ app.listen(port, () => { // Utils function isValidRecFileNameFormat(input) { - if (typeof input !== 'string') { + if (!input || typeof input !== 'string') { return false; } - if (!input.startsWith('Rec_') || !input.endsWith('.webm')) { + const validPattern = /^Rec_[a-zA-Z0-9_-]+\.webm$/; + if (!validPattern.test(input)) { return false; } return !hasPathTraversal(input); } function hasPathTraversal(input) { + if (!input || typeof input !== 'string') { + return false; + } + + let decodedInput = input; + try { + decodedInput = decodeURIComponent(input); + decodedInput = decodeURIComponent(decodedInput); + } catch (err) { + // Ignore any errors during decoding + } + const pathTraversalPattern = /(\.\.(\/|\\))+/; - return pathTraversalPattern.test(input); + const excessiveDotsPattern = /(\.{4,}\/+|\.{4,}\\+)/; + const complexTraversalPattern = /(\.{2,}(\/+|\\+))/; + + if (complexTraversalPattern.test(decodedInput)) { + return true; + } + + const normalizedPath = path.normalize(decodedInput); + + if (pathTraversalPattern.test(normalizedPath) || excessiveDotsPattern.test(normalizedPath)) { + return true; + } + + return false; } diff --git a/package.json b/package.json index 85700e93..53d7c2c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.7.20", + "version": "1.7.21", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { @@ -79,7 +79,7 @@ "mediasoup-client": "3.8.1", "ngrok": "^5.0.0-beta.2", "nodemailer": "^6.10.0", - "openai": "^4.81.0", + "openai": "^4.82.0", "qs": "6.14.0", "sanitize-filename": "^1.6.3", "socket.io": "4.8.1", diff --git a/public/js/Brand.js b/public/js/Brand.js index ee2234fd..f7e9128f 100644 --- a/public/js/Brand.js +++ b/public/js/Brand.js @@ -64,7 +64,7 @@ let BRAND = { }, about: { imageUrl: '../images/mirotalk-logo.gif', - title: 'WebRTC SFU v1.7.20', + title: 'WebRTC SFU v1.7.21', html: `