Skip to content

Commit 79d4be7

Browse files
authored
feat: add cookie session for logged in state (#962)
1 parent 01c7957 commit 79d4be7

File tree

5 files changed

+123
-20
lines changed

5 files changed

+123
-20
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Here are the exploitable vulnerable packages:
6262
* Code Injection
6363
* Command execution
6464
* Cross-site Scripting (XSS)
65+
* Information exposure
6566
* Security misconfiguration exposes server information
6667
* Insecure protocol (HTTP) communication
6768

@@ -108,6 +109,31 @@ http://localhost:3001/login?redirectPage="><script>alert(1)</script>
108109

109110
To exploit the open redirect, simply provide a URL such as `redirectPage=https://google.com` which exploits the fact that the code doesn't enforce local URLs in `index.js:72`.
110111

112+
#### Hardcoded values - session information
113+
114+
The application initializes a cookie-based session on `app.js:40` as follows:
115+
116+
```js
117+
app.use(session({
118+
secret: 'keyboard cat',
119+
name: 'connect.sid',
120+
cookie: { secure: true }
121+
}))
122+
```
123+
124+
As you can see, the session `secret` used to sign the session is a hardcoded sensitive information inside the code.
125+
126+
First attempt to fix it, can be to move it out to a config file such as:
127+
```js
128+
module.exports = {
129+
cookieSecret: `keyboard cat`
130+
}
131+
```
132+
133+
And then require the configuration file and use it to initialize the session.
134+
However, that still maintains the secret information inside another file, and Snyk Code will warn you about it.
135+
136+
Another case we can discuss here in session management, is that the cookie setting is initialized with `secure: true` which means it will only be transmitted over HTTPS connections. However, there's no `httpOnly` flag set to true, which means that the default false value of it makes the cookie accessible via JavaScript. Snyk Code highlights this potential security misconfiguration so we can fix it. We can note that Snyk Code shows this as a quality information, and not as a security error.
111137

112138
## Docker Image Scanning
113139

app.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ var express = require('express');
1212
var http = require('http');
1313
var path = require('path');
1414
var ejsEngine = require('ejs-locals');
15-
var cookieParser = require('cookie-parser');
1615
var bodyParser = require('body-parser');
16+
var session = require('express-session')
1717
var methodOverride = require('method-override');
1818
var logger = require('morgan');
1919
var errorHandler = require('errorhandler');
@@ -39,7 +39,11 @@ app.set('views', path.join(__dirname, 'views'));
3939
app.set('view engine', 'ejs');
4040
app.use(logger('dev'));
4141
app.use(methodOverride());
42-
app.use(cookieParser());
42+
app.use(session({
43+
secret: 'keyboard cat',
44+
name: 'connect.sid',
45+
cookie: { path: '/' }
46+
}))
4347
app.use(bodyParser.json());
4448
app.use(bodyParser.urlencoded({ extended: false }));
4549
app.use(fileUpload());
@@ -49,9 +53,10 @@ app.use(routes.current_user);
4953
app.get('/', routes.index);
5054
app.get('/login', routes.login);
5155
app.post('/login', routes.loginHandler);
52-
app.get('/admin', routes.admin);
53-
app.get('/account_details', routes.get_account_details);
56+
app.get('/admin', routes.isLoggedIn, routes.admin);
57+
app.get('/account_details', routes.isLoggedIn, routes.account_details);
5458
app.post('/account_details', routes.save_account_details);
59+
app.get('/logout', routes.logout);
5560
app.post('/create', routes.create);
5661
app.get('/destroy/:id', routes.destroy);
5762
app.get('/edit/:id', routes.edit);

package-lock.json

Lines changed: 63 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
"body-parser": "1.9.0",
1919
"cfenv": "^1.0.4",
2020
"consolidate": "0.14.5",
21-
"cookie-parser": "1.3.3",
2221
"dustjs-helpers": "1.5.0",
2322
"dustjs-linkedin": "2.5.0",
2423
"ejs": "1.0.0",
2524
"ejs-locals": "1.0.2",
2625
"errorhandler": "1.2.0",
2726
"express": "4.12.4",
2827
"express-fileupload": "0.0.5",
28+
"express-session": "^1.17.2",
2929
"file-type": "^8.1.0",
3030
"hbs": "^4.0.4",
3131
"humanize-ms": "1.0.1",

routes/index.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ exports.loginHandler = function (req, res, next) {
3838
User.find({ username: req.body.username, password: req.body.password }, function (err, users) {
3939
if (users.length > 0) {
4040
const redirectPage = req.body.redirectPage
41-
return adminLoginSuccess(redirectPage, res)
41+
const session = req.session
42+
const username = req.body.username
43+
return adminLoginSuccess(redirectPage, session, username, res)
4244
} else {
4345
return res.redirect('/admin')
4446
}
@@ -93,8 +95,27 @@ exports.save_account_details = function(req, res, next) {
9395
}
9496
}
9597

96-
function adminLoginSuccess(redirectPage, res) {
97-
console.log({redirectPage})
98+
exports.isLoggedIn = function (req, res, next) {
99+
if (req.session.loggedIn === 1) {
100+
return next()
101+
} else {
102+
return res.redirect('/')
103+
}
104+
}
105+
106+
exports.logout = function (req, res, next) {
107+
req.session.loggedIn = 0
108+
req.session.destroy(function() {
109+
return res.redirect('/')
110+
})
111+
}
112+
113+
function adminLoginSuccess(redirectPage, session, username, res) {
114+
session.loggedIn = 1
115+
116+
// Log the login action for audit
117+
console.log(`User logged in: ${username}`)
118+
98119
if (redirectPage) {
99120
return res.redirect(redirectPage)
100121
} else {

0 commit comments

Comments
 (0)