Title: a tool for building securely extensible applications
1Auditors
- a tool for building securely extensible
applications - Caution Work in Progress
- Mark S. Miller
- Virus Safe Computing InitiativeHewlett Packard
Labs
2Thanks to
- Tyler Close, Alan Karp, Adrian Mettler, Chip
Morningstar, Kevin Reid, Terry Stanley, Marc
Stiegler, E. Dean Tribble, David Wagner, Bryce
Zooko Wilcox-O'Hearn, Ka-Ping Yee. - Joe-E is by Adrian Mettler David Wagner
- The e-lang communityHewlett Packard LabsU.C.
BerkeleyJohns Hopkins UniversityCombex
Inc.Electric Communities
3Securely Extensible Applications
- Emacs, AutoCAD, Firefox
- Most value from 3rd party extensions
- Old dream of active content
- Richer user experience
- Microsoft spent gt1B adding scripting to their
apps - Wasted No sane person dares enable macros
- Users safety also depends on OS security
- Provides inter-process protection
- Protection mechanisms not portable across OSes
- Extensions need intra-process protection
- Tight integration with app no kernel crossings
- Complimentary to OS security
4Securely Extensible Applications
- Memory Type Safe Languages Lisp, VB, Python
- Localize accidental harm no help against malice
- Restricted Authority Java Sandbox, Javascript
- No harm, little good untrusted applets
- Least Authority Object-Capability Languages
- Actions within bounds untrusted renderers,
attachments, plugins - Behaves as expected ???
- Provably Correct Conforms to formal
specification - Ultimate Answer but still rocket science after
37 years - Some progress Proof Carrying Code, Dependent
Types - Is best the enemy of good?
5Background Object-Capabilities
Alice says bob.foo(carol)
- Inter-object causality only by sending messages
on references - Reference graph Access graph
- Only connectivity begets connectivity.
6Object-Capability Languages
- Gedanken (1970), Actors (1973),
- Eden (1985), Vulcan (1986),
- Emerald (1987), Trusty Scheme (1992),
- W7 (1995), Joule (1996),
- Original-E (1997), E (1998),
- J-Kernel (1999), Oz-E (2005),
- Joe-E (2005), CaPerl (2006),
- Emily (2006)
7Example Alice pays Bob
def payment myPurse lt- makePurse() payment lt-
deposit(10, myPurse) bob lt- buy(..., payment)
when (payment) -gt when (myPurse lt-
deposit(10, payment)) -gt ... dispense
value
buy
makePurse
mint
10
namesealerunsealer
100
200
90
210
8Distributed Secure Money in E
- def makeMint(name String)
- def sealer, unsealer makeBrandPair(name)
- def mint
- to makePurse(var balance (int gt 0))
- def decr(amount (0..balance))
- balance - amount
-
- def purse
- to getBalance() return balance
- to makePurse() return
mint.makePurse(0) - to getDecr() return
sealer.seal(decr) - to deposit(amount int, src)
- unsealer.unseal(src.getDecr())
(amount) - balance amount
-
- return purse
-
- return mint
No explicit crypto
9Why expect good behavior?specific..abstract
- Auto-authoritative answer point.getSize()
- Prior relationship y
- Particular object x y
- Particular code leverage type system
- Parameterized by data..trusted code..untrusted
code - T x if (x instanceof T) // where T is a
trusted final class - T x new T(evilObj) // x acts
well even if evilObj doesnt - ???
- Proof carrying code (PCC) passes proof checker
10Admission Controls onType Membership
- public final class String //
closed membershipString str // Can we
rely on str to act String-like? - public interface ComparableltTgt // open
membership /musttotal order/ //
yeah, right public int compareTo(T o)
sort(listOfComparables) // Can sort rely on
comparisons? - public interface Prompt extends Checked
// auditedPrompt p // Can
we rely on p to terminate?
11Admission Controls onType Membership
Checked
DeepFrozen
Auditor
Prompt
Matcher
PromptnessAuditor
PromptMatcher
EvilExtension
12Admission Controls onType Membership
- public interface Prompt extends Checked
Auditor MY_AUDITOR PromptnessAuditor.THE_ONE
public final class PromptnessAuditor implements
Auditor static public Auditor THE_ONE new
PromptnessAuditor() // design-rule check
that members must pass public boolean
audit(AST candidateSource)
// no general loops, recursion, I/O, locking
// calls only prior prompt things
13Applying for Membership
- public interface Matcher public interface
PromptMatcher extends Matcher, Prompt class
ExtendableApplication PromptMatcher
pm pm.match(str) // will we get
here? - class EvilExtension implements PromptMatcher
14Admitting an Extension
- public class AuditingLoader extends JoeELoader
protected Class findClass(String name)
// look up, compile, Joe-E-verify
name.java for // for each Checked
type it would implement if
(!checkedType.MY_AUDITOR.audit(ast))
throw AuditFailedException()
return super.findClass(name)
15Admitting an Extension
Checked
DeepFrozen
Auditor
Prompt
Matcher
PromptnessAuditor
PromptMatcher
EvilExtension
16A Goldilocks Solution
- To admit most prompt code, wed need proofs of
termination - Very general flexible, but impractically hard
- Could rely only on our own code to be prompt
- Easily safe, but too specific non extensible
- Could wrap with dynamic enforcer
- Runs matcher is separate thread, killed if
timeout exceeded - General, but only for dynamically enforceable
properties - Check for conformance to limited coding pattern
- A program with no loops is already done - Knuth
- Safe, practical, moderate extensibility
- Some help on our own code as well
17Some Other Useful Auditors
OpenState
OpenSource
Frozen
Transparent
Selfless
PassByCopy
DeepOpenState
DeepFrozen
DeepOpenSource
DeepTransparent
DeepSelfless
DeepPassByCopy
18Some Other Useful Auditors
- DeepFrozen transitively immutable
- All instance variables final, only of DeepFrozen
types - Shared access to a DeepFrozen does not enable
communication - DeepFrozenAuditor.audit deems Memoizer to be
DeepFrozen - Selfless no testable object identity
- x y forbidden
- Built-in special case requires global
enforcement - Selfless Frozen ? x is indistinguishable from a
copy of x - DeepPassByCopy transitively immutable
selfless - Also known as Data no more powerful than bits
- x is indistinguishable from unserialize(serialize(
x)) - Equiv x.equals(y), x.hashCode() behave
correctly - forms an equivalence class
19DeemingWouldnt pass. But trust me, its ok
- public interface MFunction extends DeepFrozen
Data run(EquivDeepFrozen arg)public class
Memoizer implements MFunction private final
Map myMem //
mutable map! private final MFunction myFun
public Memoizer(MFunction fun) myFun fun
public Data run(EquivDeepFrozen arg)
if (myMem.containsKey(arg)) return
myMem.get(arg) else
Data result myFun(arg)
myMem.put(arg, result)
// mutation! return result
20DeemingWouldnt pass. But trust me, its ok
- public final class DeepFrozenAuditor implements
Auditor static public Auditor THE_ONE new
DeepFrozenAuditor() // enhance design-rule
check that members must pass public boolean
audit(AST candidateSource) if ()
// if candidate is
Memoizer return true
// then deem it ok
// normal DeepFrozenAuditor checking
21Is good the enemy of best?Upward compatible
audit upgrade
- interface Prompt extends Checked
PromptnessAuditor
// as beforeclass PromptnessAuditor
implements Auditor // enhanced to deem
PCCTerminating as Promptinterface
PCCTerminating extends Prompt
PCCTerminatingAuditorclass
PCCTerminatingAuditor implements Auditor
// check asts termination proof against ast
22Is good the enemy of best?Upward compatible
audit upgrade
Checked
DeepFrozen
Auditor
Prompt
Matcher
PromptnessAuditor
PromptMatcher
EvilExtension
PCCTerminatingAuditor
PCCTerminating
Evil2
23Past, Related Future Work
- Past
- Similar object-capability patterns KeyKOS
Factory - Dynamically extensible auditors in E
- Fred Spiessens SCOLL (Safe Collaboration) model
checker - Related
- Soft Types, Higher Order Contracts, Hybrid Type
Checking - Natafly Minskys Law Governed Systems
- Gilead Brachas Pluggable Type Systems
- Oleg Kiselyovs Lightweight Dependent Types
- Future
- Auditing vs. Attestation
- Expand AST examination toolkit
- Write more interesting auditors
24Conclusions
- Next step after object-capability languages
- Admission control on type membership
- Design rules are too restrictive
- Loss of expressive power some safe programs
accepted - Accepting any untrusted code is still better than
just say no - Practical solution while waiting for proofs
- Most programmers learned by doing no formal
semantics - Programmers who could not write a formal spec can
write safe design rules others can follow. - Programmers who could not prove their components
ok can follow type-specific design rules that
ensure its ok. - Composable Extensions can extend each other
25Our Logo
The POLA Bear
26- interface OpenState Object
getState()interface Equivable extends
OpenState, Frozen - boolean equiv(Object left, Object right) if
(left instanceof Equivable right
instanceof Equivable) return
left.getState() right.getState()
left.getClass() right.getClass()
else return left right
27E Language
- object-oriented
- lambda message dispatch local side effects
- dynamic soft type checking
- def withdrawal (0..balance) ...
- distributed, concurrent, persistent
- promise pipelining between event loops
- object-granularity capability security
- patterns of safe cooperation
28Stamp Example
- def makeBrand()
- def key
- def makeEnvelope(contents)
- def envelope
- to open(k)
- require(k key)
- return contents
-
-
- return envelope
-
- def sealer
- to seal(contents) return
makeEnvelope(contents) -
- def unsealer
- to unseal(envelope) return
envelope.open(key) -
- return sealer, unsealer
29Stamp Example
- def makeBrand()
- def key
- def makeEnvelope(contents)
- def envelope
- to open(k)
- require(k key)
- return contents
-
-
- return envelope
-
- def sealer
- to seal(contents) return
makeEnvelope(contents) -
- def unsealer
- to unseal(envelope) return
envelope.open(key) -
- return sealer, unsealer
leak
30Stamp Example
- def makeBrand()
- def key
- def makeEnvelope(contents)
- def envelope
- to open(k)
- require(k key)
- return contents
-
-
- return envelope
-
- def sealer
- to seal(contents) return
makeEnvelope(contents) -
- def unsealer
- to unseal(envelope) return
envelope.open(key) -
- return sealer, unsealer
leak
31Stamp Example
- def makeBrand()
- def key
- interface Envelope guards EnvelopeStamp ...
- def makeEnvelope(contents) Envelope
- def envelope implements EnvelopeStamp
- to open(k)
- require(k key)
- return contents
-
-
- return envelope
-
- def sealer
- to seal(contents) Envelope return
makeEnvelope(contents) -
- def unsealer
- to unseal(envelope Envelope) return
envelope.open(key) -
- return sealer, unsealer
32Stamp Example
- def makeBrand()
- def key
- interface Envelope guards EnvelopeStamp ...
- def makeEnvelope(contents) Envelope
- def envelope implements EnvelopeStamp
- to open(k)
- require(k key)
- return contents
-
-
- return envelope
-
- def sealer
- to seal(contents) Envelope return
makeEnvelope(contents) -
- def unsealer
- to unseal(envelope Envelope) return
envelope.open(key) -
- return sealer, unsealer
auditor
guard
33Requirements
- We want
- to have guards adapt instances
- to let instances do voluntary conformance
- to audit object implementations
- to verify that an instance has passed an audit
- to provide generalized dispatch on brands
34Choices
- Auditor needs to see
- object expression
- constraints on free variables
35Choices
- constraints on free variables
- Static checking hard, once, safe
- Dynamic checking easy, often, unsafe
- Semi-static checking easy, rare, safe
36Choices
- Auditing interface
- audit(ast, env) returns boolean
- Audit verification
- AuditRegistry holds weak reference pairs
37Choices
- Bootstrapping
- auditors and guards should be DeepFrozen
- use (built-in) auditors for this!