diff --git a/index.html b/index.html index 288ba91..69ee55d 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ - SVR.JS 3.14.5 + SVR.JS 3.14.6 -

Welcome to SVR.JS 3.14.5

+

Welcome to SVR.JS 3.14.6



@@ -85,8 +85,13 @@

Changes:

Tests
diff --git a/licenses/index.html b/licenses/index.html index fc74aab..d629b68 100644 --- a/licenses/index.html +++ b/licenses/index.html @@ -1,7 +1,7 @@ - SVR.JS 3.14.5 Licenses + SVR.JS 3.14.6 Licenses -

SVR.JS 3.14.5 Licenses

-

SVR.JS 3.14.5

+

SVR.JS 3.14.6 Licenses

+

SVR.JS 3.14.6

MIT License

@@ -37,7 +37,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-

Packages used by SVR.JS 3.14.5

+

Packages used by SVR.JS 3.14.6

License: MIT
diff --git a/loghighlight.js b/loghighlight.js index a934a27..b4a97f3 100644 --- a/loghighlight.js +++ b/loghighlight.js @@ -34,17 +34,19 @@ function viewLog(log) { if(log[log.length-1] == "") log.pop(); if(log[0] == "") log.shift(); for(var i=0;i " + req.headers.host); @@ -3464,7 +3463,7 @@ if (!cluster.isPrimary) { if (isProxy) { var eheaders = getCustomHeaders(); eheaders["Content-Type"] = "text/html; charset=utf-8"; - res.writeHead(501, "Not Implemented", eheaders); + res.writeHead(501, http.STATUS_CODES[501], eheaders); res.write("Proxy not implemented

Proxy not implemented

SVR.JS doesn't support proxy without proxy mod. If you're administator of this server, then install this mod in order to use SVR.JS as a proxy.

" + (exposeServerVersion ? "SVR.JS/" + version + " (" + getOS() + "; " + (process.isBun ? ("Bun/v" + process.versions.bun + "; like Node.JS/" + process.version) : ("Node.JS/" + process.version)) + ")" : "SVR.JS").replace(/&/g, "&").replace(//g, ">") + "

"); res.end(); serverconsole.errmessage("SVR.JS doesn't support proxy without proxy mod."); @@ -3474,7 +3473,7 @@ if (!cluster.isPrimary) { if (req.method == "OPTIONS") { 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 if (req.method != "GET" && req.method != "POST" && req.method != "HEAD") { @@ -3507,7 +3506,7 @@ if (!cluster.isPrimary) { var hdhds = getCustomHeaders(); hdhds["Content-Type"] = "text/html; charset=utf-8"; - res.writeHead(200, "OK", hdhds); + res.writeHead(200, http.STATUS_CODES[200], hdhds); res.end((head == "" ? "SVR.JS status" + (req.headers.host == undefined ? "" : " for " + String(req.headers.host).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")) + "" : head.replace(//i, "SVR.JS status" + (req.headers.host == undefined ? "" : " for " + String(req.headers.host).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")) + "")) + "

SVR.JS status" + (req.headers.host == undefined ? "" : " for " + String(req.headers.host).replace(/&/g, "&").replace(//g, ">")) + "

" + statusBody + (foot == "" ? "" : foot)); return; } @@ -3704,25 +3703,15 @@ if (!cluster.isPrimary) { var estats = filelist[i].stats; var ename = filelist[i].name; if (filelist[i].errored) { - if (estats) { - directoryListingRows.push( - "\"[BAD]\"" + - ename.replace(/&/g, "&").replace(//g, ">") + - "-" + - estats.mtime.toDateString() + - "\r\n" - ); - } else { - directoryListingRows.push( - "\"[BAD]\"" + - ename.replace(/&/g, "&").replace(//g, ">") + - "--\r\n" - ); - } + directoryListingRows.push( + "\"[BAD]\"" + + ename.replace(/&/g, "&").replace(//g, ">") + + "-" + + (estats ? estats.mtime.toDateString() : "-") + + "\r\n" + ); } else { var entry = "\"[alt]\"Access denied - SVR.JS

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 @@ - SVR.JS 3.14.5 Tests + SVR.JS 3.14.6 Tests -

SVR.JS 3.14.5 Tests

+

SVR.JS 3.14.6 Tests

Directory (without trailing slash)

Directory (with query)