Skip to content

Commit

Permalink
feat: add runtime monitoring
Browse files Browse the repository at this point in the history
  • Loading branch information
lirantal authored Jan 8, 2019
2 parents 3b12f9f + ab7cce9 commit 921250b
Show file tree
Hide file tree
Showing 4 changed files with 5,545 additions and 35 deletions.
54 changes: 44 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
## Goof - Snyk's vulnerable demo app
# Goof - Snyk's vulnerable demo app
[![Known Vulnerabilities](https://snyk.io/test/github/snyk/goof/badge.svg?style=flat-square)](https://snyk.io/test/github/snyk/goof)

A vulnerable Node.js demo application, based on the [Dreamers Lab tutorial](http://dreamerslab.com/blog/en/write-a-todo-list-with-express-and-mongodb/).

### Running
## Features

This vulnerable app includes the following capabilities to experiment with:
* [Exploitable packages](#exploiting-the-vulnerabilities) with known vulnerabilities
* [Docker Image Scanning](#docker-image-scanning) for base images with known vulnerabilities in system libraries
* [Runtime alerts](#runtime-alerts) for detecting an invocation of vulnerable functions in open source dependencies

## Running
```bash
mongod &

Expand All @@ -13,18 +20,17 @@ npm start
```
This will run Goof locally, using a local mongo on the default port and listening on port 3001 (http://localhost:3001)

### Running with docker-compose
## Running with docker-compose
```bash
docker-compose up --build

docker-compose down
```

#### Heroku usage
### Heroku usage
Goof requires attaching a MongoLab service to be deployed as a Heroku app.
That sets up the MONGOLAB_URI env var so everything after should just work.

#### CloudFoundry usage
### CloudFoundry usage
Goof requires attaching a MongoLab service and naming it "goof-mongo" to be deployed on CloudFoundry.
The code explicitly looks for credentials to that service.

Expand All @@ -34,7 +40,7 @@ To bulk delete the current list of TODO items from the DB run:
npm run cleanup
```

### Exploiting the vulnerabilities
## Exploiting the vulnerabilities

This app uses npm dependencies holding known vulnerabilities.

Expand All @@ -44,9 +50,38 @@ Here are the exploitable vulnerable packages:
- [ms - ReDoS](https://snyk.io/vuln/npm:ms:20151024)
- [marked - XSS](https://snyk.io/vuln/npm:marked:20150520)

The `exploits` directory includes a series of steps to demonstrate each one.
The `exploits/` directory includes a series of steps to demonstrate each one.

## Docker Image Scanning

The `Dockerfile` makes use of a base image (`node:6-stretch`) that is known to have system libraries with vulnerabilities.

To scan the image for vulnerabilities, run:
```bash
snyk test --docker node:6-stretch --file=Dockerfile
```

To monitor this image and receive alerts with Snyk:
```bash
snyk monitor --docker node:6-stretch
```

## Runtime Alerts

Snyk provides the ability to monitor application runtime behavior and detect an invocation of a function is known to be vulnerable and used within open source dependencies that the application makes use of.

The agent is installed and initialized in [app.js](./app.js#L5).

For the agent to report back to your snyk account on the vulnerabilities it detected it needs to know which project on Snyk to associate with the monitoring. Due to that, we need to provide it with the project id through an environment variable `SNYK_PROJECT_ID`

### Fixing the issues
To run the Node.js app with runtime monitoring:
```bash
SNYK_PROJECT_ID=<PROJECT_ID> npm start
```

** The app will continue to work normally even if not provided a project id

## Fixing the issues
To find these flaws in this application (and in your own apps), run:
```
npm install -g snyk
Expand All @@ -55,4 +90,3 @@ snyk wizard

In this application, the default `snyk wizard` answers will fix all the issues.
When the wizard is done, restart the application and run the exploits again to confirm they are fixed.

43 changes: 24 additions & 19 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,33 @@
* Module dependencies.
*/

const snyk = require('@snyk/nodejs-runtime-agent')
snyk({
projectId: process.env.SNYK_PROJECT_ID,
});

// mongoose setup
require('./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 cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
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 cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
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');
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');

var app = express();
var app = express();
var routes = require('./routes');

// all environments
Expand Down Expand Up @@ -52,7 +57,7 @@ app.post('/update/:id', routes.update);
app.post('/import', routes.import);
app.get('/about_new', routes.about_new);
// Static
app.use(st({path: './public', url: '/public'}));
app.use(st({ path: './public', url: '/public' }));

// Add the option to output (sanitized!) markdown
marked.setOptions({ sanitize: true });
Expand All @@ -66,6 +71,6 @@ if (app.get('env') == 'development') {
var token = 'SECRET_TOKEN_f8ed84e8f41e4146403dd4a6bbcea5e418d23a9';
console.log('token: ' + token);

http.createServer(app).listen(app.get('port'), function() {
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Loading

0 comments on commit 921250b

Please sign in to comment.