diff --git a/Vuln.ts b/Vuln.ts new file mode 100644 index 00000000000..7c26cb2ea9d --- /dev/null +++ b/Vuln.ts @@ -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')); +});