diff --git a/.travis.yml b/.travis.yml index 83779b04..744dcbda 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ language: node_js node_js: - - '6' - - '7' + - '8.9' dist: trusty sudo: required diff --git a/CHANGES.md b/CHANGES.md index 3c4cceea..fcefffbf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,9 @@ ## 5.0.0 - March 16, 2018 Features, enhancements: -- Lerna package split, udaru-core, udaru-plugin and udaru-server now in separate npm packages [commit](https://github.com/nearform/udaru/pull/444) +- Lerna package split, udaru-core, udaru-plugin and udaru-server now in separate npm packages [commit](https://github.com/nearform/udaru/pull/444) - **Breaking change**: 404 not found on endpoint GET /authorization/teams/${teamId}/users if team does not exist [commit](https://github.com/nearform/udaru/pull/444) - **Breaking change**: 404 not found on endpoint /authorization/users/${userId}/teams if user does not exist [commit](https://github.com/nearform/udaru/pull/444) -- SQL module extracted and placed in own npm module (https://www.npmjs.com/package/@nearform/sql) +- SQL module extracted and placed in own npm module ([@nearform/sql](https://www.npmjs.com/package/@nearform/sql)) ## 4.1.0 - March 12, 2018 Features, enhancements: @@ -32,7 +32,7 @@ Features, enhancements: - Enhanced swagger documentation (better definition of models and other tidy ups) Fixes: -- Added fixes on the get user teams endpoint [commit](https://github.com/nearform/udaru/pull/478 and https://github.com/nearform/udaru/pull/454) +- Added fixes on the get user teams endpoint [commit](https://github.com/nearform/udaru/pull/478) and [commit](https://github.com/nearform/udaru/pull/454) - Added fix for policy validation (enforce allow|deny on effect) - Added fix for issue 450 (invalid teams payload) diff --git a/README.md b/README.md index 179826e4..ae0030a2 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This repository is home to Udaru's three main modules: ## License -Copyright nearForm Ltd 2017-2018. Licensed under [MIT][license]. +Copyright nearForm Ltd 2017-2018. Licensed under [MIT license](https://choosealicense.com/licenses/mit). [travis-badge]: https://travis-ci.org/nearform/udaru.svg?branch=master diff --git a/docs/example.md b/docs/example.md index 869a9b75..86079d8d 100644 --- a/docs/example.md +++ b/docs/example.md @@ -290,7 +290,7 @@ curl -X GET --header 'Accept: application/json' --header 'authorization: ROOTid' ## Teams -Now let's add some teams; lets create a `Justice Leage` team that has the following sub teams: `Amazons`, `Aliens`, `Atlantis` (yep, they do exist: https://en.wikipedia.org/wiki/Justice_Leagues) +Now let's add some teams; lets create a `Justice Leage` team that has the following sub teams: `Amazons`, `Aliens`, `Atlantis` (yep, they do exist: [Justice_Leagues](https://en.wikipedia.org/wiki/Justice_Leagues)) Frist, let's list teams to make sure we don't already have any: diff --git a/packages/udaru-hapi-plugin/package.json b/packages/udaru-hapi-plugin/package.json index 1ea7aeb5..95cd74ee 100644 --- a/packages/udaru-hapi-plugin/package.json +++ b/packages/udaru-hapi-plugin/package.json @@ -45,7 +45,6 @@ }, "dependencies": { "@nearform/udaru-core": "^5.0.0", - "async": "^2.6.0", "boom": "^7.2.0", "hoek": "^5.0.3", "joi": "^13.1.2", diff --git a/packages/udaru-hapi-server/security/runner.js b/packages/udaru-hapi-server/security/runner.js index 3664f6a3..2ede3e27 100644 --- a/packages/udaru-hapi-server/security/runner.js +++ b/packages/udaru-hapi-server/security/runner.js @@ -5,8 +5,8 @@ const spawn = require('child_process').spawn const exec = require('child_process').exec const path = require('path') const source = path.join(__dirname, 'fixtures/injection-endpoints.json') -const async = require('async') const chalk = require('chalk') +const hapi = spawn('node', [path.join(__dirname, '../start.js')]) const endpoints = jsonfile.readFileSync(source, { throws: false }) @@ -16,114 +16,123 @@ if (!endpoints) { } function findPython2 (pythonCommand, done) { - return exec(`${pythonCommand} --version`, function (err, stdout, stderr) { - if (err) { - return done(err) - } + return new Promise((resolve, reject) => { + exec(`${pythonCommand} --version`, function (_err, stdout, stderr) { + if (stderr.indexOf('Python 2.') >= 0) { + console.log(chalk.green(`'${pythonCommand}' is a valid Python2 ✔️`)) + return resolve(pythonCommand) + } - if (stderr.indexOf('Python 2.') >= 0) { - console.log(chalk.green(`'${pythonCommand}' is a valid Python2 ✔️`)) - return done(null, pythonCommand) - } - return done(null, false) + resolve(false) + }) }) } -function executeMap (command, config, urlDescription, done) { +function executeMap (command, config, urlDescription) { console.log('Python command that will be used:', command) - const params = [ - `./node_modules/sqlmap/sqlmap.py`, - `--url=${urlDescription.url}`, - `--method=${urlDescription.method}`, - `--headers=${urlDescription.headers}`, - `--level=${config.level}`, - `--risk=${config.risk}`, - `--dbms=${config.dbms}`, - `--timeout=${config.timeout}`, - `-v`, `${config.verbose}`, - `--flush-session`, - `--batch` - ] - if (urlDescription.params) { - params.push(`-p`) - params.push(`${urlDescription.params}`) - } - if (urlDescription.data) { - params.push(`--data=${urlDescription.data}`) - } - - console.log(chalk.green('executing sqlmap with: ', (['' + command].concat(params)).join(' '))) - - const sql = spawn(command, params) - let vulnerabilities = false - - sql.stdout.on('data', (data) => { - if (data.length > 1) { - console.log(`sqlmap: ${data}`) + return new Promise((resolve, reject) => { + const params = [ + `./node_modules/sqlmap/sqlmap.py`, + `--url=${urlDescription.url}`, + `--method=${urlDescription.method}`, + `--headers=${urlDescription.headers}`, + `--level=${config.level}`, + `--risk=${config.risk}`, + `--dbms=${config.dbms}`, + `--timeout=${config.timeout}`, + `-v`, `${config.verbose}`, + `--flush-session`, + `--batch` + ] + if (urlDescription.params) { + params.push(`-p`) + params.push(`${urlDescription.params}`) } - if (data.indexOf('identified the following injection') >= 0) { - vulnerabilities = true + if (urlDescription.data) { + params.push(`--data=${urlDescription.data}`) } - }) - sql.stderr.on('data', (data) => { - done(data) - }) + console.log(chalk.green('executing sqlmap with: ', (['' + command].concat(params)).join(' '))) - sql.on('error', (error) => { - console.error(chalk.red(error)) - done(new Error('failed to start child process')) - }) + const sql = spawn(command, params) + let vulnerabilities = false - sql.on('close', (code) => { - console.log(chalk.green(`child process exited with code ${code}\n`)) - done(null, vulnerabilities) - }) -} + sql.stdout.on('data', (data) => { + if (data.length > 1) { + console.log(`sqlmap: ${data}`) + } + if (data.indexOf('identified the following injection') >= 0) { + vulnerabilities = true + } + }) -const hapi = spawn('node', ['packages/udaru-hapi-server/start.js']) + sql.stderr.on('data', (data) => { + reject(data) + }) -async.detect(['python2', 'python'], findPython2, function (err, python) { - if (err) { - return console.error(chalk.red(err)) - } + sql.on('error', (error) => { + console.error(chalk.red(error)) + reject(new Error('failed to start child process')) + }) - hapi.stdout.once('data', (data) => { - console.log(chalk.green(`hapi: ${data}`)) + sql.on('close', (code) => { + console.log(chalk.green(`child process exited with code ${code}\n`)) + resolve(vulnerabilities) + }) + }) +} - async.everySeries(endpoints.urls, (urlDescription, done) => { - executeMap(python, endpoints, urlDescription, (err, vulnerabilities) => { - if (err) { - console.error(chalk.red(err)) - return done(err, false) +async function runner () { + try { + const pythons = await Promise.all([ + findPython2('python2'), + findPython2('python') + ]) + + const python = pythons.find(f => f) + + hapi.stdout.once('data', async (data) => { + console.log(chalk.green(`hapi: ${data}`)) + let vulnerabilities + let endpointError + + for (const urlDescription of endpoints.urls) { + try { + const v = await executeMap(python, endpoints, urlDescription) + + if (v) { + vulnerabilities = v + break + } + } catch (err) { + endpointError = err + break } - - done(null, !vulnerabilities) - }) - }, (err, result) => { - if (err) { - console.error(chalk.red(err)) - return process.exit(1) } - console.log('\n\n') - hapi.kill() - if (result) { - console.log(chalk.green('no injection vulnerabilities found\n\n`')) - return process.exit(0) - } else { + if (endpointError) { + console.error(chalk.red(endpointError)) + } else if (vulnerabilities) { console.error(chalk.red('[CRITICAL] FOUND injection vulnerabilities\n\n')) - return process.exit(1) + } else { + console.log(chalk.green('no injection vulnerabilities found\n\n`')) } + + hapi.kill() + return process.exit(endpointError || vulnerabilities ? 1 : 0) }) - }) - hapi.stderr.on('data', (data) => { - console.error(chalk.red(`stderr: ${data}`)) - }) + hapi.stderr.on('data', (data) => { + console.error(chalk.red(`stderr: ${data}`)) + }) - hapi.on('close', (code) => { - console.log(chalk.green(`child process exited with code ${code}`)) - }) -}) + hapi.on('close', (code) => { + console.log(chalk.green(`child process exited with code ${code}`)) + }) + } catch (err) { + console.error(chalk.red(err)) + } +} + +runner().catch(console.error)