Paper Info
- Paper Name: Finding Cracks in Shields On the Security of CFI Mechanisms
- Conference: CCS ‘20
- Author List: Yuan Li, Mingzhe Wang, Chao Zhang, Xingman Chen, Songtao Yang, and YingLiu
- Link to Paper: here
- Food: Cookies
Prerequisites
CFI (Control-flow integrity) is about mitigating attacks which involve control flow hijacking. Essentially, you can restrict the set of addresses that can be executed next from any given point. The way you can demark the “security boundary” for CFI is by saying there are three boundaries: the ideal boundary, the claimed boundary and real boundary. These correspond(?) to theoretical, experimental, and quantitative analyses for evaluation.
- The ideal boundary is the smallest possible set of jump targets necessary to make the program work correctly
- The claimed boundary is estimated by CFI tools using the control flow graphs.
- The real boundary is the list of all possible jump targets that CFI mechanisms actually allow.
In short, the CFI mechanisms try to control the boundaries of the attack and provide strong guarantees against attack. However results showed that most of them are flawed. We further analyzed the root causes of the flaws, and summarized 7 common pitfalls:
- Imprecise Analysis
- Improper Runtime Assumption
- Unprotected Corner Code
- Unexpected Optimization (which disables protection)
- Incorrect Implementation
- Mismatched Specification
- Unintended Targets Introduced by CFI
Background
A good number of CFI mechanisms have been proposed to provide different kind of supports, such as,
- Binary Support : Some CFI solutions such as binCFI, Opaque CFI, etc make special efforts to recover Control Flow Graphs (CFG) from the binaries.
- Modular Support : Modular support is also called the support for dynamically shared objects. Some CFI mechanisms try to deal with the two main issues with respect to modular support.
- Integration of multiple modules which are hardened by CFI separately.
- Integration of CFI protected modules with non-protected modules.
- Dynamically Generated Code Support : Provide CFI support for dynamically generated code by separating the write permission from the dynamic code itself in several ways.
- Hardware Utilization : Some hardware features can help us to improve the performance or security of CFI solutions. For instance, TSX based CFI mechanisms utilize Intel TSX and MPX to ensure that the instrumented code or metadata will not be interfered with or tampered with by attackers and taking advantage of Intel PT and LBR to obtain runtimeinformation.
- Security Guarantees: Source-level CFI solutions utilize type information to provide finer CFG and stronger security guarantees. Some of the CFI mechanisms have well integrated into standard compilers and kernels. Recent dynamic CFI solutions utilize runtime information to improve the precision of CFGs thus further enhancing security guarantees.
Problem
For this paper, our goal is to develop a methodology to evaluate different CFI techniques Designs a technique to answer:
- What is the boundary enforced by the CFI?
- Does the boundary of all possible jump locations match the CFI Enforced boundary?
- Are all the feasible jump targets realistic?
Solution
1. CScan: Feasible Targets Recognition
Evaluate the size of the real boundary through testing possible jump targets. It’s a dynamic analysis - “potentially interesting” ICTs are flagged and breakpointed and the program is driven through attempts to jump to anywhere else by modifying the runtime transfer targets externally. The important thing to find is how different it is from the CFI tool’s claimed boundary. Determining the number of runtime feasible targets is usually done following steps. 1) Examining every indirect control transfer (ICT). Based upon the jump location memory write permissions, flag is raised. Software interrupts are inserted at the flagged locations. 2) At each jump location, system context is saved for the further continuation of the program if security violation handler functions were invoked.
2. CBench: throw an AEG tool at a suite of vulnerable programs and see how well it does. Tests virtual table reuse attacks in addition to ordinary control flow hijack. The important thing to find is “does the attack work?”.
To sum it up, CScan checks how many places a ICT can go and CBench checks how different they are from the claimed boundary and what attacks work?
Discussion
This paper evaluats on “the number of allowed jumps”,however it doesn’t actually evaluate whether the CFI is correct. Second, this papar show no evaluation on scalability - if a technique works really well on toy programs and not at all on real programs, it scores well but is useless. Thrid, it is never described how to quantify the “claimed boundary”. Is this just a piece of metadata which is output by the CFI tool?
In the evaluation aspect, how generalizable is this technique really? There are so many gotchas listed for every evaluated tools, it raises the question of whether the paper actually presents a generalizable strategy for evaluating CFI tools
For techniques evaluated, the number of testset is very small compared to the number of techniques it is claimed that exist (Only 3 are shown vs 56 CFIs) and it’s not clear how they were selected - some of the CFIs which are both popular and available were not tested. The evaluated tools are different between the CScan and CBench evaluations. Another questionable aspect of the claimed generalized methodology of evaluating CFI tools
What will it look like to try to apply these methods to your own CFI tool you are looking to publish?