Information-flow Security

Goal: prevent private data from becoming public.

In class we saw discretionary and mandatory access control.

Focus on confidentiality, not integrity (harder).

Obvious Problem: Explicit Flows

For simplicity, think in terms of variables:

Problem: Assign private expressions to public variables.

E.g.

  l := h + 1

Less Obvious: Implicit Flows

Problem: Use private variables to affect control flow, which in turn affects public variables.

E.g.

  l := False
  if h {
    l := True
  }
  // l == h here!

Covert Channels

Implicit flows are covert channels.

Consider:

  while h {
    ;
  }

Secure for attackers that see only public variables.

Not secure for attackers that see termination behavior.

Security of a program depends on what attacker can observe!

Lattice Model of Secure Info-flow

Recall explicit flow:

  l := h + 1

In what sense is h + 1 a "private expression"?

Answer: confidentiality level of an expression is the least upper bound (lub) of the levels of its parts.

E.g. h is high, 1 is low, so h + 1 is high == lub(low,high).

Fancier Lattices

E.g. more levels, non linear:

  H          H             HAN   
  |          |            / | \  
  |          |          HA  |  HN
  |          |          |  MAN  |
  |          |          | / | \ |
  |    vs    M    vs    MA  |  MN
  |          |          |  LAN  |
  |          |          | / | \ |
  |          |          LA  |  LN
  |          |            \ | /  
  |          |             \|/   
  L          L              P    

Where A is army, N is navy.

E.g., HAN is least upper bound of HN and LA.

Dynamic Info-flow Checking

A little better than (discretionary or mandatory) access control.

Monitor program as it runs.

Fail if security violation detected.

Now we think of explicit returns, not just confidentiality levels of variables.

E.g. OK:

  h := l + 1
  l := l + 2
  h := h + l

E.g. not OK:

  l := False
  if h {
    l := True  // Reject this only if execution gets here!
  }
  low return l // Unsafe when h == False!

Idea

Track security level of guards so far.

Reject returning expression at lower level.

Problem: "scope creep"

E.g.

  Code        Security context  
  ----        ----------------

  l := 1  //  L
  if m {  //  M
    ...   //  M
  }       //  M
  ...     //  M
  if h {  //  H
    ...   //  H
  }       //  H
  ...     //  H

Security context grows with the guards!

Static Info-flow Checking

Goal: guarantee program is secure for all possible inputs.

Bonus: no scope creep!

Non-interference

Private input does not affect ("interfere with") public output.

A program p is non-interfering iff

implies

  low (p ls hs1) == low (p ls hs2),

where low e is the public output of e.

This is a precise definition of info-flow security.

Security Type System

Check program security at compile time!

Compositional (cf. public key)!

Assume all variables are numbers for simplicity.

Notation:

  expression : level

means all variables in expression are at or below level.

  [level] |- statement

means all assignments in statement are safe for level.

An assignment v := e is "safe" for level if v is at or above level and e is at or below level (i.e. e : level).

Here [level] is the security context.

E.g. OK:

  l + 1 : low

  l + 1 : high

  h + l : high

  [low] : l := l + 1

  [low] : h := h + l

  [high] : h := h + 1

E.g. not OK:

  h + l : low           // l is OK, h is not.

  [low] : l := h        // l is OK, h is not.

  [high] : l1 := l2 + 1 // l2 is OK, l1 is not.

E.g. if statement is safe if guard e and body b check at same level:

  e : low    [low] |- b    e : high    [high] |- b
  ---------------------    -----------------------
  [low] |- if e { b }      [high] |- if e { b }  

Full Rules for Simple C-like Language

Figure: Security Type System (Source: Sabelfeld and Myers, 2003)

Figure: Security Type System (Source: Sabelfeld and Myers, 2003)

Don't worry if you haven't seen type systems before.

If a program type checks then it's non-interfering!

Subsumption rule avoids scope creep!

Limitations of Non-interference

Overly restrictive.

Precludes password checking:

  if l_supplied_pw == h_stored_pw {
    l_authenticated := True
  }

and transmission of encrypted data:

  l_ciphertext := encrypt (h_key, h_plaintext)

!

Conclusion: need an escape hatch for practical programming (cf. casting in Java).

References

For more info on everything here, see:

Sabelfeld and Myers, 2003. Language-Based Information-Flow Security.

Volpano, Irvine, and Smith, 1996. A Sound Type System for Secure Flow Analysis.

Denning, 1976. A Lattice Model of Secure Information Flow.