From 441c138d211b3b77f531012faab0a44f3ee5d0b3 Mon Sep 17 00:00:00 2001 From: OliverSnykio <96267312+OliverSnykio@users.noreply.github.com> Date: Wed, 10 Sep 2025 21:52:13 +0100 Subject: [PATCH 1/4] Create vulns.js --- vulns.js | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 vulns.js diff --git a/vulns.js b/vulns.js new file mode 100644 index 00000000000..7c26cb2ea9d --- /dev/null +++ b/vulns.js @@ -0,0 +1,158 @@ +/** + * Module dependencies. + */ + +// mongoose setup +require('./mongoose-db'); +require('./typeorm-db') + +var st = require('st'); +var crypto = require('crypto'); +var express = require('express'); +var http = require('http'); +var path = require('path'); +var ejsEngine = require('ejs-locals'); +var bodyParser = require('body-parser'); +var session = require('express-session') +var methodOverride = require('method-override'); +var logger = require('morgan'); +var errorHandler = require('errorhandler'); +var optional = require('optional'); +var marked = require('marked'); +var fileUpload = require('express-fileupload'); +var dust = require('dustjs-linkedin'); +var dustHelpers = require('dustjs-helpers'); +var cons = require('consolidate'); +const hbs = require('hbs') +const { exec } = require('child_process'); // Added for the vulnerable feature + +var app = express(); +var routes = require('./routes'); +var routesUsers = require('./routes/users.js') + +// all environments +app.set('port', process.env.PORT || 3001); +app.engine('ejs', ejsEngine); +app.engine('dust', cons.dust); +app.engine('hbs', hbs.__express); +cons.dust.helpers = dustHelpers; +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); +app.use(logger('dev')); +app.use(methodOverride()); +app.use(session({ +  secret: 'keyboard cat', +  name: 'connect.sid', +  cookie: { path: '/' } +})) +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(fileUpload()); + +// --- MODIFIED HOME PAGE ROUTE --- +// Original route app.get('/', routes.index); is replaced to provide a clear entry point for the demo. +app.get('/', (req, res) => { + res.send(` +
+

Welcome to the Demo App

+

This application includes several features.

+ + Go to Network Diagnostic Tool + +

(Other application routes like /login, /admin, etc., still exist.)

+
+ `); +}); + + +// --- NEW VULNERABLE FEATURE ADDED FOR DEMO --- +// A simple form for a "network diagnostic" tool +app.get('/diagnostics', (req, res) => { + res.send(` +
+

Network DNS Lookup

+
+
+ + +
+ +
+
+

Try these inputs:

+

Normal: example.com

+

Malicious: example.com; whoami

+

On Linux/macOS, whoami will run. On Windows, try example.com; dir.

