Static Enforcement of Security with Types

Download Report

Transcript Static Enforcement of Security with Types

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
Varieties of Security
• Dataflow ensures security of data
• Certified Code (PCC) is an extremely general
framework for extensible code security
• Access Control is 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 Control is a flexible system of code
ownership and resource authorization
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
(* local policy *)
AccessCreds = {
Joe = {PrintPriv},…
}
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
system
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {PrintPriv},…
}
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
system
PrintPriv
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {PrintPriv},…
}
system
PrintPriv
foreignProg
joe
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {PrintPriv},…
}
system
PrintPriv
foreignProg
joe
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
privPrint
system
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {PrintPriv},…
}
system
PrintPriv
foreignProg
joe
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
privPrint
system
Stack Inspection
Main
(* local policy *) success
AccessCreds = {
Joe = {PrintPriv},…
}
system
PrintPriv
foreignProg
joe
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
privPrint
system
Stack Inspection
(* local policy *)
AccessCreds = {
Joe = {},…
}
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {},…
}
system
PrintPriv
foreignProg
joe
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
privPrint
system
Stack Inspection
Main
(* local policy *)
AccessCreds = {
Joe = {},…
}
system
PrintPriv
foreignProg
failure
(* owned by system *)
enablePriv(PrintPriv);
foreignProg();
joe
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 temporarily raised.
•
Stack Inspection: Callbacks
Stack inspection allows security contexts
to be temporarily raised:
•
(* 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);
joe
appletIP
url = applet.source();
return getIPaddr(url);
}
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
system
Callbacks
getMyIP
(* owned by system *)
appletIP(applet) =
{
enablePriv(IPPriv);
joe
appletIP
url = applet.source();
return getIPaddr(url);
}
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
system
IPPriv
Callbacks
getMyIP
(* owned by system *)
appletIP(applet) =
{
enablePriv(IPPriv);
joe
appletIP
url = applet.source();
return getIPaddr(url);
}
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
system
IPPriv
this.source
joe
Callbacks
getMyIP
(* owned by system *)
appletIP(applet) =
{
enablePriv(IPPriv);
joe
appletIP
url = applet.source();
return getIPaddr(url);
}
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
system
IPPriv
Callbacks
getMyIP
(* owned by system *)
appletIP(applet) =
{
enablePriv(IPPriv);
joe
appletIP
url = applet.source();
system
IPPriv
return getIPaddr(url);
}
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
getIPaddr
system
Callbacks
getMyIP
(* owned by system *)
appletIP(applet) =
{
enablePriv(IPPriv);
joe
appletIP
url = applet.source();
return getIPaddr(url);
}
system
IPPriv
success
(* owned by Joe, not
authorized for IPPriv *)
getMyIP() = appletIP(this);
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:
– privWrap can safely use the identity function
id, so privWrap(id) should be typable
id : unit -{}-> unit
privWrap : (unit -{SomePriv}-> unit) -{}-> unit
Subtyping Security Types
• Security requirements may safely be
overestimated
(fnlt)
P’
C
t1’ <: t1, t2 <: t2’
C
t1 -P-> t2 <: t1’-P’-> t2’
P
unit -{}-> unit <: unit -{SomePriv}-> unit
privWrap(id) : unit
Security Type Judgements
Security Type Judgements
(checkpriv)
G, P, p
G, P, p
e:t
{p} P
checkPriv p for e : t
Security Type Judgements
(checkpriv)
(appl)
G, P, p
G, P, p
G, P, p
e : t’
e:t
{p} P
checkPriv p for e : t
P’
t
G, P, p
G, P, p ee’ : t
e’ : t’ P’
P
Security Type Judgements
G, P, p
(checkpriv)
(appl)
G, P, p
G, P, p
(enablepriv)
e : t’
e:t
{p} P
checkPriv p for e : t
P’
G, P, p
G, P, p ee’ : t
G, P u{p}, p
G, P, p
t
e:t
e’ : t’ P’
{p}
A(p)
enablePriv p for e : t
P
Formal Properties of the System
• Stack Inspection is modeled in a language
with well-defined operational semantics:
S, A
(secstacks)
e
v
S ::= (p, P) :: S’
• 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 system to 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