Securing Software
Run-time Enforcement
Goals
- Understand how Control-Flow Integrity (CFI) works
- Analyze the strengths and weaknesses of CFI
- Construct basic control-flow graphs
- Type systems
- Understand what type safety does (and does not) guarantee
- Assess whether a language is strongly typed
CFI
- What is the adversary model for CFI?
- How does this compare to the adversary model for previous defenses we’ve seen (e.g., canaries)?
- What properties does CFI require to be sound?
- What guarantees does CFI give us?
- How does this compare to previous defenses?
-
Why does CFI require a control-flow graph?
- Control Flow Graphs (CFGs)
- What is a basic block?
- How are CFGs defined?
- Building a CFG
- What distinguishes a sensitive vs. an insensitive analysis?
- What properties might an analysis be sensitive to?
- Define soundness vs. completeness
-
Where and how does CFI instrument a binary?
-
How can CFI instrumentation be verified?
-
What’s the performance impact of CFI?
- What kinds of attacks can bypass CFI?
Types
- Why do we need types?
- Why are types necessary for compilation?
- What kinds of properties can types provide?
- Why don’t most type systems support verification?
- What does it mean for a language to be type safe?
- Why is C considered unsafe?
- Give some examples of untyped, weakly-typed, and strongly-typed languages
-
What elements do you need to prove that a language is type safe?
- From safety to security
- How can types be used to encode safety properties?
- What is non-interference? Why does it match our intuitive notion of secrecy?