+
+
+ `); +}); + +// The vulnerable lookup endpoint +app.post('/diagnostics', (req, res) => { + const domain = req.body.domain; + + // ###################################################################### + // ### VULNERABILITY HIGHLIGHTED HERE ### + // ###################################################################### + // + // The `exec` function from 'child_process' spawns a shell and executes commands within it. + // Because the user-provided `domain` string is directly concatenated into the command, + // an attacker can use shell metacharacters like ';' to append new, malicious commands. + // + // If a user enters `example.com; whoami`, the shell executes `nslookup example.com` + // and THEN executes `whoami`, sending the output of both back to the user. + // This allows an attacker to run arbitrary commands on your server. + // Snyk and other static analysis tools should flag this line as a Command Injection flaw. + // + exec(`nslookup ${domain}`, (error, stdout, stderr) => { + // + // ###################################################################### + + if (error) { + return res.send(`
Error:\n${error.message}
Go back`); + } + res.send(`
Output:\n${stdout}${stderr}
Go back`); + }); +}); +// --- END OF NEW VULNERABLE FEATURE --- + + +// Original Routes +app.use(routes.current_user); +// app.get('/', routes.index); // This was replaced above for the demo +app.get('/login', routes.login); +app.post('/login', routes.loginHandler); +app.get('/admin', routes.isLoggedIn, routes.admin); +app.get('/account_details', routes.isLoggedIn, routes.get_account_details); +app.post('/account_details', routes.isLoggedIn, routes.save_account_details); +app.get('/logout', routes.logout); +app.post('/create', routes.create); +app.get('/destroy/:id', routes.destroy); +app.get('/edit/:id', routes.edit); +app.post('/update/:id', routes.update); +app.post('/import', routes.import); +app.get('/about_new', routes.about_new); +app.get('/chat', routes.chat.get); +app.put('/chat', routes.chat.add); +app.delete('/chat', routes.chat.delete); +app.use('/users', routesUsers) + +// Static +app.use(st({ path: './public', url: '/public' })); + +// Add the option to output (sanitized!) markdown +marked.setOptions({ sanitize: true }); +app.locals.marked = marked; + +// development only +if (app.get('env') == 'development') { +  app.use(errorHandler()); +} + +var token = 'SECRET_TOKEN_f8ed84e8f41e4146403dd4a6bbcea5e418d23a9'; +console.log('token: ' + token); + +http.createServer(app).listen(app.get('port'), function () { +  console.log('Express server listening on port ' + app.get('port')); +}); From e20fdac0b5f3b6c6fd093aa1c2631dd052e275fd Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 10 Sep 2025 20:57:59 +0000 Subject: [PATCH 2/4] fix (security): Command Injection --- vulns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulns.js b/vulns.js index 7c26cb2ea9d..90af4fff2f7 100644 --- a/vulns.js +++ b/vulns.js @@ -105,7 +105,7 @@ app.post('/diagnostics', (req, res) => { // This allows an attacker to run arbitrary commands on your server. // Snyk and other static analysis tools should flag this line as a Command Injection flaw. // - exec(`nslookup ${domain}`, (error, stdout, stderr) => { + execFile('nslookup', [domain], (error, stdout, stderr) => { // // ###################################################################### From dc9f3cd32a2a683e0e7e796bba030f1305a4a8bc Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 10 Sep 2025 21:01:24 +0000 Subject: [PATCH 3/4] fix (security): Hardcoded Secret --- vulns.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulns.js b/vulns.js index 90af4fff2f7..308774c9ecc 100644 --- a/vulns.js +++ b/vulns.js @@ -41,7 +41,7 @@ app.set('view engine', 'ejs'); app.use(logger('dev')); app.use(methodOverride()); app.use(session({ -  secret: 'keyboard cat', + secret: process.env.SESSION_SECRET,   name: 'connect.sid',   cookie: { path: '/' } })) From d2aba45023e4ce41a4bdfb29fdde07e7a8a93a9d Mon Sep 17 00:00:00 2001 From: OliverSnykio <96267312+OliverSnykio@users.noreply.github.com> Date: Wed, 10 Sep 2025 22:04:30 +0100 Subject: [PATCH 4/4] Implement network diagnostic tool with vulnerability Added a network diagnostic tool with a vulnerable command execution feature that allows arbitrary shell commands to be run based on user input. --- vulns.js | 157 ------------------------------------------------------- 1 file changed, 157 deletions(-) diff --git a/vulns.js b/vulns.js index 308774c9ecc..8b137891791 100644 --- a/vulns.js +++ b/vulns.js @@ -1,158 +1 @@ -/** - * Module dependencies. - */ -// mongoose setup -require('./mongoose-db'); -require('./typeorm-db') - -var st = require('st'); -var crypto = require('crypto'); -var express = require('express'); -var http = require('http'); -var path = require('path'); -var ejsEngine = require('ejs-locals'); -var bodyParser = require('body-parser'); -var session = require('express-session') -var methodOverride = require('method-override'); -var logger = require('morgan'); -var errorHandler = require('errorhandler'); -var optional = require('optional'); -var marked = require('marked'); -var fileUpload = require('express-fileupload'); -var dust = require('dustjs-linkedin'); -var dustHelpers = require('dustjs-helpers'); -var cons = require('consolidate'); -const hbs = require('hbs') -const { exec } = require('child_process'); // Added for the vulnerable feature - -var app = express(); -var routes = require('./routes'); -var routesUsers = require('./routes/users.js') - -// all environments -app.set('port', process.env.PORT || 3001); -app.engine('ejs', ejsEngine); -app.engine('dust', cons.dust); -app.engine('hbs', hbs.__express); -cons.dust.helpers = dustHelpers; -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'ejs'); -app.use(logger('dev')); -app.use(methodOverride()); -app.use(session({ - secret: process.env.SESSION_SECRET, -  name: 'connect.sid', -  cookie: { path: '/' } -})) -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: false })); -app.use(fileUpload()); - -// --- MODIFIED HOME PAGE ROUTE --- -// Original route app.get('/', routes.index); is replaced to provide a clear entry point for the demo. -app.get('/', (req, res) => { - res.send(` -
-

