From e80ff54ebc3a23f96a7df104ba45bfc05e43d712 Mon Sep 17 00:00:00 2001 From: davide-acanfora Date: Mon, 27 May 2024 19:18:02 +0200 Subject: [PATCH 1/4] Don't print release number to anyone who visits the service --- src/www/js/app.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/www/js/app.js b/src/www/js/app.js index 6b13a3b..6745f69 100644 --- a/src/www/js/app.js +++ b/src/www/js/app.js @@ -390,9 +390,6 @@ new Vue({ return releasesArray[0]; }); - console.log(`Current Release: ${currentRelease}`); - console.log(`Latest Release: ${latestRelease.version}`); - if (currentRelease >= latestRelease.version) return; this.currentRelease = currentRelease; From 859dd2f25b5b6f2cf737f54f41a8728ae607b110 Mon Sep 17 00:00:00 2001 From: davide-acanfora Date: Mon, 27 May 2024 19:22:09 +0200 Subject: [PATCH 2/4] Replace uuid module with built in crypto for UUIDv4 generation --- src/lib/WireGuard.js | 7 +++---- src/package-lock.json | 15 +-------------- src/package.json | 3 +-- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/lib/WireGuard.js b/src/lib/WireGuard.js index aa5d42a..8cdec7c 100644 --- a/src/lib/WireGuard.js +++ b/src/lib/WireGuard.js @@ -1,10 +1,9 @@ 'use strict'; -const fs = require('fs').promises; +const fs = require('node:fs/promises'); const path = require('path'); - const debug = require('debug')('WireGuard'); -const uuid = require('uuid'); +const crypto = require('node:crypto'); const QRCode = require('qrcode'); const Util = require('./Util'); @@ -248,7 +247,7 @@ Endpoint = ${WG_HOST}:${WG_PORT}`; } // Create Client - const id = uuid.v4(); + const id = crypto.randomUUID(); const client = { id, name, diff --git a/src/package-lock.json b/src/package-lock.json index 6db68a7..32fecae 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -13,8 +13,7 @@ "debug": "^4.3.4", "express-session": "^1.18.0", "h3": "^1.11.1", - "qrcode": "^1.5.3", - "uuid": "^9.0.1" + "qrcode": "^1.5.3" }, "devDependencies": { "eslint-config-athom": "^3.1.3", @@ -4626,18 +4625,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", diff --git a/src/package.json b/src/package.json index f63277e..ac53391 100644 --- a/src/package.json +++ b/src/package.json @@ -17,8 +17,7 @@ "debug": "^4.3.4", "express-session": "^1.18.0", "h3": "^1.11.1", - "qrcode": "^1.5.3", - "uuid": "^9.0.1" + "qrcode": "^1.5.3" }, "devDependencies": { "eslint-config-athom": "^3.1.3", From c26b536b65401e36bcd56b5526b78ece77fe2909 Mon Sep 17 00:00:00 2001 From: davide-acanfora Date: Mon, 27 May 2024 19:24:11 +0200 Subject: [PATCH 3/4] Remove unnecessary bcryptjs module usage --- src/lib/Server.js | 10 ---------- src/package-lock.json | 6 ------ src/package.json | 1 - 3 files changed, 17 deletions(-) diff --git a/src/lib/Server.js b/src/lib/Server.js index 529447d..69c603f 100644 --- a/src/lib/Server.js +++ b/src/lib/Server.js @@ -1,6 +1,5 @@ 'use strict'; -const bcrypt = require('bcryptjs'); const crypto = require('node:crypto'); const { createServer } = require('node:http'); const { stat, readFile } = require('node:fs/promises'); @@ -118,15 +117,6 @@ module.exports = class Server { return next(); } - if (req.url.startsWith('/api/') && req.headers['authorization']) { - if (bcrypt.compareSync(req.headers['authorization'], bcrypt.hashSync(PASSWORD, 10))) { - return next(); - } - return res.status(401).json({ - error: 'Incorrect Password', - }); - } - return res.status(401).json({ error: 'Not Logged In', }); diff --git a/src/package-lock.json b/src/package-lock.json index 32fecae..bdf0cd6 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -9,7 +9,6 @@ "version": "1.0.1", "license": "GPL", "dependencies": { - "bcryptjs": "^2.4.3", "debug": "^4.3.4", "express-session": "^1.18.0", "h3": "^1.11.1", @@ -909,11 +908,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", diff --git a/src/package.json b/src/package.json index ac53391..5183190 100644 --- a/src/package.json +++ b/src/package.json @@ -13,7 +13,6 @@ "author": "Emile Nijssen", "license": "GPL", "dependencies": { - "bcryptjs": "^2.4.3", "debug": "^4.3.4", "express-session": "^1.18.0", "h3": "^1.11.1", From d2d15fca2ad8bf2fa3009384bfeff6ca1a14f01c Mon Sep 17 00:00:00 2001 From: davide-acanfora Date: Mon, 27 May 2024 19:25:38 +0200 Subject: [PATCH 4/4] Path traversal vulnerability resolved --- src/lib/Server.js | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/lib/Server.js b/src/lib/Server.js index 69c603f..cd1f6d1 100644 --- a/src/lib/Server.js +++ b/src/lib/Server.js @@ -3,7 +3,7 @@ const crypto = require('node:crypto'); const { createServer } = require('node:http'); const { stat, readFile } = require('node:fs/promises'); -const { join } = require('node:path'); +const { resolve, sep } = require('node:path'); const expressSession = require('express-session'); const debug = require('debug')('Server'); @@ -202,15 +202,41 @@ module.exports = class Server { return { success: true }; })); + const safePathJoin = (base, target) => { + // Manage web root (edge case) + if (target === '/') { + return `${base}${sep}`; + } + + // Prepend './' to prevent absolute paths + const targetPath = `.${sep}${target}`; + + // Resolve the absolute path + const resolvedPath = resolve(base, targetPath); + + // Check if resolvedPath is a subpath of base + if (resolvedPath.startsWith(`${base}${sep}`)) { + return resolvedPath; + } + + throw createError({ + status: 400, + message: 'Bad Request', + }); + }; + // Static assets const publicDir = '/app/www'; app.use( defineEventHandler((event) => { return serveStatic(event, { - getContents: (id) => readFile(join(publicDir, id)), + getContents: (id) => { + return readFile(safePathJoin(publicDir, id)); + }, getMeta: async (id) => { - const stats = await stat(join(publicDir, id)).catch(() => {}); + const filePath = safePathJoin(publicDir, id); + const stats = await stat(filePath).catch(() => {}); if (!stats || !stats.isFile()) { return; }