forked from svrjs/svrjs
Add middleware that checks for forbidden paths. Also add some more placeholder config.json variables.
This commit is contained in:
parent
d688166022
commit
67fec5fe98
2 changed files with 115 additions and 1 deletions
|
@ -35,6 +35,7 @@ if (process.serverConfig.secure) {
|
|||
if (process.serverConfig.spubport === undefined) process.serverConfig.spubport = 443;
|
||||
if (process.serverConfig.sni === undefined) process.serverConfig.sni = {};
|
||||
if (process.serverConfig.enableOCSPStapling === undefined) process.serverConfig.enableOCSPStapling = false;
|
||||
|
||||
}
|
||||
if (process.serverConfig.port === undefined) process.serverConfig.port = 80;
|
||||
if (process.serverConfig.pubport === undefined) process.serverConfig.pubport = 80;
|
||||
|
@ -70,6 +71,8 @@ if (process.serverConfig.useWebRootServerSideScript === undefined) process.serve
|
|||
if (process.serverConfig.exposeModsInErrorPages === undefined) process.serverConfig.exposeModsInErrorPages = true;
|
||||
if (process.serverConfig.disableTrailingSlashRedirects === undefined) process.serverConfig.disableTrailingSlashRedirects = false;
|
||||
if (process.serverConfig.environmentVariables === undefined) process.serverConfig.environmentVariables = {};
|
||||
if (process.serverConfig.customHeadersVHost === undefined) process.serverConfig.customHeadersVHost = [];
|
||||
if (process.serverConfig.enableDirectoryListingVHost === undefined) process.serverConfig.enableDirectoryListingVHost = [];
|
||||
if (process.serverConfig.wwwrootPostfixesVHost === undefined) process.serverConfig.wwwrootPostfixesVHost = [];
|
||||
if (process.serverConfig.wwwrootPostfixPrefixesVHost === undefined) process.serverConfig.wwwrootPostfixPrefixesVHost = [];
|
||||
if (process.serverConfig.allowDoubleSlashes === undefined) process.serverConfig.allowDoubleSlashes = false;
|
||||
|
@ -111,7 +114,8 @@ let middleware = [
|
|||
// TODO: blocklist
|
||||
require("./middleware/webRootPostfixes.js"),
|
||||
require("./middleware/rewriteURL.js"),
|
||||
require("./middleware/responseHeaders.js")
|
||||
require("./middleware/responseHeaders.js"),
|
||||
require("./middleware/checkForbiddenPaths.js")
|
||||
];
|
||||
|
||||
function addMiddleware(mw) {
|
||||
|
|
110
src/middleware/checkForbiddenPaths.js
Normal file
110
src/middleware/checkForbiddenPaths.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
const os = require("os");
|
||||
const path = require("path");
|
||||
|
||||
// Function to get URL path for use in forbidden path adding.
|
||||
function getInitializePath(to) {
|
||||
var cwd = process.cwd();
|
||||
if (os.platform() == "win32") {
|
||||
to = to.replace(/\//g, "\\");
|
||||
if (to[0] == "\\") to = cwd.split("\\")[0] + to;
|
||||
}
|
||||
var absoluteTo = path.isAbsolute(to) ? to : (__dirname + (os.platform() == "win32" ? "\\" : "/") + to);
|
||||
if (os.platform() == "win32" && cwd[0] != absoluteTo[0]) return "";
|
||||
var relative = path.relative(cwd, absoluteTo);
|
||||
if (os.platform() == "win32") {
|
||||
return "/" + relative.replace(/\\/g, "/");
|
||||
} else {
|
||||
return "/" + relative;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if URL path name is a forbidden path.
|
||||
function isForbiddenPath(decodedHref, match) {
|
||||
var forbiddenPath = forbiddenPaths[match];
|
||||
if (!forbiddenPath) return false;
|
||||
if (typeof forbiddenPath === "string") {
|
||||
return decodedHref === forbiddenPath || (os.platform() === "win32" && decodedHref.toLowerCase() === forbiddenPath.toLowerCase());
|
||||
}
|
||||
if (typeof forbiddenPath === "object") {
|
||||
return forbiddenPath.some(function (forbiddenPathSingle) {
|
||||
return (decodedHref === forbiddenPathSingle || (os.platform() === "win32" && decodedHref.toLowerCase() === forbiddenPathSingle.toLowerCase()));
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to check if URL path name is index of one of defined forbidden paths.
|
||||
function isIndexOfForbiddenPath(decodedHref, match) {
|
||||
var forbiddenPath = forbiddenPaths[match];
|
||||
if (!forbiddenPath) return false;
|
||||
if (typeof forbiddenPath === "string") {
|
||||
return decodedHref === forbiddenPath || decodedHref.indexOf(forbiddenPath + "/") === 0 || (os.platform() === "win32" && (decodedHref.toLowerCase() === forbiddenPath.toLowerCase() || decodedHref.toLowerCase().indexOf(forbiddenPath.toLowerCase() + "/") === 0));
|
||||
}
|
||||
if (typeof forbiddenPath === "object") {
|
||||
return forbiddenPath.some(function (forbiddenPathSingle) {
|
||||
return (decodedHref === forbiddenPathSingle || decodedHref.indexOf(forbiddenPathSingle + "/") === 0 || (os.platform() === "win32" && (decodedHref.toLowerCase() === forbiddenPathSingle.toLowerCase() || decodedHref.toLowerCase().indexOf(forbiddenPathSingle.toLowerCase() + "/") === 0)));
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up forbidden paths
|
||||
var forbiddenPaths = {};
|
||||
|
||||
forbiddenPaths.config = getInitializePath("./config.json");
|
||||
forbiddenPaths.certificates = [];
|
||||
if (process.serverConfig.secure) {
|
||||
forbiddenPaths.certificates.push(getInitializePath(configJSON.cert));
|
||||
forbiddenPaths.certificates.push(getInitializePath(configJSON.key));
|
||||
Object.keys(sni).forEach(function (sniHostName) {
|
||||
forbiddenPaths.certificates.push(getInitializePath(sni[sniHostName].cert));
|
||||
forbiddenPaths.certificates.push(getInitializePath(sni[sniHostName].key));
|
||||
});
|
||||
}
|
||||
forbiddenPaths.svrjs = getInitializePath("./" + ((__dirname[__dirname.length - 1] != "/") ? __filename.replace(__dirname + "/", "") : __filename.replace(__dirname, "")));
|
||||
forbiddenPaths.serverSideScripts = [];
|
||||
if (process.serverConfig.useWebRootServerSideScript) {
|
||||
forbiddenPaths.serverSideScripts.push("/serverSideScript.js");
|
||||
} else {
|
||||
forbiddenPaths.serverSideScripts.push(getInitializePath("./serverSideScript.js"));
|
||||
}
|
||||
forbiddenPaths.serverSideScriptDirectories = [];
|
||||
forbiddenPaths.serverSideScriptDirectories.push(getInitializePath("./node_modules"));
|
||||
forbiddenPaths.serverSideScriptDirectories.push(getInitializePath("./mods"));
|
||||
forbiddenPaths.temp = getInitializePath("./temp");
|
||||
forbiddenPaths.log = getInitializePath("./log");
|
||||
|
||||
|
||||
module.exports = (req, res, logFacilities, config, next) => {
|
||||
let decodedHrefWithoutDuplicateSlashes = "";
|
||||
try {
|
||||
decodedHrefWithoutDuplicateSlashes = decodeURIComponent(req.parsedURL.pathname).replace(/\/+/g,"/");
|
||||
} catch (err) {
|
||||
res.error(400);
|
||||
}
|
||||
|
||||
// Check if path is forbidden
|
||||
if ((isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "config") || isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "certificates")) && !req.isProxy) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Access to configuration file/certificates is denied.");
|
||||
return;
|
||||
} else if (isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "temp") && !isProxy) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Access to temporary folder is denied.");
|
||||
return;
|
||||
} else if (isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "log") && !isProxy && (config.enableLogging || config.enableLogging == undefined) && !config.enableRemoteLogBrowsing) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Access to log files is denied.");
|
||||
return;
|
||||
} else if (isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "svrjs") && !isProxy && !exposeServerVersion) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Access to SVR.JS script is denied.");
|
||||
return;
|
||||
} else if ((isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "svrjs") || isForbiddenPath(decodedHrefWithoutDuplicateSlashes, "serverSideScripts") || isIndexOfForbiddenPath(decodedHrefWithoutDuplicateSlashes, "serverSideScriptDirectories")) && !isProxy && (config.disableServerSideScriptExpose || config.disableServerSideScriptExpose === undefined)) {
|
||||
res.error(403);
|
||||
logFacilities.errmessage("Access to sources is denied.");
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
Reference in a new issue