Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example showing running bash via a bad rest api. #97

Merged
merged 1 commit into from
Jul 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions examples/nodejs-bad-rest-api/README.md
Original file line number Diff line number Diff line change
@@ -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/<cmd>` 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/<cmd>`.
* falco: will detect when you execute a shell via the express server.

### Access urls under `/api/exec/<cmd>` 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 )
```
24 changes: 24 additions & 0 deletions examples/nodejs-bad-rest-api/demo.yml
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions examples/nodejs-bad-rest-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "bad-rest-api",
"main": "server.js",
"dependencies": {
"express": "~4.0.0"
}
}
25 changes: 25 additions & 0 deletions examples/nodejs-bad-rest-api/server.js
Original file line number Diff line number Diff line change
@@ -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);