a conservative algorithm for computing the flow of permissions in java programs

25
A Conservative Algorithm for Computing the Flow of Permissions in Java Programs Gleb Naumovich Polytechnic University Brooklyn, USA Presented by David Chays Polytechnic University

Upload: tavon

Post on 12-Jan-2016

12 views

Category:

Documents


0 download

DESCRIPTION

A Conservative Algorithm for Computing the Flow of Permissions in Java Programs. Gleb Naumovich Polytechnic University Brooklyn, USA. Presented by David Chays Polytechnic University. Motivation. Security problems may exist on two levels Protocol level - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Gleb NaumovichPolytechnic University

Brooklyn, USA

Presented byDavid Chays

Polytechnic University

Page 2: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Motivation

Security problems may exist on two levelsProtocol level

Attacks exploit weakness of encryption/authentication/transfer protocols

Implementation levelAttacks exploit errors in implementation of

secure protocolsJava developers rely on the built-in

security model to provide protection against some types of attacks

This model is complicated, so application programmers are likely to make mistakes in its use

This work aims at validating the use of the Java security model by developers

Page 3: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Java security model: permissions

Remotely loaded classes may be given permission to perform specific operations

grant signedBy “Poly”, codebase http://cis.poly.edu/gleb/classes/- { permission java.io.FilePermission “/tmp/*”, “read, write”;}

Code dealing with sensitive operations (e.g. reading/writing, opening sockets) has to check that callers have sufficient permissions

