Download Security via Type Qualifiers: Enhancing Software Security with Qualified Types - Prof. Jef and more Study notes Computer Science in PDF only on Docsity!
Security via Type Qualifiers
Jeff Foster University of Maryland Joint work with Alex Aiken, Rob Johnson, John Kodumal, Tachio Terauchi, and David Wagner CMSC 631, Fall 2004 2
Introduction
- Ensuring that software is secure is hard
- Standard practice for software quality:
- Testing
- Make sure program runs correctly on set of inputs
- Code auditing
- Convince yourself and others that your code is correct CMSC 631, Fall 2004 3
Drawbacks to Standard Approaches
- Difficult
- Expensive
- Incomplete
- A malicious adversary is trying to exploit
anything you miss!
CMSC 631, Fall 2004 4
Tools for Security
- What more can we do?
- Build tools that analyze source code
- Reason about all possible runs of the program
- Check limited but very useful properties
- Eliminate categories of errors
- Let people concentrate on the deep reasoning
- Develop programming models
- Avoid mistakes in the first place
- Encourage programmers to think about security CMSC 631, Fall 2004 5
Tools Need Specifications
put_tty_queue_nolock(c, tty); spin_lock_irqsave(&tty->read_lock, flags); spin_unlock_irqrestore(&tty->read_lock, flags);
- Goal: Add specifications to programs In a way that...
- Programmers will accept
- Scales to large programs
- Solves many different problems CMSC 631, Fall 2004 6 ptr( char) ptr(char) → char
Type Qualifiers
- Extend standard type systems (C, Java, ML)
- Programmers already use types
- Programmers understand types
- Get programmers to write down a little more... const int ANSI C tainted Format-string vulnerabilities kernel (^) User/kernel vulnerabilities
CMSC 631, Fall 2004 7
Application: Format String Vulnerabilities
- I/O functions in C use format strings printf("Hello!"); Hello! printf("Hello, %s!", name); Hello, name!
- Instead of printf("%s", name);
Why not
printf(name);? CMSC 631, Fall 2004 8
Format String Attacks
- Adversary-controlled format specifier name := <data-from-network> printf(name); /* Oops */
- Attacker sets name = “%s%s%s” to crash program
- Attacker sets name = “...%n...” to write to memory
- Yields (often remote root) exploits
- Lots of these bugs in the wild
- New ones weekly on bugtraq mailing list
- Too restrictive to forbid variable format strings CMSC 631, Fall 2004 9
Using Tainted and Untainted
- Add qualifier annotations int printf(untainted char *fmt, ...) tainted char *getenv(const char *) tainted = may be controlled by adversary untainted = must not be controlled by adversary CMSC 631, Fall 2004 10
Subtyping
void f(tainted int); untainted int a; f(a); void g(untainted int); tainted int b; f(b); OK f accepts tainted or untainted data Error g accepts only untainted data untainted ≤ tainted tainted ≤/ untainted untainted < tainted
Demo of cqual
http://www.cs.umd.edu/~jfoster CMSC 631, Fall 2004 12
The Plan
- The Nice Theory
- Polymorphism
- The Icky Stuff in C
CMSC 631, Fall 2004 19
Partial Orders
- Qualifiers Q come with a partial order ≤:
- q ≤ q (reflexive)
- q ≤ p, p ≤ q ⇒ q = p (anti-symmetric)
- q ≤ p, p ≤ r ⇒ q ≤ r (transitive)
- Qualifiers introduce subtyping
- In our example:
- untainted < tainted CMSC 631, Fall 2004 20
Example Partial Orders
- Lower in picture = lower in partial order
- Edges show ≤ relations a b a b c d a b c 2-point lattice Discrete partial order CMSC 631, Fall 2004 21
Combining Partial Orders
- Let (Q 1 , ≤ 1 ) and (Q 2 , ≤ 2 ) be partial orders
- We can form a new partial order, their cross-
product:
(Q 1 , ≤ 1 ) x (Q 2 , ≤ 2 ) = (Q, ≤)
where
- Q = Q 1 x Q 2
- (a, b) ≤ (c, d) if a ≤ 1 c and b ≤ 2 d CMSC 631, Fall 2004 22
Example
- Makes sense with orthogonal sets of qualifiers
- Allows us to write type rules assuming only one set of qualifiers tainted untainted const nonconst
×
tainted const untainted const tainted nonconst untainted nonconst
CMSC 631, Fall 2004 23
Extending the Qualifier Order to Types
- Add one new rule subsumption to type system
Q ≤ Q’
boolQ^ ≤ boolQ’
Q ≤ Q’
intQ^ ≤ intQ’
- Means: If any position requires an expression
of type qt’, it is safe to provide it a subtype qt
G |-- e : qt qt ≤ qt’ G |-- e : qt’ CMSC 631, Fall 2004 24
Use of Subsumption
|-- 42 : int |-- annot(untainted, 42) : untainted int untainted ≤ tainted |-- annot(untainted, 42) : tainted int |-- check(tainted, annot(untainted, 42)) : tainted int
CMSC 631, Fall 2004 25
Subtyping on Function Types
- What about function types?
- Recall: S is a subtype of T if an S can be
used anywhere a T is expected
- When can we replace a call “f x” with a call “g x”?
qt1 →Q^ qt2 ≤ qt1’ →Q’^ qt2’ CMSC 631, Fall 2004 26
Replacing “f x” by “g x”
- When is qt1’ →Q’^ qt2’ ≤ qt1 →Q^ qt2?
- Return type:
- We are expecting qt2 (f’s return type)
- So we can only return at most qt
- qt2’ ≤ qt
- Example: A function that returns tainted can
be replaced with one that returns untainted
CMSC 631, Fall 2004 27
Replacing “f x” by “g x” (cont’d)
- When is qt1’ →Q’^ qt2’ ≤ qt1 →Q^ qt2?
- Argument type:
- We are supposed to accept qt1 (f’s argument type)
- So we must accept at least qt
- qt1 ≤ qt1’
- Example: A function that accepts untainted
can be replaced with one that accepts tainted
CMSC 631, Fall 2004 28
Subtyping on Function Types
- We say that → is
- Covariant in the range (subtyping dir the same)
- Contravariant in the domain (subtyping dir flips) qt1’ ≤ qt1 qt2 ≤ qt2’ Q ≤ Q’ qt1 →Q^ qt2 ≤ qt1’ →Q’^ qt2’ CMSC 631, Fall 2004 29
Dynamic Semantics with Qualifiers
- Operational semantics tags values with
qualifiers
- v ::= x | nQ^ | trueQ^ | falseQ | fun fQ^ (x : qt1) : qt2 = e
- Evaluation rules same as before, carrying the
qualifiers along, e.g.,
if trueQ^ then e1 else e2 → e CMSC 631, Fall 2004 30
Dynamic Semantics with Qualifiers (cont’d)
- One new rule checks a qualifier:
- Evaluation at a check can continue only if the qualifier matches what is expected - Otherwise the program gets stuck
- (Also need rule to evaluate under a check)
Q’ ≤ Q
check(Q, vQ’) → v
CMSC 631, Fall 2004 37
The Solution
- Add a level of indirection to semantics
- Add locations to set of values
- A store S is a mapping from locations to values
- New reduction relation <S, e> → <S’, e’>
- In initial store S, expression e evaluates to e’, resulting in new store S’ CMSC 631, Fall 2004 38
Adding Stores to Old Rules
- Most rules just carry the stores along
- Ordering rules need to thread the store <S, if trueQ^ then e1 else e2> → <S, e1> <S, e1> → <S’, e1’> <S, e1 e2> → <S’, e1’ e2> CMSC 631, Fall 2004 39
Dynamic Semantics for Allocation
<S, e> → <S’, e’> <S, ref e> → <S’, ref e’> loc fresh in S <S, ref v> → <S[loc:v], loc> CMSC 631, Fall 2004 40
Dynamic Semantics for Dereference
<S, e> → <S’, e’> <S, !e> → <S’, !e’> loc in S <S, !loc> → <S, S(loc)> CMSC 631, Fall 2004 41
Dynamic Semantics for Assignment
<S, e1> → <S’, e1’> <S, e1:=e2> → <S’, e1:=e2> loc in S <S, loc:=v> → <S[loc:v], v> <S, e2> → <S’, e2’> <S, loc:=e2> → <S’, loc:=e2> CMSC 631, Fall 2004 42
Subtyping References
- The wrong rule for subtyping references is
- Counterexample let x = ref 0untainted^ in let y = x in y := 3tainted; check(untainted, !x) oops! Q ≤ Q’ qt ≤ qt’ refQ^ qt ≤ refQ’^ qt’
CMSC 631, Fall 2004 43
You’ve Got Aliasing!
- We have multiple names for the same memory
location
- But they have different types
- And we can write into memory at different types x^ tainted untainted y CMSC 631, Fall 2004 44
Solution #1: Java’s Approach
- Java uses this subtyping rule
- If S is a subclass of T, then S[] is a subclass of T[]
- Counterexample:
- Foo[] a = new Foo[5];
- Object[] b = a;
- b[0] = new Object(); // forbidden at runtime
- a[0].foo(); // …so this can’t happen CMSC 631, Fall 2004 45
Solution #2: Purely Static Approach
- Reason from rules for functions
- A reference is like an object with two methods:
- get : unit → qt
- set : qt → unit
- Notice that qt occurs both co- and contravariantly
- The right rule: Q ≤ Q’ qt ≤ qt’ qt’ ≤ qt refQ^ qt ≤ refQ’^ qt’ Q ≤ Q’ qt = qt’ refQ^ qt ≤ refQ’^ qt’ or CMSC 631, Fall 2004 46
Challenge Problem: Soundness
- We want to prove
- Preservation: Evaluation preserves types
- Progress: Well-typed programs don’t get stuck
- Can you prove it with updateable references?
- Hint: You’ll need a stronger induction hypothesis
- You’ll need to reason about types in the store
- E.g., so that if you retrieve a value out of the store, you know what type it has CMSC 631, Fall 2004 47
Type Qualifier Inference
- Recall our motivating example
- We gave a legacy C program that had no information about qualifiers
- We added signatures only for the standard library functions
- Then we checked whether there were any contradictions
- This requires type qualifier inference CMSC 631, Fall 2004 48
Type Qualifier Inference Statement
- Given a program with
- Qualifier annotations
- Some qualifier checks
- And no other information about qualifiers
- Does there exist a valid typing of the
program?
- We want an algorithm to solve this problem