diff --git a/examples/nodejs-bad-rest-api/README.md b/examples/nodejs-bad-rest-api/README.md new file mode 100644 index 00000000000..fb254a97a13 --- /dev/null +++ b/examples/nodejs-bad-rest-api/README.md @@ -0,0 +1,66 @@ +#Demo of falco with bash exec via poorly designed REST API. + +## Introduction + +This example shows how a server could have a poorly designed API that +allowed a client to execute arbitrary programs on the server, and how +that behavior can be detected using Sysdig Falco. + +`server.js` in this directory defines the server. The poorly designed +API is this route handler: + +```javascript +router.get('/exec/:cmd', function(req, res) { + var output = child_process.execSync(req.params.cmd); + res.send(output); +}); + +app.use('/api', router); +``` + +It blindly takes the url portion after `/api/exec/` and tries to +execute it. A horrible design choice(!), but allows us to easily show +Sysdig falco's capabilities. + +## Demo architecture + +### Start everything using docker-compose + +From this directory, run the following: + +``` +$ docker-compose -f demo.yml up +``` + +This starts the following containers: + +* express_server: simple express server exposing a REST API under the endpoint `/api/exec/`. +* falco: will detect when you execute a shell via the express server. + +### Access urls under `/api/exec/` to run arbitrary commands. + +Run the following commands to execute arbitrary commands like 'ls', 'pwd', etc: + +``` +$ curl http://localhost:8080/api/exec/ls + +demo.yml +node_modules +package.json +README.md +server.js +``` + +``` +$ curl http://localhost:8080/api/exec/pwd + +.../examples/nodejs-bad-rest-api +``` + +### Try to run bash via `/api/exec/bash`, falco sends alert. + +If you try to run bash via `/api/exec/bash`, falco will generate an alert: + +``` +falco | 22:26:53.536628076: Warning Shell spawned in a container other than entrypoint (user=root container_id=6f339b8aeb0a container_name=express_server shell=bash parent=sh cmdline=bash ) +``` diff --git a/examples/nodejs-bad-rest-api/demo.yml b/examples/nodejs-bad-rest-api/demo.yml new file mode 100644 index 00000000000..a826ab6e4d5 --- /dev/null +++ b/examples/nodejs-bad-rest-api/demo.yml @@ -0,0 +1,24 @@ +# Owned by software vendor, serving install-software.sh. +express_server: + container_name: express_server + image: node:latest + working_dir: /usr/src/app + command: bash -c "npm install && node server.js" + ports: + - "8080:8080" + volumes: + - ${PWD}:/usr/src/app + +falco: + container_name: falco + image: sysdig/falco:latest + privileged: true + volumes: + - /var/run/docker.sock:/host/var/run/docker.sock + - /dev:/host/dev + - /proc:/host/proc:ro + - /boot:/host/boot:ro + - /lib/modules:/host/lib/modules:ro + - /usr:/host/usr:ro + - ${PWD}/../../rules/falco_rules.yaml:/etc/falco_rules.yaml + tty: true diff --git a/examples/nodejs-bad-rest-api/package.json b/examples/nodejs-bad-rest-api/package.json new file mode 100644 index 00000000000..7eb284107aa --- /dev/null +++ b/examples/nodejs-bad-rest-api/package.json @@ -0,0 +1,7 @@ +{ + "name": "bad-rest-api", + "main": "server.js", + "dependencies": { + "express": "~4.0.0" + } +} diff --git a/examples/nodejs-bad-rest-api/server.js b/examples/nodejs-bad-rest-api/server.js new file mode 100644 index 00000000000..bb437302917 --- /dev/null +++ b/examples/nodejs-bad-rest-api/server.js @@ -0,0 +1,25 @@ +var express = require('express'); // call express +var app = express(); // define our app using express +var child_process = require('child_process'); + +var port = process.env.PORT || 8080; // set our port + +// ROUTES FOR OUR API +// ============================================================================= +var router = express.Router(); // get an instance of the express Router + +// test route to make sure everything is working (accessed at GET http://localhost:8080/api) +router.get('/', function(req, res) { + res.json({ message: 'API available'}); +}); + +router.get('/exec/:cmd', function(req, res) { + var output = child_process.execSync(req.params.cmd); + res.send(output); +}); + +app.use('/api', router); + +app.listen(port); +console.log('Server running on port: ' + port); +