ACCESS DENIED
Request from " + reqip + " is denied. The client is now in the blacklist.
SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" + (req.headers.host == undefined ? "" : " on " + String(req.headers.host).replace(/&/g, "&").replace(//g, ">")) + "
");
- serverconsole.errmessage("Client blocked");
+ // Scan the block list
+ if (blocklist.check(reqip)) {
+ // Invoke 403 Forbidden error
+ callServerError(403);
+ serverconsole.errmessage("Client is in the block list.");
return;
}
@@ -4116,7 +4102,7 @@ if (!cluster.isPrimary) {
// Respond with list of methods
var hdss = getCustomHeaders();
hdss["Allow"] = "GET, POST, HEAD, OPTIONS";
- res.writeHead(204, "No Content", hdss);
+ res.writeHead(204, http.STATUS_CODES[204], hdss);
res.end();
return;
} else {
@@ -4542,21 +4528,17 @@ if (!cluster.isPrimary) {
}
redirect(location, nonscode.scode == 302 || nonscode.scode == 307, nonscode.scode == 307 || nonscode.scode == 308);
return;
- } else if (nonscode.scode == 403) {
- callServerError(403);
- serverconsole.errmessage("Content blocked.");
- return;
- } else if (nonscode.scode == 410) {
- callServerError(410);
- serverconsole.errmessage("Content is gone.");
- return;
- } else if (nonscode.scode == 418) {
- callServerError(418);
- serverconsole.errmessage("SVR.JS is always a teapot ;)");
- return;
} else {
callServerError(nonscode.scode);
- serverconsole.errmessage("Client fails receiving content.");
+ if (nonscode.scode == 403) {
+ serverconsole.errmessage("Content blocked.");
+ } else if (nonscode.scode == 410) {
+ serverconsole.errmessage("Content is gone.");
+ } else if (nonscode.scode == 418) {
+ serverconsole.errmessage("SVR.JS is always a teapot ;)");
+ } else {
+ serverconsole.errmessage("Client fails receiving content.");
+ }
return;
}
}
@@ -4569,8 +4551,7 @@ if (!cluster.isPrimary) {
function checkIfPasswordMatches(list, password, callback, _i) {
if (!_i) _i = 0;
var cb = function (hash) {
- var matches = (hash == list[_i].pass);
- if (matches) {
+ if (hash == list[_i].pass) {
callback(true);
} else if (_i >= list.length - 1) {
callback(false);
@@ -4665,17 +4646,36 @@ if (!cluster.isPrimary) {
var username = decodedCredentialsMatch[1];
var password = decodedCredentialsMatch[2];
var usernameMatch = [];
+ var sha256Count = 0;
+ var pbkdf2Count = 0;
+ var scryptCount = 0;
if (!authcode.userList || authcode.userList.indexOf(username) > -1) {
usernameMatch = users.filter(function (entry) {
+ if(entry.scrypt) {
+ scryptCount++;
+ } else if(entry.pbkdf2) {
+ pbkdf2Count++;
+ } else {
+ sha256Count++;
+ }
return entry.name == username;
});
}
if (usernameMatch.length == 0) {
- usernameMatch.push({
+ // Pushing false user match to prevent time-based user enumeration
+ var fakeCredentials = {
name: username,
- pass: "FAKEPASS",
- salt: "FAKESALT"
- }); // Fake credentials
+ pass: "SVRJSAWebServerRunningOnNodeJS",
+ salt: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0"
+ };
+ if (!process.isBun) {
+ if (scryptCount > sha256Count && scryptCount > pbkdf2Count) {
+ fakeCredentials.scrypt = true;
+ } else if (pbkdf2Count > sha256Count) {
+ fakeCredentials.pbkdf2 = true;
+ }
+ }
+ usernameMatch.push(fakeCredentials);
}
checkIfPasswordMatches(usernameMatch, password, function (authorized) {
try {
@@ -5025,7 +5025,7 @@ function start(init) {
if (init) {
for (i = 0; i < logo.length; i++) console.log(logo[i]); // Print logo
console.log();
- console.log("Welcome to SVR.JS - a web server running on Node.JS");
+ console.log("Welcome to \x1b[1mSVR.JS - a web server running on Node.JS\x1b[0m");
// Print warnings
if (version.indexOf("Nightly-") === 0) serverconsole.locwarnmessage("This version is only for test purposes and may be unstable.");
@@ -5042,6 +5042,7 @@ function start(init) {
if (cluster.isPrimary === undefined) serverconsole.locwarnmessage("You're running SVR.JS on single thread. Reliability may suffer, as the server is stopped after crash.");
if (crypto.__disabled__ !== undefined) serverconsole.locwarnmessage("Your Node.JS version doesn't have crypto support! The 'crypto' module is essential for providing cryptographic functionality in Node.JS. Without crypto support, certain security features may be unavailable, and some functionality may not work as expected. It's recommended to use a Node.JS version that includes crypto support to ensure the security and proper functioning of your server.");
if (crypto.__disabled__ === undefined && !crypto.scrypt) serverconsole.locwarnmessage("Your JavaScript runtime doesn't have native scrypt support. HTTP authentication involving scrypt hashes will not work.");
+ if (!process.isBun && /^v(?:[0-9]\.|1[0-7]\.|18\.(?:[0-9]|1[0-8])\.|18\.19\.0|20\.(?:[0-9]|10)\.|20\.11\.0|21\.[0-5]\.|21\.6\.0|21\.6\.1(?![0-9]))/.test(process.version)) serverconsole.locwarnmessage("Your Node.JS version is vulnerable to HTTP server DoS (CVE-2024-22019).");
if (process.getuid && process.getuid() == 0) serverconsole.locwarnmessage("You're running SVR.JS as root. It's recommended to run SVR.JS as an non-root user. Running SVR.JS as root may increase the risks of OS command execution vulnerabilities.");
if (secure && process.versions && process.versions.openssl && process.versions.openssl.substr(0, 2) == "1.") {
if (new Date() > new Date("11 September 2023")) {
@@ -5240,11 +5241,11 @@ function start(init) {
else if (!cluster.isPrimary) process.send("Cannot block non-existent IP.");
} else {
for (var i = 0; i < ip.length; i++) {
- if (ip[i].indexOf(":") == -1) {
+ if (ip[i] != "localhost" && ip[i].indexOf(":") == -1) {
ip[i] = "::ffff:" + ip[i];
}
- if (!blacklist.check(ip[i])) {
- blacklist.add(ip[i]);
+ if (!blocklist.check(ip[i])) {
+ blocklist.add(ip[i]);
}
}
if (cluster.isPrimary === undefined) serverconsole.climessage("IPs successfully blocked.");
@@ -5260,7 +5261,7 @@ function start(init) {
if (ip[i].indexOf(":") == -1) {
ip[i] = "::ffff:" + ip[i];
}
- blacklist.remove(ip[i]);
+ blocklist.remove(ip[i]);
}
if (cluster.isPrimary === undefined) serverconsole.climessage("IPs successfully unblocked.");
else if (!cluster.isPrimary) process.send("IPs successfully unblocked.");
@@ -5437,7 +5438,7 @@ function start(init) {
} catch (err) {
// Nevermind... Don't want SVR.JS to fail starting, because os.freemem function is not working.
}
- if (cpus < 1) cpus = 1; // If SVR.JS is run on Haiku or if useAvailableCores = 0
+ if (cpus < 1) cpus = 1; // If SVR.JS is running on Haiku or if useAvailableCores = 0
for (var i = 0; i < cpus; i++) {
if (i == 0) {
SVRJSFork();
@@ -5759,7 +5760,7 @@ function saveConfig() {
delete configJSONobj.domian;
if (configJSONobj.page404 === undefined) configJSONobj.page404 = "404.html";
configJSONobj.timestamp = timestamp;
- configJSONobj.blacklist = blacklist.raw;
+ configJSONobj.blacklist = blocklist.raw;
if (configJSONobj.nonStandardCodes === undefined) configJSONobj.nonStandardCodes = [];
if (configJSONobj.enableCompression === undefined) configJSONobj.enableCompression = true;
if (configJSONobj.customHeaders === undefined) configJSONobj.customHeaders = {};
diff --git a/tests.html b/tests.html
index 3ef3565..40e8e96 100644
--- a/tests.html
+++ b/tests.html
@@ -1,7 +1,7 @@
-