Current Techniques in Language-based Security David Walker COS 597B With slides stolen from: Steve Zdancewic University of Pennsylvania Mobile Code Modern languages like Java and C# have been designed for Internet applications and extensible systems applet applet applet web browser operating system PDAs, Cell Phones, Smart Cards, … COS 597B 2 Applet Security Problems Protect OS & other valuable resources. Applets should not: crash browser or OS execute “rm –rf /” be able to exhaust resources Applets should: be able to access some system resources (e.g. to display a picture) be isolated from each other Principles of least privileges and complete mediation apply COS 597B 3 Java and C# Security Static Type Systems Memory safety and jump safety Run-time checks for Array index bounds Downcasts Access controls These lectures Virtual Machine / JIT compilation Bytecode verification Enforces encapsulation boundaries (e.g. private field) Garbage Collected Eliminates memory management errors Library support Cryptography, authentication, … COS 597B 4 Access Control for Applets What level of granularity? Applets can touch some parts of the file system but not others Applets can make network connections to some locations but not others Different code has different levels of trustworthiness www.l33t-hax0rs.com vs. www.java.sun.com Trusted code can call untrusted code e.g. to ask an applet to repaint its window Untrusted code can call trusted code e.g. the paint routine may load a font How is the access control policy specified? COS 597B 5 Outline Java Security Model (C# similar) Stack inspection Concrete examples To discuss: what security principles does the Java security model obey or not obey? Semantics from a PL perspective Formalizing stack inspection Reasoning about programs that use stack inspection COS 597B 6 Java Security Model VM Runtime a.class b.class c.class d.class e.class Security Policy Domain A Permissions Domain B Permissions Classloader SecurityManager http://java.sun.com/j2se/1.4.2/docs/guide/security/spec/security-specTOC.fm.html COS 597B 7 Kinds of Permissions java.security.Permission Class perm = new java.io.FilePermission("/tmp/abc","read"); java.security.AllPermission java.security.SecurityPermission java.security.UnresolvedPermission java.awt.AWTPermission java.io.FilePermission java.io.SerializablePermission java.lang.reflect.ReflectPermission java.lang.RuntimePermission java.net.NetPermission java.net.SocketPermission … COS 597B 8 Code Trustworthiness How does one decide what protection domain the code is in? Source (e.g. local or applet) Digital signatures C# calls this “evidence based” How does one decide what permissions a protection domain has? Configurable – administrator file or command line Enforced by the classloader COS 597B 9 Classloaders In order to pull new code into the virtual machine, we use an object from the ClassLoader class A class loader will look in the file system, or across the network for a class file, or possibly dynamically generate the class When loading the first class of an application, a new instance of the URLClassLoader is used. When loading the first class of an applet, a new instance of the AppletClassLoader is used. Class loaders are responsible for placing classes into their security domains AppletClassLoader places classes in domains depending on where they are from Other ClassLoaders places classes in domains based on digital signatures, or origin (such as local file system) COS 597B 10 Associating Privileges with Domains grant codeBase “http://www.l33t-hax0rz.com/*” { permission java.io.FilePermission(“/tmp/*”, “read,write”); } grant codeBase “file://$JAVA_HOME/lib/ext/*” { permission java.security.AllPermission; } grant signedBy “trusted-company.com” { permission java.net.SocketPermission(…); permission java.io.FilePermission(“/tmp/*”, “read,write”); … } Policy information stored in: $JAVA_HOME/lib/security/java.policy $USER_HOME/.java.policy (or passed on command line) COS 597B 12 Example Trusted Code Code in the System protection domain void fileWrite(String filename, String s) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { FilePermission fp = new FilePermission(filename,“write”); sm.checkPermission(fp); /* … write s to file filename (native code) … */ } else { throw new SecurityException(); } } public static void main(…) { SecurityManager sm = System.getSecurityManager(); FilePermission fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); } COS 597B 13 Example Client Applet code obtained from http://www.l33t-hax0rz.com/ class UntrustedApplet { void run() { ... s.FileWrite(“/tmp/foo.txt”, “Hello!”); ... s.FileWrite(“/home/stevez/important.tex”, “kwijibo”); ... } } COS 597B 14 Stack Inspection Stack frames are annotated with their protection domains and any enabled privileges. During inspection, stack frames are searched from most to least recent: fail if a frame belonging to someone not authorized for privilege is encountered succeed if activated privilege is found in frame COS 597B 15 Stack Inspection Example fp = new FilePermission(“/tmp/*”,“write,…”); Policy Database main(…){ sm.enablePrivilege(fp); UntrustedApplet.run(); } COS 597B 16 Stack Inspection Example Policy Database main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 597B 17 Stack Inspection Example Policy Database void run() { … s.FileWrite(“/tmp/foo.txt”, “Hello!”); … } main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 597B 18 Stack Inspection Example void fileWrite(“/tmp/foo.txt”, “Hello!”) { fp = new FilePermission(“/tmp/foo.txt”,“write”) sm.checkPermission(fp); /* … write s to file filename … */ Policy Database void run() { … s.FileWrite(“/tmp/foo.txt”, “Hello!”); … } main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 597B 19 Stack Inspection Example void fileWrite(“/tmp/foo.txt”, “Hello!”) { fp = new FilePermission(“/tmp/foo.txt”,“write”) sm.checkPermission(fp); /* … write s to file filename … */ main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); Policy Database void run() { … s.FileWrite(“/tmp/foo.txt”, “Hello!”); … } Succeed! fp sm.enablePrivilege(fp); UntrustedApplet.run(); } COS 597B 20 Stack Inspection Example Policy Database void run() { … s.FileWrite(“/home/stevez/important.tex”, “kwijibo”); } main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 597B 21 Stack Inspection Example void fileWrite(“…/important.txt”, “kwijibo”) { fp = new FilePermission(“important.txt”, “write”); sm.checkPermission(fp); Fail main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); Policy Database void run() { … s.FileWrite(“/home/stevez/important.tex”, “kwijibo”); } fp } COS 597B 22 Other Possibilities The fileWrite method could enable the write permission itself Potentially dangerous, should not base the file to write on data from the applet … but no enforcement in Java (information flow would help here) A trusted piece of code could disable a previously granted permission Terminate the stack inspection early COS 597B 23 Stack Inspection Algorithm checkPermission(T) { // loop newest to oldest stack frame foreach stackFrame { if (local policy forbids access to T by class executing in stack frame) throw ForbiddenException; if (stackFrame has enabled privilege for T) return; // allow access if (stackFrame has disabled privilege for T) throw ForbiddenException; } // end of stack if (Netscape || …) throw ForbiddenException; if (MS IE4.0 || JDK 1.2 || …) return; } COS 597B 24 Two Implementations On demand – On a checkPermission invocation, actually crawl down the stack, checking on the way Used in practice Eagerly – Keep track of the current set of available permissions during execution (security-passing style Wallach & Felten) + more apparent (could print current perms.) - more expensive (checkPermission occurs infrequently) COS 597B 25 Stack Inspection Stack inspection seems appealing: Fine grained, flexible, configurable policies Distinguishes between code of varying degrees of trust But… How do we understand what the policy is? Semantics tied to the operational behavior of the program (defined in terms of stacks!) How do we compare implementations Changing the program (e.g. optimizing it) may change the security policy Policy is distributed throughout the software, and is not apparent from the program interfaces. Is it any good? COS 597B 26 Stack Inspection Literature Stack Inspection: Theory and Variants Cédric Fournet and Andrew D. Gordon Understanding Java Stack Inspection Dan S. Wallach and Edward W. Felten Formalize Java Stack Inspection using ABLP logic And many more... COS 597B 27 Formalizing Stack Inspection Abstract Stack Inspection Abstract permissions p,q R,S Permissions Principals (sets of permissions) Hide the details of classloading, etc. Examples: System = {fileWrite(“f1”), fileWrite(“f2”),…} Applet = {fileWrite(“f1”)} COS 597B 29 lsec Syntax Language syntax: e,f ::= x lx.e e f R{e} enable p in e test p then e else f fail v ::= x o ::= v | | lx.e fail expressions variable function application framed expr enable check perm. failure values outcome COS 597B 30 Framing a Term Models the Classloader that marks the (unframed) code with its protection domain: R[x] = x R[lx.e] = lx.R{R[e]} R[e f] = R[e] R[f] R[enable p in e] = enable p in R[e] R[test p then e else f] = test p then R[e] else R[f] R[fail] = fail COS 597B 31 Example readFile = lfileName.System{ test fileWrite(fileName) then … // primitive file IO (native code) else fail } Applet{readFile “f2”} fail System{readFile “f2”} <f2 contents> COS 597B 32 lsec Operational Semantics Evaluation contexts: E ::= [] E e v E enable p in E R{E} Hole Eval. Function Eval. Arg. Tagged frame Frame E models the control stack COS 597B 33 lsec Operational Semantics E[(lx.e) v] E[enable p in v] E[R{v}] E[fail] E[test p then e else f] E[e{v/x}] E[v] E[v] fail E[e] if Stack(E) |-- p E[test p then e else f] E[f] if (Stack(E) |-- p) eo iff e * o COS 597B Stack Inspection 34 Example Evaluation Context Applet{readFile “f2”} E = Applet{[]} r = readfile “f2” COS 597B 35 Example Evaluation Context Applet{readFile “f2”} E = Applet{[]} r = (lfileName.System{ test fileWrite(fileName) then … // primitive file IO (native code) else fail }) “f2” COS 597B 36 Example Evaluation Context Applet{readFile “f2”} E = Applet{[]} r = System{ test fileWrite(“f2”) then … // primitive file IO (native code) else fail } COS 597B 37 Example Evaluation Context Applet{System{ test fileWrite(“f2”) then … // primitive file IO (native code) else fail }} COS 597B 38 Example Evaluation Context Applet{System{ test fileWrite(“f2”) then … // primitive file IO (native code) else fail }} E’ = Applet{System{[]}} r’ = test fileWrite(“f2”) then … // primitive file IO (native code) else fail COS 597B 39 Formal Stack Inspection E’ = Applet{System{[]}} r’ = test fileWrite(“f2”) then … // primitive file IO (native code) else fail When does stack E’ allow permission fileWrite(“f2”)? Stack(E’) |-- fileWrite(“f2”) COS 597B 40 Stack of an Eval. Context Stack([]) = . Stack(E e) = Stack(E) Stack(v E) = Stack(E) Stack(enable p in E) = enable(p).Stack(E) Stack(R{E}) = R.Stack(E) Stack(E’) = Stack(Applet{System{[]}}) = Applet.Stack(System{[]}) = Applet.System.Stack([]) = Applet.System. COS 597B 41 Abstract Stack Inspection . |-- p empty stack axiom x |-- p p R x.R |-- p protection domain check x |-- p x.enable(q) |-- p p q irrelevant enable x |= p x.enable(p) |-- p check enable COS 597B 42 Abstract Stack Inspection . |= p pR x.R |= p x |= p x.enable(q) |= p empty stack enables all enable succeeds* irrelevant enable * Enables should occur only in trusted code COS 597B 43 Equational Reasoning e iff there exists o such that e o Let C[] be an arbitrary program context. Say that e = e’ iff for all C[], if C[e] and C[e’] are closed then C[e] iff C[e’]. COS 597B 44 Example Inequality let x = e in e’ = (lx.e’) e ok = lx.x loop = (lx.x x)(lx.x x) (note: loop ) f = lx. let z = x ok in l_.z g = lx. let z = x ok in l_.(x ok) Claim: f ≠ g Proof: Let C[] = {[] l_.test p then loop else ok} ok COS 597B 45 Example Continued C[f] = {f l_.test p then loop else ok} ok • {let z = (l_.test p then loop else ok) ok in l_.z} ok • {let z = test p then loop else ok in l_.z} ok • {let z = ok in l_.z} ok • {l_.ok} ok • (l_.ok) ok • ok COS 597B 46 Example Continued C[g] = {g l_.test p then loop else ok} ok • {let z = (l_.test p then loop else ok) ok in l_.((l_.test p then loop else ok) ok)} ok • {let z = test p then loop else ok in l_. ((l_.test p then loop else ok) ok)} ok • {let z = ok in l_. ((l_.test p then loop else ok) ok)} ok • {l_. ((l_.test p then loop else ok) ok)} ok • (l_. ((l_.test p then loop else ok) ok)) ok • (l_.test p then loop else ok) ok • test p then loop else ok • loop loop loop loop … COS 597B 47 Example Applications Eliminate redundant annotations: lx.R{ly.R{e}} = lx.ly.R{e} Decrease stack inspection costs: e = test p then (enable p in e) else e COS 597B 48 Axiomatic Equivalence Can give a sound set of equations that characterize =. Example axioms: • is a congruence (preserved by contexts) • (lx.e) v e{v/x} (beta equivalence) • x fv(v) lx.v v • enable p in o o • enable p in (enable q in e) enable q in (enable p in e) • R S R{S{e}} S{e} • R{S{enable p in e}} R{p}{S{enable p in e}} • … many, many more Implies = COS 597B 49 Example: Tail Calls Ordinary evaluation: R{(lx.S{e}) v} R{S{e{v/x}}} Tail-call eliminated evaluation: R{(lx.S{e}) v} S{e{v/x}} Not sound in general! But OK in special cases. COS 597B 50 Example: Tail Calls Suppose R S. Then: R{(lx.S{e}) v} R{S{e{v/x}}} S{e{v/x}} S{e}{v/x} (lx.S{e}) v In particular, code within a protection domain can safely make tail calls to other code in that domain. COS 597B 51 Example: Higher-order Code main = System [lh.(h ok ok)] fileHandler = System[ls.lc.l_.c (readFile s)] leak = Applet[ls.output s] main(l_.Applet{fileHandler “f2” leak}) COS 597B 52 Example: Higher-order Code • main(l_.Applet{fileHanler “f2” leak}) • * System{Applet{fileHandler “f2” leak} okS} • * System{Applet{System{System{ l_.System{leak (readFile “f2”)}}}} okS} • * System{l_.System{leak (readFile “f2”)} okS} • * System{System{leak <f2 contents>}} • * System{System{Applet{output <f2 contents>}}} • * System{System{Applet{ok}}} • * ok COS 597B 53 Discussion Problem: Applets returning closures that circumvent stack inspection. Possible solution: Values of the form: R{v} (i.e. keep track of the protection domain of the source) Similarly, one could have closures capture their current security context Integrity analysis (i.e. where data comes from) Fournet & Gordon prove some properties of strengthened versions of stack inspection. COS 597B 54 Conclusions What security principles does the Java model obey? To what extent? Open design? Economy of mechanism? Minimal trusted computing base? Security as process? Least privilege? Fail-safe defaults? Psychological acceptability? COS 597B 55