Static Enforcement of Security with Types
490 likes | 510 Vues
This paper discusses the use of types for static enforcement of security in programming languages, with a focus on Java security and stack inspection. It explores the benefits, limitations, and possible improvements of this approach, and provides examples and code snippets to illustrate the concepts.
Static Enforcement of Security with Types
E N D
Presentation Transcript
Static Enforcement of Security with Types Christian Skalka and Scott Smith Johns Hopkins University
Background: PL Security • Non-local execution of code (e.g. Applets) presents new security problems • Some PLs provide user-level abstractions for security (Ambit, Spi-calculus, Java) • Built-in mechanisms allow expression and enforcement of various models/policies
Dataflow ensures security of data Certified Code (PCC) is an extremely general framework for extensible code security Access Controlis a flexible system of code ownership and resource authorization Varieties of Security
Dataflow ensures security of data Certified Code (PCC) is an extremely general framework for extensible code security Access Controlis a flexible system of code ownership and resource authorization Varieties of Security
Overview • Background: PL Security • Java JDK 1.2 and stack inspection • Using types instead of stack inspection • Security Types: formal properties • Possible improvements • Work in Progress • Conclusion
Java Security • Java JDK 1.2 provides a system for access control and code security • possibly non-local program execution requires protection of resources • All code has a specified owner, granted certain privileges locally • Resources are protected by a dynamic check (stack inspection)
Stack Inspection • Stack frames are annotated with names of owners 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
Example: privileged printing privPrint(f) = (* owned by system *) { checkPrivilege(PrintPriv); print(f); } foreignProg() = (* owned by Joe *) { …; privPrint(file); …; }
Stack Inspection (* local policy *) AccessCreds = { Joe ={???},… } (* owned by system *) enablePriv(PrintPriv); foreignProg();
Stack Inspection (* local policy *) AccessCreds = { Joe ={PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg();
Stack Inspection Main system (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg();
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg();
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); foreignProg joe
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); foreignProg joe privPrint system
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); foreignProg joe privPrint system
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe = {PrintPriv},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); success foreignProg joe privPrint system
Stack Inspection (* local policy *) AccessCreds = { Joe ={},… } (* owned by system *) enablePriv(PrintPriv); foreignProg();
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe ={},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); foreignProg joe privPrint system
Stack Inspection Main system PrintPriv (* local policy *) AccessCreds = { Joe ={},… } (* owned by system *) enablePriv(PrintPriv); foreignProg(); foreignProg joe failure privPrint system
Why Stack Inspection? • How is it different from a capability system? • Why not just use an access control matrix and a global set of allowable privileges? • Privileges not held by current code owner are removed from allowable set
Stack Inspection: Callbacks • Stack inspection allows security contexts to be temporarilyraised.
Stack Inspection: Callbacks • Stack inspection allows security contexts to be temporarilyraised: (* owned by system *) getIPaddr(url) = { checkPriv(IPPriv); addr = IPlookup(url); return addr; }
Callbacks (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this);
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system IPPriv
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system IPPriv this.source joe
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system IPPriv
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system IPPriv getIPaddr system
Callbacks getMyIP (* owned by system *) appletIP(applet) = { enablePriv(IPPriv); url =applet.source(); return getIPaddr(url); } (* owned by Joe, not authorized for IPPriv *) getMyIP() = appletIP(this); joe appletIP system IPPriv success getIPaddr system
A Static Approach Our thesis: types can statically enforce the Java security model. • Unsafe programs rejected at compile time • Need for runtime checks eliminated • Types are a declaritive form of security policy expression and enforcement
Security Type Examples (* privPrint needs PrintPriv *) privPrint : file -{PrintPriv}-> unit (* PrintPriv in AccessCreds(Joe) *) foreignProg : unit -{PrintPriv}-> t (* PrintPriv not in AccessCreds(Joe) *) foreignProg : *ERROR*, cannot be typed
Security Type Examples (* enables SomePriv for parameter f *) privWrap(f) = {enablePriv(SomePriv); f(); } privWrap : (unit -{SomePriv}-> unit) -{}-> unit
Subtyping Security Types • With monotypes, subtypes allow typing of more safe programs: • privWrapcan safely use the identity function id, soprivWrap(id)should be typable id :unit -{}-> unit privWrap : (unit -{SomePriv}-> unit) -{}-> unit
Security requirements may safely be overestimated Subtyping Security Types P C t1’<: t1, t2 <: t2’ P’ u (fnlt) C t1-P-> t2 <: t1’-P’-> t2’ unit -{}-> unit <: unit -{SomePriv}-> unit privWrap(id) : unit
Security Type Judgements G, P, p e : t {p} P u (checkpriv) G, P, p checkPriv p for e : t
Security Type Judgements G, P, p e : t {p} P u (checkpriv) G, P, p checkPriv p for e : t P’ G, P, p e : t’ t G, P, p e’ : t’ P’ P u (appl) G, P, p ee’ : t
Security Type Judgements G, P, p e : t {p} P u (checkpriv) G, P, p checkPriv p for e : t P’ G, P, p e : t’ t G, P, p e’ : t’ P’ P u (appl) G, P, p ee’ : t {p} G, P u{p}, p e : t A(p) u (enablepriv) enablePriv p for e : t G, P, p
Formal Properties of the System • Stack Inspection is modeled in a language with well-defined operational semantics: S, A e v S ::= (p, P) :: S’ (secstacks) Unsafe expressions reduce to secfail: S, A e secfail
Formal Properties of the System • We prove subject reduction and type safety results for the system • Well-typed programs are not unsafe. • We prove soundness and completeness results for a type inference algorithm • type system can be transparently layered over existing system
Type Inference • Algorithm is standard constraint inference, plus a new constraint satisfiability check: • Privilege sets may contain variables • Privilege set variable constraints may be recursive • Satisfiability check is novel, efficient; correctness is proved
Incompleteness of the System • Java privileges are first-class • Java programs can conditionally branch on presence/absence of privileges • Paramaterized privileges, e.g.: fileRead(filename) • Dynamic access control lists
Work in Progress • Extend type systemto accurately type privilege tests • Polymorphism • More sophisticated language features (Java features, modules) • Readability of types
Conclusion • Java security model is sound, but dynamic checks impose penalties • Types can be used to enforce the model, and eliminate these penalties • Security Types may be inferred efficiently http://www.cs.jhu.edu/~ces/work.html
Conclusion • Java security model is sound, but dynamic checks impose penalties • Types can be used to enforce the model, and eliminate these penalties • Security Types may be inferred efficiently http://www.cs.jhu.edu/~ces/work.html
Conclusion • Java security model is sound, but dynamic checks impose penalties • Types can be used to enforce the model, and eliminate these penalties • Security Types may be inferred efficiently http://www.cs.jhu.edu/~ces/work.html
Conclusion • Java security model is sound, but dynamic checks impose penalties • Types can be used to enforce the model, and eliminate these penalties • Security Types may be inferred efficiently http://www.cs.jhu.edu/~ces/work.html
Conclusion • Java security model is sound, but dynamic checks impose penalties • Types can be used to enforce the model, and eliminate these penalties • Security Types may be inferred efficiently http://www.cs.jhu.edu/~ces/work.html