-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
239 lines (189 loc) · 6.39 KB
/
index.js
File metadata and controls
239 lines (189 loc) · 6.39 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
require("./utils.js");
require('dotenv').config();
const express = require('express');
const session = require('express-session');
const MongoStore = require('connect-mongo');
const bcrypt = require('bcrypt');
const saltRounds = 12;
const port = process.env.PORT || 3000;
const app = express();
const Joi = require("joi");
const expireTime = 60 * 60 * 1000; //expires after 1 hour (minutes * seconds * millis)
/* secret information section */
const mongodb_host = process.env.MONGODB_HOST;
const mongodb_user = process.env.MONGODB_USER;
const mongodb_password = process.env.MONGODB_PASSWORD;
const mongodb_database = process.env.MONGODB_DATABASE;
const mongodb_session_secret = process.env.MONGODB_SESSION_SECRET;
const node_session_secret = process.env.NODE_SESSION_SECRET;
/* END secret section */
var { database } = require('./databaseConnection');
var mongoStore = MongoStore.create({
mongoUrl: `mongodb+srv://${mongodb_user}:${mongodb_password}@${mongodb_host}/test`,
crypto: {
secret: mongodb_session_secret
}
});
const userCollection = database.db(mongodb_database).collection('users');
app.use(express.urlencoded({extended: false}));
var mongoStore = MongoStore.create({
mongoUrl: `mongodb+srv://${mongodb_user}:${mongodb_password}@${mongodb_host}/sessions`,
crypto: {
secret: mongodb_session_secret
}
})
app.use(session({
secret: node_session_secret,
store: mongoStore, //default is memory store
saveUninitialized: false,
resave: true
}
));
// App Get for the home page
app.get('/', (req,res) => {
if (req.session.username) {
const username = req.session.username;
const message = `Hello, ${username}.`;
const links = `
<a href="/members">Members Area</a>
<a href="/logout">Logout</a>
`;
res.send(`
<h1>${message}</h1>
<p>${links}</p>
`);
} else {
res.send(`<h1>Welcome to the Home Page</h1><br><a href='/signup'>Sign up</a><br><a href='/login'>Log in</a>`);
}
});
app.get('/nosql-injection', async (req,res) => {
var username = req.query.user;
if (!username) {
res.send(`<h3>no user provided - try /nosql-injection?user=name</h3> <h3>or /nosql-injection?user[$ne]=name</h3>`);
return;
}
console.log("user: "+username);
const schema = Joi.string().max(20).required();
const validationResult = schema.validate(username);
//If we didn't use Joi to validate and check for a valid URL parameter below
// we could run our userCollection.find and it would be possible to attack.
// A URL parameter of user[$ne]=name would get executed as a MongoDB command
// and may result in revealing information about all users or a successful
// login without knowing the correct password.
if (validationResult.error != null) {
console.log(validationResult.error);
res.send("<h1 style='color:darkred;'>A NoSQL injection attack was detected!!</h1>");
return;
}
const result = await userCollection.find({username: username}).project({username: 1, password: 1, _id: 1}).toArray();
console.log(result);
res.send(`<h1>Hello ${username}</h1>`);
});
// New User Signup
app.get('/signup', (req,res) => {
var html = `
create user
<form action='/submitUser' method='post'>
<input name='username' type='text' placeholder='username'>
<input name='password' type='password' placeholder='password'>
<button>Submit</button>
</form>
`;
res.send(html);
});
app.post('/submitUser', async (req,res) => {
var username = req.body.username;
var password = req.body.password;
const schema = Joi.object(
{
username: Joi.string().alphanum().max(20).required(),
password: Joi.string().max(20).required()
});
const validationResult = schema.validate({username, password});
if (validationResult.error != null) {
console.log(validationResult.error);
res.redirect("/createUser");
return;
}
var hashedPassword = await bcrypt.hash(password, saltRounds);
await userCollection.insertOne({username: username, password: hashedPassword});
console.log("Inserted user");
req.session.authenticated = true;
req.session.username = username;
req.session.cookie.maxAge = expireTime;
res.redirect('/members');
});
//User Login
app.get('/login', (req,res) => {
var badlogin = req.query.badlogin;
var html = `
log in
<form action='/loggingin' method='post'>
<input name='username' type='text' placeholder='username'>
<input name='password' type='password' placeholder='password'>
<button>Submit</button>
</form>
`;
if(badlogin == 1) {
html += `<h3>Incorrect username or password</h3>`;
}
res.send(html);
});
app.post('/loggingin', async (req,res) => {
var username = req.body.username;
var password = req.body.password;
const schema = Joi.string().max(20).required();
const validationResult = schema.validate(username);
if (validationResult.error != null) {
console.log(validationResult.error);
res.redirect("/login");
return;
}
const result = await userCollection.find({username: username}).project({username: 1, password: 1, _id: 1}).toArray();
console.log(result);
if (result.length != 1) {
console.log("user not found");
res.redirect("/login");
return;
}
if (await bcrypt.compare(password, result[0].password)) {
console.log("correct password");
req.session.authenticated = true;
req.session.username = username;
req.session.cookie.maxAge = expireTime;
res.redirect('/loggedIn');
return;
}
else {
res.redirect("/login?badlogin=1");
return;
}
});
app.get('/loggedin', (req,res) => {
if (!req.session.authenticated) {
res.redirect('/login');
}
res.redirect('/members');
});
app.get('/logout', (req,res) => {
req.session.destroy();
res.redirect('/');
});
app.get('/members', (req, res) => {
if (!req.session.authenticated) {
res.redirect('/');
}
const randomIndex = Math.floor(Math.random() * 3) + 1;
var username = req.session.username;
var picname = "pokemon" + randomIndex + ".jpg";
res.send(`Hello, ` + username + `<br> <img src='/pictures/` + picname + `' style='width: 250px;'>
<br> <button type='button' onclick="window.location.href='/logout'">Logout</button>`);
});
app.use(express.static(__dirname + "/public"));
app.get("*", (req,res) => {
res.status(404);
res.send("Page not found - 404");
})
app.listen(port, () => {
console.log("Node application listening on port "+port);
});