Meteor Meets Mallory

Post on 10-May-2015

2,633 views 0 download

Tags:

description

devshop talk 7/25/13

transcript

Meteor meets Mallory*Emily Stark, Meteor core developeremily@meteor.com

* Mallory is usually the name of the bad guy in crypto/security stuff

Meteor security model and best

practices

Outline

1. Meteor security principles

2. Cross-site scripting

3. Mongo injections

Meteor security principles

Secure design principles

○ Data and code are separate

○ Easy to reason about client/server boundary

○ Stateful connections that must be deliberately authenticated

Securely structuring your app

○ Server code is trusted, client code is not○ server/ or Meteor.settings for secrets○ Meteor.isServer doesn't make code private

○ Use publications and allow/deny to lock down database API○ Allow/deny rules not applied to server code

Cross-site scripting

Cross-site scripting (XSS)

Cross-site scripting (XSS)

Meteor foils some attacks

< > ' " ` &

&lt; &gt; &#x27; &quot; &#x60; &amp;

when inside {{ }}

(packages/handlebars/evaluate-handlebars.js)

But not all

<a href="{{ userWebsite }}"> {{ username }}'s website</a>

URL sanitization

<a href="javascript:alert(localStorage)"> {{ username }}'s website</a>

URL sanitization

<a href="javascript:alert(localStorage)"> {{ username }}'s website</a>

Can you execute any damaging Javascript when quotes are escaped?

URL sanitization

<a href="javascript:eval(String.fromCharCode(77, 101, ...))"> {{ username }}'s website</a>

CSS sanitization<div style="background-color:{{ usersFavoriteColor }}"></div>

CSS sanitization<div style="background-color:expression(alert(localStorage))"></div>

Sanitize untrusted URLs and CSS

○ Don't try to filter out "javascript:", "expression", etc.

○ Do strict checking: urls start with http, css values come from a list of safe values

○ Use Content Security PolicyEx: Content-Security-Policy: default-src 'self'

Mongo injections

Mongo injections

Meteor.methods({ getUser: function(user, pwd) { return Users.findOne({ username: user, password: pwd }); }});

user: "Alice"pwd: {$ne: "foo"}

Using check

Meteor.methods({ getUser: function (user, pwd) { check(user, String); check(pwd, String); return Users.findOne({ user: user, password: pwd }); }});

check is versatile

check(usernames, [String])

check(profile, { admin: Boolean, location: Match.Optional(String)});

check(age, Match.OneOf(String, Number))

Using audit-argument-checks

Meteor.methods({ insertName: function (name) { MyCollection.insert({ name: name

}); console.log("Inserted", {name: name});

}});

insertName({ foo: "bar"})

Using audit-argument-checks

Inserted {"name": {"foo": "bar"}}insertName({

foo: "bar"})

Using audit-argument-checks

meteor add audit-argument-checksinsertName({

foo: "bar"})

Using audit-argument-checks

Inserted {"name": {"foo": "bar"}}Exception while invoking method 'insertName'Error: Did not check() all arguments during call to 'insertName'

insertName({ foo: "bar"})

What was that Meteor 0.6.4.1 release all about?

Meteor.methods({ saveUser: function(profile) { delete profile.admin; Users.insert(profile); }});

<malicious input>

{"admin": "true!", "\x01...": null, ...}

Conclusion

○ Meteor security design principles○ Securing boundary between client and server○ Data/code separation

○ Some attacks to watch out for○ Always validate untrusted user input

○ security-resources.meteor.com

Questions?