THE NODE.JS HIGHWAY: ATTACKS AT FULL THROTTLE Susan St.Clair, - - PowerPoint PPT Presentation

the
SMART_READER_LITE
LIVE PREVIEW

THE NODE.JS HIGHWAY: ATTACKS AT FULL THROTTLE Susan St.Clair, - - PowerPoint PPT Presentation

THE NODE.JS HIGHWAY: ATTACKS AT FULL THROTTLE Susan St.Clair, Solutions Architect Checkmarx Agenda Agenda Architecture DoS Weak Crypto JSON SQLi Re-DoS App Re-Routing Single Thread Architecture - Event Loop


slide-1
SLIDE 1

THE NODE.JS HIGHWAY: ATTACKS AT FULL THROTTLE

Susan St.Clair, Solutions Architect Checkmarx

slide-2
SLIDE 2

Agenda

  • Architecture
  • DoS
  • Weak Crypto
  • JSON “SQLi”
  • Re-DoS
  • App Re-Routing

Agenda

slide-3
SLIDE 3

Single Thread Architecture - Event Loop

Event Queue

Network Database File System Register Callback

Operation Complete Trigger Callback Event Loop Single Thread

slide-4
SLIDE 4

Single Threaded Event Loop Event handler

Code.DanYork.Com

slide-5
SLIDE 5
  • CPU intensive applications
  • Complex business logic that

requires lots of calculations

  • I/O intensive applications
  • DB queries
  • UI intensive applications

(many webapps)

What’s it Good for?

slide-6
SLIDE 6

Function sum (p) for (i=1;i<=p;++i) { f=f+i; }

Denial of Service (DoS)

slide-7
SLIDE 7

DoS DEMO

slide-8
SLIDE 8

Weak Crypto

slide-9
SLIDE 9

Seed State0[0,1] State1[0,1] State2[0,1] State3[0,1] Staten[0,1] Random0 Random1 Random2 Randomn Random3

Check out Amit Klein’s research on the subject http://dl.packetstormsecurity.net/paper s/general/Google_Chrome_3.0_Beta_M ath.random_vulnerability.pdf

V8 PRNG is known to be weak

slide-10
SLIDE 10

Given 3 “random” new passwords – we will be able to tell all future ones

  • First, we need to “reverse” the MD5 for 3 passwords to their
  • riginal “random” float number
  • Then, we need to compute the “state” variable to get the 4th consecutive

value.

V8’s Default PRNG

slide-11
SLIDE 11
  • Given 3 consecutive random numbers, the values of state[0] and state[1] can be

inferred – hence all future values can be known in advance.

But

  • In browsers, each tab has its own set of “state” variables. That’s one of the

reasons this issue is treated as low-severity

But

  • In node.js, all users are running within the same context. Each user can tell what

are the values of the global “state” variables.

V8’s Default PRNG – So What?!

slide-12
SLIDE 12

Step 1

Register FakeUser1 Register FakeUser2 Register FakeUser3 FakeUser1 Password FakeUser2 Password FakeUser3 Password Reminder: Password = MD5(random())

slide-13
SLIDE 13

Step2

Register FakeUser1 Register FakeUser2 Register FakeUser3 FakeUser1 Password FakeUser2 Password FakeUser3 Password Reminder: Password = MD5(random())

slide-14
SLIDE 14

Step3

FakeUser1 – Clear Random FakeUser1 Password FakeUser2 Password FakeUser3 Password Reminder: Password = MD5(random()) FakeUser2 – Clear Random FakeUser3 – Clear Random

slide-15
SLIDE 15

Step 4

FakeUser1 – Clear Random FakeUser1 Password FakeUser2 Password FakeUser3 Password Reminder: Password = MD5(random()) FakeUser2 – Clear Random FakeUser3 – Clear Random RealUser1 – Future Password

slide-16
SLIDE 16

PASSWORD GUESSING DEMO

slide-17
SLIDE 17

Architecture

  • MongoDB
  • Document-oriented

