aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorMinteck <freeziv.ytb@gmail.com>2021-03-07 18:29:17 +0100
committerMinteck <freeziv.ytb@gmail.com>2021-03-07 18:29:17 +0100
commit0f79e708bf07721b73ea41e5d341be08e8ea4dce (patch)
treef3c63cd6a9f4ef0b26f95eec6a031600232e80c8 /core
downloadelectrode-0f79e708bf07721b73ea41e5d341be08e8ea4dce.tar.gz
electrode-0f79e708bf07721b73ea41e5d341be08e8ea4dce.tar.bz2
electrode-0f79e708bf07721b73ea41e5d341be08e8ea4dce.zip
Initial commit
Diffstat (limited to 'core')
-rw-r--r--core/access.js52
-rw-r--r--core/cookies.js11
-rw-r--r--core/finder.js22
-rw-r--r--core/headClean.js15
-rw-r--r--core/request.js111
5 files changed, 211 insertions, 0 deletions
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('<html><head><title>ENOTFOUND - File not found</title></head><body><h1>ENOTFOUND</h1><p>This file couldn\'t be found on the server</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ 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('<html><head><title>EACCES - Permission denied</title></head><body><h1>EACCES</h1><p>Permission to access this file was denied by the server configuration</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ 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('<html><head><title>' + error.code + ' - Internal error</title></head><body><h1>' + error.code + '</h1><p>An internal server error ocurred while trying to give back the file</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ 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('<html><head><title>' + e.name + ' - post-PHP error</title></head><body><h1>' + e.name + '</h1><p>Unable to process PHP headers</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ 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('<html><head><title>' + phpc.error.name + ' - PHP error</title></head><body><h1>' + phpc.error.name + '</h1><p>The PHP integration didn\'t fulfill the request correctly:</p><pre>' + phpc.stderr + '</pre><pre>' + phpc.error.message.split("\n").join("<br>") + '</pre><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ 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('<html><head><title>EACCES - Permission denied</title></head><body><h1>EACCES</h1><p>Permission to access this file was denied by the server configuration</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ res.end();
+ }
+ }
+ }
+ }
+ } catch (error) {
+ res.writeHead(500, { 'Content-Type': 'text/html' });
+ res.write('<html><head><title>' + error.name + ' - Internal error</title></head><body><h1>' + error.name + '</h1><p>An internal server error ocurred while trying to give back the file</p><hr><address>' + config.product.name + ' version ' + version + '</address></body></html>');
+ console.log(chalk.gray(cluster.worker.id + " ") + chalk.red("error:") + " " + error.name + ": " + error.message);
+ console.log(error.stack);
+ res.end();
+ }
+}