-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
95 lines (75 loc) · 2.96 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
const express = require("express");
const jwt = require("jwt-simple");
const crypto = require("crypto");
const app = express();
// Alex only likes Chrome. All FireFox users should get out of here!
const PORT = process.env.PORT || 8080;
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 4096 });
const pub = publicKey.export({ type: "pkcs1", format: "pem" });
const priv = privateKey.export({ type: "pkcs1", format: "pem" });
const bot = require("./bot.js");
app.set("view engine", "hbs");
app.use(express.static("public"));
app.use(express.urlencoded({ extended: false }));
app.use(require("cookie-parser")());
app.use((req, res, next) => {
if(!req.cookies.auth) {
let username = crypto.randomBytes(8).toString("hex");
let cookie = jwt.encode({ username }, priv, "RS256");
req.cookies.auth = cookie;
res.cookie("auth", cookie);
}
try {
let auth = jwt.decode(req.cookies.auth, pub);
res.locals.username = auth.username;
}
catch(err) {
res.clearCookie("auth");
return res.redirect("/?message=Invalid token");
}
let nonce = crypto.randomBytes(16).toString("hex");
res.setHeader("Content-Security-Policy", `
default-src 'self';
img-src 'self' data:;
style-src 'nonce-${nonce}';
font-src https://fonts.googleapis.com/ https://fonts.gstatic.com/;
object-src 'none';
base-uri 'none';
script-src 'self' https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/;
`.trim().replace(/\s+/g, " "));
res.locals.nonce = nonce;
next();
});
const isUser = (user) => (req, res, next) => res.locals.username === user ? next() : res.redirect("/");
app.get("/home", isUser("Alex"), (req, res) => {
res.render("home");
});
app.post("/home", isUser("Alex"), (req, res) => {
let { message } = req.body;
if(!message || typeof message !== "string") {
return res.redirect("/home?message=Missing message");
}
// no XSS
message = message.replace(/"/g, """);
message = message.replace(/</g, "<");
message = message.replace(/>/g, ">");
// convert images and links
message = message.replace(/(https?:\/\/[^\s]*\.(png|jpg|gif)[^\s]*)/g, `<iframe src="$1"></iframe>`);
message = message.replace(/(https?:\/\/(?![^\s]*(?:jpg|png|gif))[^\s]+)/g, `<a href="$1">$1</a>`);
return res.render("home", { message });
});
app.post("/report", isUser("Alex"), (req, res) => {
let { message } = req.body;
if(!message || typeof message !== "string") {
return res.redirect("/home?message=Missing message");
}
bot.visit(message, jwt.encode({ username: "Alex" }, priv, "RS256"));
return res.redirect("/home?message=The admin will look at your message now");
});
app.get("/", (req, res) => {
if(res.locals.username === "Alex") {
return res.redirect("/home");
}
res.render("login");
});
app.listen(PORT, () => console.log(`listening on port ${PORT}`));