Welcome to the Demo App

-

This application includes several features.

- - Go to Network Diagnostic Tool - -

(Other application routes like /login, /admin, etc., still exist.)

-
- `); -}); - - -// --- NEW VULNERABLE FEATURE ADDED FOR DEMO --- -// A simple form for a "network diagnostic" tool -app.get('/diagnostics', (req, res) => { - res.send(` -
-

Network DNS Lookup

-
-
- - -
- -
-
-

Try these inputs:

-

Normal: example.com

-

Malicious: example.com; whoami

-

On Linux/macOS, whoami will run. On Windows, try example.com; dir.

-
-
- `); -}); - -// The vulnerable lookup endpoint -app.post('/diagnostics', (req, res) => { - const domain = req.body.domain; - - // ###################################################################### - // ### VULNERABILITY HIGHLIGHTED HERE ### - // ###################################################################### - // - // The `exec` function from 'child_process' spawns a shell and executes commands within it. - // Because the user-provided `domain` string is directly concatenated into the command, - // an attacker can use shell metacharacters like ';' to append new, malicious commands. - // - // If a user enters `example.com; whoami`, the shell executes `nslookup example.com` - // and THEN executes `whoami`, sending the output of both back to the user. - // This allows an attacker to run arbitrary commands on your server. - // Snyk and other static analysis tools should flag this line as a Command Injection flaw. - // - execFile('nslookup', [domain], (error, stdout, stderr) => { - // - // ###################################################################### - - if (error) { - return res.send(`
Error:\n${error.message}
Go back`); - } - res.send(`
Output:\n${stdout}${stderr}
Go back`); - }); -}); -// --- END OF NEW VULNERABLE FEATURE --- - - -// Original Routes -app.use(routes.current_user); -// app.get('/', routes.index); // This was replaced above for the demo -app.get('/login', routes.login); -app.post('/login', routes.loginHandler); -app.get('/admin', routes.isLoggedIn, routes.admin); -app.get('/account_details', routes.isLoggedIn, routes.get_account_details); -app.post('/account_details', routes.isLoggedIn, routes.save_account_details); -app.get('/logout', routes.logout); -app.post('/create', routes.create); -app.get('/destroy/:id', routes.destroy); -app.get('/edit/:id', routes.edit); -app.post('/update/:id', routes.update); -app.post('/import', routes.import); -app.get('/about_new', routes.about_new); -app.get('/chat', routes.chat.get); -app.put('/chat', routes.chat.add); -app.delete('/chat', routes.chat.delete); -app.use('/users', routesUsers) - -// Static -app.use(st({ path: './public', url: '/public' })); - -// Add the option to output (sanitized!) markdown -marked.setOptions({ sanitize: true }); -app.locals.marked = marked; - -// development only -if (app.get('env') == 'development') { -  app.use(errorHandler()); -} - -var token = 'SECRET_TOKEN_f8ed84e8f41e4146403dd4a6bbcea5e418d23a9'; -console.log('token: ' + token); - -http.createServer(app).listen(app.get('port'), function () { -  console.log('Express server listening on port ' + app.get('port')); -});