database.

  • Classified as NoSQL
  • Doesn’t use the traditional

table-based structure

  • Stores JSON documents in

its dynamic schemas.

slide-18
SLIDE 18

Mongo Queries

db.products.insert( { item: "card", qty : 15 } ) db.products.insert( { name: “elephant", size: 1700 } ) db.products.insert db.products.find db.products.find()

  • Find all of them

db.products.find( { qty: 15 })

  • Find based on equality

db.products.find( { qty: { $gt: 25 } } ) - Find based on criteria Data is inserted and stored as JSON Queries as described using JSON var obj;

  • bj.qty=15;

db.products.find(obj)

slide-19
SLIDE 19

name = req.query.username; pass = req.query.password; db.users.find({username: name, password: pass}); … If exists ….

Security – User Supplied Data

  • Can you spot the vulnerabilities in the code?
  • Traditional SQL:
  • JSON:
slide-20
SLIDE 20

name = req.query.username; pass = req.query.password; db.users.find({username: name, password: pass});

Security – User Supplied Data

What if we use the following query:

db.users.find({username: {$gt, “a”}, password : {$gt, “a”}}

slide-21
SLIDE 21

JSON-based SQL Injection

  • Node.JS, being a JSON based language, can accept

JSON values for the .find method:

  • A user can bypass it by sending

http://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb.html

http:///server/page?user[$gt]=a&pass[$gt]=a

slide-22
SLIDE 22

PASSWORD BYPASS DEMO

slide-23
SLIDE 23

JSON-base SQL Injection Defense

You can use the following: Then

db.users.find({username: username}); bcrypt.compare(candidatePassword, password, cb);

slide-24
SLIDE 24

JSON-based SQL Injection

This can lead to Regular Expression Denial of Service through the {“username”: {“$regex”: “……..}}

db.users.find({username: username});

slide-25
SLIDE 25

JSON-based NoSQL Injection

  • So always validate the input length, structure and

permitted characters

  • Remembering that Node.js is highly sensitive to

CPU-intensive tasks, and there’s a single thread for user-code – ReDoS is really bad

slide-26
SLIDE 26
  • Recap

– With Node.js there is no web server – Traditional web-servers (IIS, Tomcat) have strict separation between the application, the server, and the OS

  • Run-time Server Poisoning

– Node.js server runs in a single thread; if corrupted, server behavior can be altered – Alterations will last for all subsequent requests.

NodeJS as a Webserver

slide-27
SLIDE 27
  • EVALuates a string.

– At the context of the current applicative user within the context of the application. – In .net/java, eval can’t control the web server or other users’ threads

  • Node.js is server-less so corrupting “current” thread, harms all

users

‘Evil EVAL’

slide-28
SLIDE 28

Express.js (Wikipedia) :

“a Node.js web application framework, designed for building single-page, multi-page, and hybrid web applications.”

app.get('/add', function(req,res) { var data=req.query; return res.render('index', {message: eval(req.query.a + '+' + req.query.b)}); } http://server/add?a=3&b=8

11 (!)

Routing

Express

slide-29
SLIDE 29

Maintained in an ordered list (although called “stack” by express).

Routing Stack /Add /Remove

/page/:id

/ab*d

Func1() Func2() Func3() Func4()

  • The stack is accessible in runtime: app._router.stack

Server Routing

slide-30
SLIDE 30

Run-time Server Poisoning

  • ‘Stack’ is accessible at run-time (read &

write!)

  • Replace existing routing with new one

– Affects all users connecting to system with NO apparent impact to the source code

slide-31
SLIDE 31

Routing Stack /Remove

/page/:id

/ab*d

Func1() Func2() Func3() Func4() /Add /Add Func5()

app._router.stack.splice(3,1); // remove routing entry app.get('/add',function(req, res) // add new routing { return res.render('index', {message: req.query.a * req.query.b} ); });

Server Routing Change

slide-32
SLIDE 32

Routing Stack

slide-33
SLIDE 33