From 0f79e708bf07721b73ea41e5d341be08e8ea4dce Mon Sep 17 00:00:00 2001 From: Minteck Date: Sun, 7 Mar 2021 18:29:17 +0100 Subject: Initial commit --- core/access.js | 52 +++++++++++++++++++++++++ core/cookies.js | 11 ++++++ core/finder.js | 22 +++++++++++ core/headClean.js | 15 ++++++++ core/request.js | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+) create mode 100644 core/access.js create mode 100644 core/cookies.js create mode 100644 core/finder.js create mode 100644 core/headClean.js create mode 100644 core/request.js (limited to 'core') diff --git a/core/access.js b/core/access.js new file mode 100644 index 0000000..b788213 --- /dev/null +++ b/core/access.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const path = require('path'); +const chalk = require('chalk'); + +module.exports = (filename) => { + if (fs.existsSync(path.dirname(filename) + "/.htaccess")) { + try { + access = fs.readFileSync(path.dirname(filename) + "/.htaccess").toString(); + if (access.trim().includes("##net.minteckprojects.fns.electrode@DenyAccess##")) { + return false; + } else { + return true; + } + } catch (e) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " unable to read htaccess from " + path.dirname(filename) + ": " + e.message); + console.log(e.stack); + return true; + } + } else { + if (fs.existsSync(path.dirname(path.dirname(filename)) + "/.htaccess")) { + try { + access = fs.readFileSync(path.dirname(path.dirname(filename)) + "/.htaccess").toString(); + if (access.trim().includes("##net.minteckprojects.fns.electrode@DenyAccess##")) { + return false; + } else { + return true; + } + } catch (e) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " unable to read htaccess from " + path.dirname(path.dirname(filename)) + ": " + e.message); + console.log(e.stack); + return true; + } + } else { + if (fs.existsSync(path.dirname(path.dirname(path.dirname(filename))) + "/.htaccess")) { + try { + access = fs.readFileSync(path.dirname(path.dirname(path.dirname(filename))) + "/.htaccess").toString(); + if (access.trim().includes("##net.minteckprojects.fns.electrode@DenyAccess##")) { + return false; + } else { + return true; + } + } catch (e) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " unable to read htaccess from " + path.dirname(path.dirname(path.dirname(filename))) + ": " + e.message); + console.log(e.stack); + return true; + } + } else { + return true; + } + } + } +} \ No newline at end of file diff --git a/core/cookies.js b/core/cookies.js new file mode 100644 index 0000000..c51380e --- /dev/null +++ b/core/cookies.js @@ -0,0 +1,11 @@ +module.exports = (request) => { + var list = {}, + rc = request.headers.cookie; + + rc && rc.split(';').forEach(function( cookie ) { + var parts = cookie.split('='); + list[parts.shift().trim()] = decodeURI(parts.join('=')); + }); + + return list; +} \ No newline at end of file diff --git a/core/finder.js b/core/finder.js new file mode 100644 index 0000000..ac5f254 --- /dev/null +++ b/core/finder.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const url = require('url'); + +/** + * @param {string} url + */ +module.exports = (efs) => { + cfs = url.parse(efs, true).pathname; + if (fs.existsSync("./public/" + cfs) && !fs.lstatSync("./public/" + cfs).isDirectory()) { + return "./public/" + cfs; + } else if (fs.existsSync("./public/" + cfs + "/index.php")) { + return "./public/" + cfs + "/index.php"; + } else if (fs.existsSync("./public/" + cfs + "/index.html")) { + return "./public/" + cfs + "/index.html"; + } else if (fs.existsSync("./public/" + cfs)) { + return "./public/" + cfs; + } else if (cfs.endsWith(".htaccess")) { + return null; + } else { + return null; + } +} \ No newline at end of file diff --git a/core/headClean.js b/core/headClean.js new file mode 100644 index 0000000..31ce5a9 --- /dev/null +++ b/core/headClean.js @@ -0,0 +1,15 @@ +const fs = require('fs'); + +module.exports = () => { + fs.readdir("./cache", (error, files) => { + if (error) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " unable to cleanup cache: " + error.message); + } else { + files.forEach((file) => { + if (file.startsWith("HAD_")) { + fs.unlink("./cache/" + file, () => {}); + } + }) + } + }) +} \ No newline at end of file diff --git a/core/request.js b/core/request.js new file mode 100644 index 0000000..caceceb --- /dev/null +++ b/core/request.js @@ -0,0 +1,111 @@ +const chalk = require('chalk'); +const mime = require('mime'); +const FileType = require('file-type'); + +module.exports = (req, res, post, files) => { + try { + res.setHeader("X-Electrode-WorkerID", cluster.worker.id) + res.setHeader('Cache-Control', 'private, no-cache, no-store, must-revalidate'); + res.setHeader('Expires', '-1'); + res.setHeader('Pragma', 'no-cache'); + if (req.url.includes('../')) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.blue("warn:") + " working around exploit"); + res.writeHead(301, { 'Location': '/index.php' }); + res.end(); + } else if (req.url.trim() == '/' || req.url.trim() == '//' || req.url.trim() == '') { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.blue("warn:") + " working around redirection trap"); + res.writeHead(301, { 'Location': '/index.php' }); + res.end(); + } else { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.green("verb:") + " " + req.method + " " + req.url + " - HTTP/" + req.httpVersion + " - " + req.connection.remoteAddress); + + filename = core.finder(req.url); + if (filename == null) { + res.writeHead(404, { 'Content-Type': 'text/html' }); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " not found: " + req.url); + res.write('ENOTFOUND - File not found

ENOTFOUND

This file couldn\'t be found on the server


' + config.product.name + ' version ' + version + '
'); + res.end(); + } else { + if (require('fs').lstatSync(filename).isDirectory()) { + res.writeHead(403, { 'Content-Type': 'text/html' }); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " is directory: " + req.url); + res.write('EACCES - Permission denied

EACCES

Permission to access this file was denied by the server configuration


' + config.product.name + ' version ' + version + '
'); + res.end(); + } else { + if (core.access(filename)) { + if (!filename.endsWith(".php")) { + res.setHeader("Cache-Control", "no-cache") + require('fs').readFile(filename, (error, file) => { + if (error) { + res.writeHead(500, { 'Content-Type': 'text/html' }); + res.write('' + error.code + ' - Internal error

' + error.code + '

An internal server error ocurred while trying to give back the file


' + config.product.name + ' version ' + version + '
'); + res.end(); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.red("error:") + " while loading file: " + error.message); + } else { + FileType.fromFile(filename).then((type) => { + res.writeHead(200, { 'Content-Type': type + "", 'Content-Size': file.toString().length }); + res.end(file); + }); + } + }) + } else { + php.runtime(php.cache(req, res, filename, post, files)).then((phpc) => { + if (phpc.error == null) { + if (require('fs').existsSync("./cache/HAD_" + phpc.id + ".json")) { + try { + headers = JSON.parse(require('fs').readFileSync("./cache/HAD_" + phpc.id + ".json")); + hlist = {}; + headers.forEach(h => { + p = h.split(":"); + n = p[0]; + p.shift(); + v = p.join(":"); + hlist[n.toLowerCase()] = v; + }) + if (typeof hlist["content-type"] == "undefined") { + hlist["content-type"] = "text/html"; + } + if (typeof hlist["location"] != "undefined") { + res.writeHead(301, hlist); + } else { + res.writeHead(200, hlist); + } + } catch (e) { + console.log(chalk.gray(cluster.worker.id + " ") + chalk.red("error:") + " while loading php headers: " + e.message); + console.log(e.stack); + res.writeHead(500, { 'Content-Type': 'text/html' }); + res.write('' + e.name + ' - post-PHP error

' + e.name + '

Unable to process PHP headers


' + config.product.name + ' version ' + version + '
'); + res.end(); + } + } + + res.write(phpc.content); + res.end(); + core.headClean(); + } else { + res.writeHead(500, { 'Content-Type': 'text/html' }); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.red("error:") + " while running php: " + phpc.error.message); + console.log(phpc.error.stack); + res.write('' + phpc.error.name + ' - PHP error

' + phpc.error.name + '

The PHP integration didn\'t fulfill the request correctly:

' + phpc.stderr + '
' + phpc.error.message.split("\n").join("
") + '

' + config.product.name + ' version ' + version + '
'); + res.end(); + core.headClean(); + } + }); + } + } else { + res.writeHead(403, { 'Content-Type': 'text/html' }); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.yellow("warn:") + " denied by .htaccess: " + req.url); + res.write('EACCES - Permission denied

EACCES

Permission to access this file was denied by the server configuration


' + config.product.name + ' version ' + version + '
'); + res.end(); + } + } + } + } + } catch (error) { + res.writeHead(500, { 'Content-Type': 'text/html' }); + res.write('' + error.name + ' - Internal error

' + error.name + '

An internal server error ocurred while trying to give back the file


' + config.product.name + ' version ' + version + '
'); + console.log(chalk.gray(cluster.worker.id + " ") + chalk.red("error:") + " " + error.name + ": " + error.message); + console.log(error.stack); + res.end(); + } +} -- cgit