Secure Distributed Programming with Object-capabilities in JavaScript
description
Transcript of Secure Distributed Programming with Object-capabilities in JavaScript
Secure Distributed Programming with Object-capabilities in JavaScript
Mark S. Miller and the Cajadores
Overview
Why object-capability (ocap) security?Local ocap security in JavaScriptFlexible secure mobile codeDistributed crypto-caps in JavaScriptSecure distributed object programming
Early Choice. Late Despair
ACLs and OCaps start in mid ‘60s.ACLs: “Who is making this request?”OCaps: “Is this request authorized?”
‘70s: Industry took ACL fork in road.‘90s to present: Rise of Malware
A Very Powerful Program
A Very Powerful Program
This program can delete any file you can.
Original Web
Server
Server
Frame
Frame
Browser
Link/Form GET/POST
New Page
Link/Form GET/POST
New Page
Ajax = Mobile code + async msgs
Server
Server
Frame
Frame
Browser
XHR GET/POST
XHR Response
XHR GET/POST
XHR Response
Web services
Kludging Towards Distributed Objects
Server
Server
Frame
Frame
Browser
XHR GET/POST
XHR Response, Comet
XHR GET/POST
XHR Response, Comet
Web servicesJSONPFragment
tricks
A Web of Distributed Objects
Server
Server
Frame
Frame
Browser
XHR GET/POST
XHR Response, SSE
XHR GET/POST
XHR Response, SSE
Web servicesCross-Origin XHRwith UMP
postMessage
A Web of Distributed Objects
Mobile messages, code, objects, references
A Web of Distributed Objects
A Web of Distributed Objects
A Web of Distributed Objects
A Very Powerful Email Message
A Very Powerful Email Message<html> <head> <title>Basic Mashup</title> <script> function animate(id) { var element = document.getElementById(id); var textNode = element.childNodes[0]; var text = textNode.data; var reverse = false; element.onclick = function() { reverse = !reverse; }; setInterval(function() { textNode.data = text = reverse ? text.substring(1) + text[0] : text[text.length-1] + text.substring(0, text.length-1); }, 100); }</script> </head> <body onload="animate('target')"> <pre id="target">Hello Programmable World! </pre></body> </html>
Active Content: Mobile Code as Media
<html> <head> <title>Basic Mashup</title> <script> function animate(id) { var element = document.getElementById(id); var textNode = element.childNodes[0]; var text = textNode.data; var reverse = false; element.onclick = function() { reverse = !reverse; }; setInterval(function() { textNode.data = text = reverse ? text.substring(1) + text[0] : text[text.length-1] + text.substring(0, text.length-1); }, 100); }</script> </head> <body onload="animate('target')"> <pre id="target">Hello Programmable World! </pre></body> </html>
The Road Not Taken
?
The Road Not Taken
?
The Road Not Taken
?
The Road Not Taken
? ?
Security as Extreme Modularity
Modularity: Avoid needless dependenciesSecurity: Avoid needless vulnerabilitiesVulnerability is a form of dependency
Modularity:Principle of info hiding - need to know
Security:Principle of least authority - need to do
Connectivity by…… Introduction
ref to Carolref to Bobdecides to share
… Parenthood… Endowment… Initial Conditions
Alice says: bob.foo(carol)
How might object Bob come to know object Carol?
OCaps: Small step from pure objects
Memory safety and encapsulation+ Effects only by using held references+ No powerful references by default
OCaps: Small step from pure objects
Memory safety and encapsulation+ Effects only by using held references+ No powerful references by default Reference graph ≡ Access graph Only connectivity begets connectivity Natural Least Authority OO expressiveness for security patterns
function makeCounter() { var count = 0; return { incr: function() { return ++count; }, decr: function() { return --count; } };}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
Objects as Closures in JavaScript
Objects as Closures in JavaScript
function makeCounter() { var count = 0; return { incr: function() { return ++count; }, decr: function() { return --count; } };}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
A record of closures hiding state is a fine representation of an
object of methods hiding instance vars
function makeCounter() { var count = 0; return { incr: function() { return ++count; }, decr: function() { return --count; } };}
• Scoping confusions• Encapsulation leaks• Pervasive mutability
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
Objects as Closures in EcmaScript 3
Defensive Objects in SES on ES5“use strict”;function makeCounter() { var count = 0; return def({ incr: function() { return ++count; }, decr: function() { return --count; } });}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
A tamper-proof record of lexical closures encapsulating
state is a defensive object
Turning EcmaScript 5 into SES
<script src=“initSES.js”></script>
Monkey patch away bad non-std behaviors
Remove non-whitelisted primordials Install leaky WeakMap emulation Make virtual global root Freeze whitelisted global variables• Replace eval & Function with safe
alternatives Freeze accessible primordials
No powerful references by default
Alice says: var bobSrc = //site B var carolSrc = //site C var bob = eval(bobSrc); var carol = eval(carolSrc);
bob
carol
Alice Bob
Carol
No powerful references by default
bob
carol
Alice
Bob and Carol are confined. Only Alice controls how they can interact or get more connected.
Bob
Carol
Alice says: var bobSrc = //site B var carolSrc = //site C var bob = eval(bobSrc); var carol = eval(carolSrc);
No powerful references by default
Alice says:bob
carol
Bob
Carol
Bob
Carol
bob
carol
counter
Only connectivity begets connectivity
Alice says: var counter = makeCounter(); bob(counter.incr); carol(counter.decr); bob = carol = null;countcountcount
incr
decr
Bob
Carol
bob
carol
counter
Only connectivity begets connectivity
Alice says: var counter = makeCounter(); bob(counter.incr); carol(counter.decr); bob = carol = null;countcountcount
incr
decr
Bob can only count up and see result. Carol only down.
Alice can only do both.
Bob
Carol
bob
carol
counter
Only connectivity begets connectivity
Alice says: var counter = makeCounter(); bob(counter.incr); carol(counter.decr); bob = carol = null;countcountcount
incr
decr
Express policy by the behavior of the objects you provide.
Dr. SESDistributed Resilient Secure
EcmaScript
Linguistic abstraction for safe messagingStretch reference graph between event loops &
machinesCrypto analog of memory safety
SES + Promise library + infix “!” syntax(“Q” Library usable today without “!” syntax)
Unguessable URLs as Crypto-Caps
https://www.example.com/app/#mhbqcmmva5ja3
How are secrets like object references?
Dr. SESDistributed Resilient Secure
EcmaScript
var result = bob.foo(carol); Local-only immediate callvar resultP = bobP ! foo(carol); Eventual send
Dr. SESDistributed Resilient Secure
EcmaScript
var result = bob.foo(carol); Local-only immediate callvar resultP = bobP ! foo(carol); Eventual sendvar result = bob.foo; Local-only immediate getvar resultP = bobP ! foo; Eventual get
Dr. SESDistributed Resilient Secure
EcmaScript
var resultP = bobP ! foo(carol); Eventual send
var resultP = bobP ! foo; Eventual get
Dr. SESDistributed Resilient Secure
EcmaScript
var resultP = bobP ! foo(carol); Eventual sendvar resultP = bobP ! foo; Eventual get
Q(resultP).when(function(result) { …result…}, function (ex) { …ex…});
Register for notification
Dr. SESDistributed Resilient Secure
EcmaScript
var resultP = bobP ! foo(carol); Eventual sendvar resultP = bobP ! foo; Eventual get
Q(resultP).when(function(result) { …result…}, function (ex) { …ex…});
xhr.onreadystatechange = …
Async object ops as JSON/REST ops
var resultP = bobP ! foo(carol); POST https://…q=foo {…}var resultP = bobP ! foo; GET https://…q=foo
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
buy
$90$10
return Q(paymentP).when(function(p) { return Q(myPurse ! deposit(10, p)).when(function(_) { return good; }, …
Money as “factorial” of secure coding
function makeMint() { var amp = WeakMap(); return function mint(balance) { var purse = def({ getBalance: function() { return balance; }, makePurse: function() { return mint(0); }, deposit: function(amount, src) { Nat(balance + amount); amp.get(src)(Nat(amount)); balance += amount; } }); function decr(amount) { balance = Nat(balance – amount); } amp.set(purse, decr); return purse; }}
No explicit crypto
Alice Bobbuy
makeMint
mintmintpurse decrpurse decrpurse decr
balance
amp
Causeway Distributed Debugger
Sourcilloscope
Causeway Distributed Debugger
Causality Grid
Causeway Distributed Debugger
Causality Grid at Scale
Authorization by Designation
CapDesk
Authorization by Designation
Belay
Questions?
Why object-capability (ocap) security?Local ocap security in JavaScriptFlexible secure mobile codeDistributed crypto-caps in JavaScriptSecure distributed programming
How to lose an arms race
How to lose an arms race
Doomed to never ending tinkering?
Doomed to never ending tinkering?
Identity-centric accessHTTP auth infoclient side certs
script, img, fragment holes
Cookiesaugments attacker’s authority
confused deputiesOrigin: header “fix”
subtler confused deputies
Doomed to never ending tinkering?
Identity-centric accessHTTP auth infoclient side certs
script, img, fragment holes
Cookiesaugments attacker’s authority
confused deputiesOrigin: header “fix”
subtler confused deputies
Identity-centric vs. Authorization-centric
Running ES5 & SES on old browsers
Future objects on old browsers
OCaps in JavaScript
Caja on EcmaScript 3One of the hardest oo languages to secure.Complex server-side translator. Some runtime
overhead.Successful large scale deployment.
Secure EcmaScript (SES) on EcmaScript 5One of the easiest oo languages to secure.<script src=“initSES.js”></script>Simple client-side init and verifier. No runtime
overhead.
Safe Mobile Messages: Uniform XHR
As in “Uniform Resource Locator”Designation (ideally) independent of requestor
contextIgnore browser’s “helpful” extras
HTTP Auth info, client side certs, cookies, Origin: header,
Like IP address: use only for forensics & emergencies
Authorize based only on payloadHTTPS URL or request body – info the requestor
knowsWaive response “protection”
Access-Control-Allow-Origin: *
The other half of the object revolutionProtect object from world Protect world from objectResponsibility driven design
Authority driven design
Avoid needless coupling Avoid needless vulnerability
Information hiding Principle of Least AuthorityAvoid global variables Forbid mutable static stateProcedural, data, control, …
…, and access abstractions
Patterns and frameworks Patterns of safe cooperation
Say what you mean Mean only what you say
Bringing Object-orientationto Security Programming
Mark S. Miller and the Cajadores
Overview: Bottom up by Layers
Composing Networks of GamesSmart Contracts as GamesDimensions & Taxonomy of Electronic
RightsPatterns of Safe CooperationAccess Abstractions and CompositionsObject-capabilities (ocaps)Objects, References, Messages
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial
ConditionsHow might object Bob come to know of object
Carol?
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial
Conditions
Alice says: bob.foo(carol)
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial
Conditions
Alice says: bob.foo(carol)
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial
Conditions
Alice says: bob.foo(carol)
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial Conditions
Alice says: bob.foo(carol)
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial Conditions
Alice says: bob.foo(carol)
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial Conditions
Bob says: var carol = { ... };
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial Conditions
Alice says: var bob = { ... carol ... };
How do I designate thee?by Introduction
ref to Carolref to Bobdecides to share
by Parenthoodby Endowmentby Initial Conditions
At t0:
OCaps: Small step from pure objects
Memory safety and encapsulation+ Effects only by using held references+ No powerful references by default
OCaps: Small step from pure objects
Memory safety and encapsulation+ Effects only by using held references+ No powerful references by default Reference graph ≡ Access graph Only connectivity begets connectivity OO expressiveness for security patterns
Objects as Closures
function makeCounter() { var count = 0; return { incr: function() { return ++count; }, decr: function() { return --count; } };}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
Objects as Closures
function makeCounter() { var count = 0; return { incr: function() { return ++count; }, decr: function() { return --count; } };}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
A record of closures hiding state is a fine representation of an
object of methods hiding instance vars
Objects as Closures in SES on ES5
“use strict”;function makeCounter() { var count = 0; return def({ incr: function() { return ++count; }, decr: function() { return --count; } });}
makeCounter
count
incr
decr
count
incr
decr
count
incr
decr
A tamper-proof record of lexical closures encapsulating
state is a defensive object
Turning EcmaScript 5 into SES
<script src=“initSES.js”></script>
Monkey patch away bad non-std behaviors
Remove non-whitelisted primordials Install leaky WeakMap emulation Make virtual global root Freeze whitelisted global variables• Replace eval & Function with safe
alternatives Freeze accessible primordials
Revocable Function Forwarderfunction makeFnCaretaker(target) { return def({ wrapper: function(…args) { return target(…args); }, revoke: function() { target = null; } });}
makeCaretaker
target
wrapperrevoke
target
wrapperrevoke
target
wrapperrevoke
target
wrapperrevoke
target
wrapperrevoke
target
wrapperrevoke
Alice
Unconditional AccessAlice says: bob.foo(carol);
Bob
Carol
foo
Grants Bob full access to Carol forever
Alice
Revocability ≡ Temporal attenuation
Alice says: var ct = makeCaretaker(carol); bob.foo(ct.wrapper);
target
wrapperrevoke
Bob
Carol
foo
Alice
Revocability ≡ Temporal attenuation
Alice says: var ct = makeCaretaker(carol); bob.foo(ct.wrapper); //…
target
wrapperrevoke
Bob
Carol
Alice Alice says: var ct = makeCaretaker(carol); bob.foo(ct.wrapper); //… ct.revoke();
target
wrapperrevoke
Bob
Carol
Revocability ≡ Temporal attenuation
Alice Alice says: var ct = makeCaretaker(carol); bob.foo(ct.wrapper); //… ct.revoke();
target
wrapperrevoke
Bob
Carol
Revocability ≡ Temporal attenuation
Alice
Attenuators ≡ Access Abstractions
Alice says: var ct = makeCaretaker(carol); bob.foo(ct.wrapper);
Bob
CarolExpress security policy by the behavior of the objects you provide
foo
Abstractions extend vocabularyPrimitives Abstraction Forms Extended
Vocabulary+, ., [] procedural
abstractionfoo(bar, baz), …
int, struct, array data abstraction Point, Window, …
if, while, switch control abstraction addListener, visitor, …
points-to access abstraction caretaker, membrane, …
Alice
Membranes: Transitive Interposition
function makeFnMembrane(target) { var enabled = true; function wrap(wrapped) { if (wrapped !== Object(wrapped)) { return wrapped; } return function(…args) { if (!enabled) { throw new Error(“revoked”); } return wrap(wrapped(…args.map(wrap)); } } return def({ wrapper: wrap(target), revoke: function() { enabled = false; } });}
Bob
Carol
bar
Dave
Attenuators Compose
function makeROFile(file) { return def({ read: file.read, getLength: file.getLength });}var rorFile = makeROFile(revocableFile);
No powerful references by default
Alice says: var bobSrc = //site B var carolSrc = //site C var bob = eval(bobSrc); var carol = eval(carolSrc);
bob
carol
Alice Bob
Carol
No powerful references by default
bob
carol
Alice
Bob and Carol are confined. Only Alice controls how they can interact or get more connected.
Bob
Carol
Alice says: var bobSrc = //site B var carolSrc = //site C var bob = eval(bobSrc); var carol = eval(carolSrc);
No powerful references by default
Alice says:bob
carol
Bob
Carol
Bob
Carol
bob
carol
counter
Only connectivity begets connectivity
Alice says: var counter = makeCounter(); bob(counter.incr); carol(counter.decr); bob = carol = null;countcountcount
incr
decr
Bob
Carol
bob
carol
counter
Only connectivity begets connectivity
Alice says: var counter = makeCounter(); bob(counter.incr); carol(counter.decr); bob = carol = null;countcountcount
incr
decr
Bob can only count up and see result. Carol only down.Alice can only do both.
Membrane eval → compartment
var compartment = makeMembrane(eval);
var vbob = compartment.wrapper(bobSrc);
Alice Bob
Membrane eval → compartment
var compartment = makeMembrane(eval);
var vbob = compartment.wrapper(bobSrc);
//…
Alice Bob
Membrane eval → compartment
var compartment = makeMembrane(eval);
var vbob = compartment.wrapper(bobSrc);
//…compartment.revoke();
Alice Bob GC
Composing Authority
∪?
Usuallyintersection
Subset
Rights Amplification
≥∪∪
Authority conditional on other possessions.
Enables more expressive power.
Rights Amplificationfunction makeBrand() { var amp = WeakMap(); return def({ seal: function(payload) { var box = def({}); amp.set(box, payload); return box; }, unseal: function(box) { return amp.get(box); } });}
Alice Bobfoo
makeBrand
amp
seal unsealseal unseal
payload
box
payload
box
payload
boxamp
Rights Amplificationfunction makeBrand() { var amp = WeakMap(); return def({ seal: function(payload) { var box = def({}); amp.set(box, payload); return box; }, unseal: function(box) { return amp.get(box); } });}
Crypto patterns without cryptomakeBrand() generate key
pairseal method encryption key
unseal method decryption key
payload plaintext
box cyphertext
Distributed Secure Currency
$100 $200
Distributed Secure Currency
$100 $200
var paymentP = myPurse ! makePurse();
Distributed Secure Currency
$100 $200
var paymentP = myPurse ! makePurse();
makePurse
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);
deposit
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);
$90$10
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
$90$10
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
buy
$90$10
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
$90$10
return Q(paymentP).when(function(p) {
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
$90$10
return Q(paymentP).when(function(p) { return Q(myPurse ! deposit(10, p)).when(function(_) {
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
$90$10
deposit
return Q(paymentP).when(function(p) { return Q(myPurse ! deposit(10, p)).when(function(_) {
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
$90 $210
return Q(paymentP).when(function(p) { return Q(myPurse ! deposit(10, p)).when(function(_) {
Distributed Secure Currency
$100 $0
$200
var paymentP = myPurse ! makePurse();paymentP ! deposit(10, myPurse);var goodP = bobP ! buy(desc, paymentP);
return Q(paymentP).when(function(p) { return Q(myPurse ! deposit(10, p)).when(function(_) { return good; }, …
$90 $210
Money as “factorial” of secure coding
function makeMint() { var amp = WeakMap(); return function mint(balance) { var purse = def({ getBalance: function() { return balance; }, makePurse: function() { return mint(0); }, deposit: function(amount, src) { Nat(balance + amount); amp.get(src)(Nat(amount)); balance += amount; } }); function decr(amount) { balance = Nat(balance – amount); } amp.set(purse, decr); return purse; }}
No explicit crypto
Alice Bobbuy
makeMint
mintmintpurse decrpurse decrpurse decr
balance
amp
Dimensions of Electronic Rights
Object reference• Shared• Specific• Opaque• Exercisable
Money• Exclusive• Fungible• Assayable• Symbolic
Smart Contracts as Board Games
NegotiationDesign a game both expect to win
Players make moves, but only “legal” ones
Move changes state of boardBoard-state determines move “legality”
ERights are “pieces” placed on boardGame escrows pieces, Pieces/ERights released only by play
A Simple Exchange Game
The Five Players
A Covered Call Option
Composing Networks of Games
Questions?
Composing Networks of GamesSmart Contracts as GamesDimensions & Taxonomy of Electronic
RightsPatterns of Safe CooperationAccess Abstractions and CompositionsObject-capabilities (ocaps)Objects, References, Messages