Current Techniques in Language-based Security David Walker COS 441 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 441 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 441 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 441 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 441 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 how exactly does it work? Reasoning about programs that use stack inspection COS 441 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 441 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 441 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 441 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 441 10 Classloader Hierarchy Primordial ClassLoader ClassLoader SecureClassLoader URLClassLoader AppletClassLoader COS 441 11 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 441 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 441 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/dpw/grades.txt”, “Ginsburg: A+”); ... } } COS 441 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 441 15 Stack Inspection Example fp = new FilePermission(“/tmp/*”,“write,…”); Policy Database main(…){ sm.enablePrivilege(fp); UntrustedApplet.run(); } COS 441 16 Stack Inspection Example Policy Database main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 441 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 441 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 441 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 441 20 Stack Inspection Example Policy Database void run() { … s.FileWrite(“/home/dpw/grades.txt”, “Ginsburg: A+”); } main(…){ fp = new FilePermission(“/tmp/*”,“write,…”); sm.enablePrivilege(fp); UntrustedApplet.run(); fp } COS 441 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/dpw/grades.txt”, “Ginsburg: A+”); } fp } COS 441 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 A trusted piece of code could disable a previously granted permission Terminate the stack inspection early COS 441 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 441 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 441 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 441 26 Stack Inspection Literature Stack Inspection: Theory and Variants Cédric Fournet and Andrew D. Gordon Use operational semantics like in class Understanding Java Stack Inspection Dan S. Wallach and Edward W. Felten Formalize Java Stack Inspection using a special logic of authentication COS 441 27 Formalizing Stack Inspection Abstract Stack Inspection Abstract permissions p,q R,S Permissions (left abstract in the theory) Principals (sets of permissions) Hide the details of classloading, etc. Examples: System = {fileWrite(“f1”), fileWrite(“f2”),…} Applet = {fileWrite(“f1”)} COS 441 29 lsec Syntax Language syntax: e ::= x lx.e e1 e2 R{e} enable p in e test p then e1 else e2 fail v ::= x o ::= v | | lx.e fail expressions variable function application framed expr enable check perm. failure values outcome COS 441 30 Framing a Term Models the Classloader that marks the (unframed) code with its protection domain: Load(R,x) = x Load(R,lx.e) = lx. R{ Load(R,e) } Load(R,e1 e2) = Load(R,e1) Load(R,e2) Load(R,enable p in e) = enable p in Load(R,e) Load(R,test p then e2 else e2) = test p then Load(R,e1) else Load(R,e2) Load(R,fail) = fail COS 441 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 441 32 lsec Operational Semantics Evaluation contexts: E ::= [] E e v E enable p in E R{E} Hole Eval function Eval arg Tag on stack frame Stack frame E models the control stack COS 441 33 lsec Operational Semantics E[(lx.e) v] --> E[e{v/x}] E[enable p in v] --> E[v] E[R{v}] --> E[v] E[fail] --> fail E[test p then e else f] if --> E[e] Stack(E) |-- p E[test p then e else f] --> E[f] if (Stack(E) |-- p) COS 441 34 Example Evaluation Context Applet{readFile “f2”} E = Applet{[]} r = readfile “f2” COS 441 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 441 36 Example Evaluation Context Applet{readFile “f2”} E = Applet{[]} r = System{ test fileWrite(“f2”) then … // primitive file IO (native code) else fail } COS 441 37 Example Evaluation Context Applet{System{ test fileWrite(“f2”) then … // primitive file IO (native code) else fail }} COS 441 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 441 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 441 40 Formal Stack Inspection Structure of Stacks: s ::= . | s.R | s.enable(p) (Empty Stack) (Stack for code of principal R) (Privelege p enabled) COS 441 41 Stack of an Eval. Context Stack([]) = Stack(E e) = Stack(v E) = Stack(enable p in E) = Stack(R{E}) = . Stack(E) Stack(E) enable(p).Stack(E) R.Stack(E) Stack(E’) = Stack(Applet{System{[]}}) = Applet.Stack(System{[]}) = Applet.System.Stack([]) = Applet.System. COS 441 42 Abstract Stack Inspection . |-- p empty stack axiom s |-- p p R s.R |-- p protection domain check s |-- p s.enable(q) |-- p p q irrelevant enable s |= p s.enable(p) |-- p check enable COS 441 43 Abstract Stack Inspection . |= p pR x.R |= p x |= p x.enable(q) |= p empty stack enables all enable succeeds irrelevant enable COS 441 44 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 441 45 Example Inequality ok = lx.x (note: loop ) loop = (lx.x x)(lx.x x) 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 441 46 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 stack({ [ ] }) = .. • ok .. |-- p is not valid COS 441 47 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 return from function • (l_.test p then loop else ok) ok ==> pop frame • test p then loop else ok • loop loop loop … COS 441 stack([ ] ) = . . |-- p is valid! 48 Example Applications Formal reasoning about the semantics of stack inspection makes it possible to perform safe optimizations: 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 441 49 Axiomatic Equivalence Can give a sound set of equations that characterize =. Example axioms: • (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 COS 441 Implies = 50 Other Problems Applets returning closures can 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 441 53 Conclusions What security properties does the Java security model guarantee? What optimizations are legal? Formal semantics helps us find the answers & suggests improvements COS 441 54