AccessController.checkPermission(new java.io.FilePermission( “/tmp/*”, “read, write”));

Page 4: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission checking: running examplepublic class Account { private Money balance; private String persistentLocation;

public Account(Money initialAmount, String persistentLocation) { AccessController.checkPermission( new NewAccountPermission ("NewAccountPermission")); this.balance = (Money) initialAmount.clone(); this.persistentLocation = persistentLocation; }

public Money getBalance() { AccessController.checkPermission( new BalancePermission("BalancePermission")); return (Money) this.balance.clone(); }

public void credit(Money amount) { AccessController.checkPermission( new CreditPermission("CreditPermission")); this.balance.add(amount); this.write(); }

public void debit(Money amount) { AccessController.checkPermission( new DebitPermission("DebitPermission")); this.balance.subtract(amount); this.write(); }

private void write() { AccessController.doPrivileged() ( new PrivilegedAction() { public Object run() { FileWriter writer = new FileWriter (this.persistentLocation); writer.write(balance); writer.close(); } } ); }

public void transfer(Money amount, Account toAccount) { this.debit(amount); toAccount.credit(amount); }}

Page 5: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission checking: running example (cont.)

public class AccountWithProtection extends Account { private Account protection;

public AccountWithProtection(Money initialAmount, String persistentLocation, Account protection) { super(initialAmount, persistentLocation); this.protection = protection; }

public void debit(Money amount) { AccessController.checkPermission( new CustomerPermission("CustomerPermission"); AccessController.doPrivileged() ( new PrivilegedAction() { public Object run() { Money currentBalance = this.getBalance(); if (currentBalance.compare(amount) == Money.LESS_THAN) { Money toTransfer = amount.clone(); toTransfer.subtract(currentBalance); this.protection.transfer(toTransfer, this); } super.debit(amount); } } ); }}

public class CustomerInterface { public static void main(String[] args) { Account savings = new Account( new Money(3000, 0), "savings"); AccountWithProtection credit = new AccountWithProtection( new Money(5000, 0), "credit", savings); AccountWithProtection overdraft = new AccountWithProtection( new Money(1000, 0), "overdraft", credit); AccountWithProtection checking = new AccountWithProtection( new Money(2000, 0), "checking", overdraft);

checking.debit(new Money(10000, 0)); }}

Page 6: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

How checkPermission works

Examines all classes on the call stack and makes sure that all of them have permission to do an operation

class MainClass { public static void main(String [] args) { … MyClass o = new MyClass(); o.m(); }}

class MyClass { … public void m() { … RemoteClass obj = new RemoteClass(); obj.passAccount(new Account(1000)); }}

MainClassmain

MyClassm

RemoteClasspassAccount

Accountdebit

}JVM makessure all classeshave the permissionchecked in Account

Page 7: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Java security model: privileged regions

“Trusted” code can temporarily grant additional privileges to other classes in the call stack

Useful in situations where untrusted classes can be allowed to perform specific actions that would otherwise require privileges

E.g., an application programmer may decide to

Not give untrusted classes permissions to check balance, credit, or debit an account

Let untrusted classes find out whether the account balance is above or below $1000

Page 8: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

How privileged regions work

class MainClass { public static void main(String [] args) { … MyClass o = new MyClass(); o.m(); }}

class MyClass { private Account account; … public void debit(int amount) { AccessController.doPrivileged( new PrivilegedAction() { this.account.debit(amount); } } public void m() { … RemoteClass obj = new RemoteClass(); obj.giveAccess(MyClass.this)); }}

MainClassmain

MyClassm

RemoteClassgiveAccess

Accountdebit

MyClassdebit

Privileged{}

JVM checks thatthese classes haveDebitPermission

JVM does not checkthat these classes have DebitPermission

Page 9: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

How permissions are defined

public class CreditPermission extends BasicPermission { ...

public boolean implies(Permission p) { return (p instanceof CreditPermission) || (p instanceof FilePermission); }}

Page 10: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

What we would like to verify

Often, the developer can easily identify “sensitive” parts of the program

Want to verify that these parts are protected by permissions

Formally: by the time program point S is reached, permission P has been checked

Have to take into account:Interprocedural pathsImplication relationships between

permissions“Insecure entry points” --- code that can

be called by malicious classes

Page 11: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Our approach (high level)

Construct a representation of implies relationships among permissions in the program

Construct a representation of relationships among sets of permissions

Construct a static model of the program

Call graph basedRun data flow analysis to determine for

each point in the program what permissions must be checked on all paths to that point

Page 12: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission lattice

Define a partial order among permissions based on their implication relationship

Because our approach is static, have to place several restrictions on how permissions are defined:

Values of permission parameters have to be statically defined strings

The implies method defined in a way that a permission object implies all permission objects of the same class

Permission objects are immutable

Essentially, instead of permission objects, we deal with statically defined permission classes

In practice, such permission definitions are common

Page 13: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission lattice for the example

Page 14: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission set lattice

To analyze the flow of permissions through the program, need to reason about sets of permissions

Have to define a lattice that describes relationships among sets of permissions, based on the implication relationships

Cannot simply say that permission set P1 implies permission set P2 if any permission in P2 is implied by a permission in P1

Would not be a partial order (e.g. consider sets {p1} and {p1 p2}, where p1 implies p2)

Define canonical permission setsGiven a set of permissions, simply remove all

permissions that are implied by other permissions in this set

Page 15: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission set lattice for the example

Page 16: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Program representation: Permission Call Graphs (PCGs) Similar to Jensen et al. [IEEE symposium on

security and privacy, 1999] and Nitta et al. [ACM symposium on access control models and technologies, 2001]

Captures relationships between control flow, permission checking, and privileged regions

Each node represents one of Start of a method execution Call to a method checkPermission call Entrance to a privileged region Exit from a privileged region

Constructed from control flow graphs for all methods in the program

Assume that all public methods of public classes can be called by external classes

An overapproximation

Page 17: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Permission call graph for the example

Page 18: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Data flow algorithm for computing the permission flow Forward-flow all-paths flow-sensitive context-

insensitive analysis For each node n in the PCG, differentiate

between two sets of paths leading to it: Paths on which n is executed inside a privileged region Paths on which n is executed outside privileged regions

The algorithm computes two sets of permissions for each node n:

Permissions that are checked on all executions to n where n is executed inside a privileged region: priv(n)

Permissions that are checked on all executions to n where n is executed outside privileged regions: unpriv(n)

After a fixed point is reached, a conservative estimate of all permissions checked on all paths to n is the intersection of the two permission sets for n

Page 19: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Example of computing priv and unpriv sets for a PCG node

checkPermission(DebitPermission)

m1m2

priv(m1) = {CreditPermission}unpriv(m1) = {CreditPermission}

priv(m2) = {DebitPermission}unpriv(m2) = {WritePermission}

n

INpriv(n) = {WritePermission}INunpriv(n) = {WritePermission}

priv(n) = {WritePermission}unpriv(n) = {DebitPermission}

Page 20: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Results of the analysis for the example

Page 21: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Checking properties about permissions

Given the information from the analysis, can answer questions of the form “is permission p always checked by the time statement s is executed?”

Cannot directly answer questions like “is one of permissions p1, …, pk always checked by the time statement s is executed?”

The algorithm uses the meet operation on the permission set lattice to compute the flow of permissions into a node

Can check such properties if the permission lattice is modified

And consequently, the permission set lattice is modified

Page 22: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Property-modified lattice for the example

• The property checks whether one of permissions NewAccountPermission, CreditPermission, DebitPermission is checked on all executions to node 16

Page 23: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

A violation is detected when checking this property!The analyst can follow the path of

permissions through the graph to determine on what type of executions none of permissions NewAccountPermission, CreditPermission, DebitPermission are checked before node 16 is executed

It would make sense for CustomerPermission to imply BalancePermission, CreditPermission, and DebitPermission

After the implies method of CustomerPermission is modified accordingly, the analysis successfully proves the property

Page 24: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Future work

Implementation and experimentsShould scale well, since the analysis is

cubic in the size of the PCG and the number of permission types used in the program

Previous approaches (Jensen et al., Nitta et al.) used exponential-time analyses

Believe that in most practical situations, permissions are defined and used in a static fashion

Investigate whether more complex permission-related properties need to be checked

The approach is context-insensitiveDo not believe that there is much to be

gained by context-sensitivity, but have to check experimentally

Page 25: A Conservative Algorithm for Computing the Flow of Permissions in Java Programs

Questions?

I’ll try to answer, but if that fails…Email: [email protected]