173 lines
5.5 KiB
JavaScript
173 lines
5.5 KiB
JavaScript
const crypto = require("node:crypto");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
|
|
const cookieparser = require("cookie-parser");
|
|
const sqlite = require("better-sqlite3");
|
|
const geoip = require("geoip-country");
|
|
const express = require("express");
|
|
const bcrypt = require("bcrypt");
|
|
|
|
const database = sqlite("./database.db");
|
|
const app = express();
|
|
|
|
const panelgenesis = fs.readFileSync("./files/panelgenesis.html", "utf8");
|
|
const panelending = fs.readFileSync("./files/panelending.html", "utf8");
|
|
const loginp2 = fs.readFileSync("./files/loginp2.html", "utf8");
|
|
const invalidp2 = fs.readFileSync("./files/invalidp2.html", "utf8");
|
|
const hmacsecret = Buffer.from(fs.readFileSync("./hmacsecret", "utf8"), "base64url");
|
|
|
|
const queryA = database.prepare("SELECT identifier, quote FROM fluff_authentication_base WHERE identifier = ?;");
|
|
const queryB = database.prepare("SELECT id, passhash FROM fluff_authentication_base WHERE identifier = ?;");
|
|
const queryC = database.prepare("SELECT * FROM fluff_authentication_base WHERE id = ?;");
|
|
const queryD = database.prepare("SELECT serviceId FROM fluff_authorised_services WHERE userId = ?;");
|
|
const queryE = database.prepare("SELECT * FROM fluff_services WHERE id = ?;");
|
|
|
|
function sha384(data) {
|
|
return crypto.createHash("sha384").update(data).digest("base64url");
|
|
}
|
|
function hmacify(data) {
|
|
return sha384(`${sha384(data)}${sha384(hmacsecret)}`);
|
|
}
|
|
function genToken(userId) {
|
|
const prepend = `${userId}.${Date.now()+3_600_000}.${crypto.randomBytes(16).toString("base64url")}`;
|
|
const signature = hmacify(prepend);
|
|
|
|
return `${prepend}.${signature}`;
|
|
}
|
|
function verifyToken(token) {
|
|
if (typeof token !== "string") return false;
|
|
|
|
const split = token.split(".");
|
|
const bib = `${split[0]}.${split[1]}.${split[2]}`;
|
|
const sig = split[3];
|
|
|
|
if (hmacify(bib) !== sig)
|
|
return false;
|
|
|
|
const expiration = parseInt(split[1]);
|
|
if (Date.now() > expiration) {
|
|
return false;
|
|
}
|
|
|
|
return split[0];
|
|
}
|
|
function sanitiseStringHTML(str) {
|
|
return str.replaceAll("&", "&").replaceAll(">", ">").replaceAll("<", "<");
|
|
}
|
|
|
|
app.use(express.urlencoded());
|
|
app.use(cookieparser());
|
|
app.use((req, res, next) => {
|
|
console.log(req.headers);
|
|
|
|
if (typeof req.headers['referer'] !== "string") return next();
|
|
|
|
const pars = new URL(req.headers['referer']);
|
|
console.log(pars.hostname);
|
|
if (pars.hostname !== "desloratadyna.net") {
|
|
res.status(403);
|
|
res.end();
|
|
return;
|
|
}
|
|
|
|
next();
|
|
});
|
|
app.use((req, res, next) => {
|
|
req.userId = verifyToken(req.cookies.token);
|
|
if (!req.headers['x-forwarded-for']) return next();
|
|
|
|
const geo = geoip.lookup(req.headers['x-forwarded-for']);
|
|
console.log(geo);
|
|
|
|
if (geo.country !== "US")
|
|
if (geo.country !== "UA")
|
|
if (geo.country !== "PL") {
|
|
const stream = fs.createReadStream("./files/disallowed.html");
|
|
|
|
res.status(451);
|
|
res.setHeader("Content-Type", "text/html");
|
|
stream.pipe(res);
|
|
|
|
return;
|
|
}
|
|
next();
|
|
});
|
|
|
|
app.get("/cgi-bin/loginp1.js", async (req, res, next) => {
|
|
const stream = fs.createReadStream("./files/login.html");
|
|
|
|
res.setHeader("Content-Type", "text/html");
|
|
stream.pipe(res);
|
|
});
|
|
|
|
app.post("/cgi-bin/loginp2.js", async (req, res, next) => {
|
|
const funkyData = queryA.all(req.body.identifier);
|
|
if (funkyData.length !== 1) {
|
|
const pisstream = fs.createReadStream("./files/invalidp1.html");
|
|
res.setHeader("Content-Type", "text/html");
|
|
pisstream.pipe(res);
|
|
|
|
return;
|
|
}
|
|
|
|
if (req.body.invalid === "true") {
|
|
res.setHeader("Content-Type", "text/html");
|
|
res.write(invalidp2.replaceAll("PYRAPYRAPYRAPYRA").replaceAll("PYRIPYRIPYRIPYRI", funkyData[0].quote));
|
|
res.end();
|
|
|
|
return;
|
|
}
|
|
|
|
res.setHeader("Content-Type", "text/html");
|
|
res.write(loginp2.replaceAll("PYRAPYRAPYRAPYRA", req.body.identifier).replaceAll("PYRIPYRIPYRIPYRI", funkyData[0].quote));
|
|
res.end();
|
|
});
|
|
|
|
app.post("/cgi-bin/loginp3.js", async (req, res, next) => {
|
|
const funnyData = queryB.get(req.body.identifier);
|
|
const hashd = sha384(req.body.password);
|
|
res.setHeader("Content-type", "text/html");
|
|
|
|
const valid = await bcrypt.compare(hashd, funnyData.passhash);
|
|
if (!valid) {
|
|
res.redirect("/cgi-bin/loginp2.js?invalid=true&identifier="+encodeURIComponent(req.body.identifier));
|
|
return;
|
|
}
|
|
|
|
console.log(funnyData.id);
|
|
res.cookie("token", genToken(funnyData.id), { maxAge: 1 * 1 * 60 * 60 * 1000, sameSite: 'strict' });
|
|
res.redirect("/cgi-bin/primarypage");
|
|
});
|
|
|
|
app.get("/cgi-bin/primarypage", async (req, res, next) => {
|
|
if (req.userId === false) return res.redirect("/");
|
|
const userData = queryC.get(req.userId);
|
|
const serviceData = queryD.all(req.userId);
|
|
|
|
console.log(userData);
|
|
|
|
res.setHeader("content-type", "text/html");
|
|
res.write(panelgenesis);
|
|
res.write(`<p id="hello">haihoo, ${userData.identifier}</p>`);
|
|
res.write("<table border=1 cellpadding=5 cellspacing=0><tbody><tr><th>name</th><th width=\"400px\">description</th><th>actions</th></tr>");
|
|
|
|
for (let i = 0; i < serviceData.length; i++) {
|
|
const service = queryE.get(serviceData[i].serviceId);
|
|
res.write(`<tr><td>${sanitiseStringHTML(service.displayName)}</td><td>${sanitiseStringHTML(service.shortDescription)}</td><td>`);
|
|
res.write(`<a href="//desloratadyna.net/cgi-bin/unauthorise/${serviceData[i].serviceId}">unauthorise service</a><br>`);
|
|
res.write(`<a href="${encodeURI(service.tosLink)}">terms of service</a><br>`);
|
|
res.write(`<a href="${encodeURI(service.ppLink)}">privacy policy</a><br>`);
|
|
res.write('</td></tr>');
|
|
}
|
|
|
|
res.write("</tbody></table>");
|
|
res.write(`<br><p id="tiny">Generated just for you, by ${os.hostname()}<br>${new Date()}</p>`);
|
|
res.write(panelending);
|
|
res.end();
|
|
});
|
|
|
|
// haha 420
|
|
app.listen(42420);
|
|
|