Protecting application integrity and confidentiality in the presence of fatal vulnerabilities
Principal Investigator: Mathias Payer
On current systems, programs are written in low-level languages like C or C++ which are prone to memory corruption errors. Such vulnerabilities are used to compromise the integrity and confidentiality of running systems, to execute attacker-controlled code, and to exfiltrate sensitive data. While finding and fixing bugs is important, some bugs will very likely remain. Our research focuses on making systems resilient against attack vectors in the presence of unpatched vulnerabilities. By leveraging compiler-based and binary-translation-based tools we enforce additional security policies on the running software to guarantee the integrity, confidentiality, and availability of systems. Two recent examples of successful research projects are Code-Pointer Integrity, a compiler-based safety mechanism and Lockdown, a binary-only Control-Flow Integrity mechanism that supports legacy software.
Data Confidentiality and Integrity
Ideally, memory safety protects systems against memory corruption attacks. Unfortunately, retrofitting memory safety to low-level languages results in prohibitive performance overhead. To restrict overhead, Code-Pointer Integrity restricts memory safety guarantees to code pointers and sensitive data, allowing fast access to regular data and protecting sensitive data from illegal modification. The Code-Pointer Integrity property protects applications from control-flow hijack attacks and stops any code reuse attack. Data Confidentiality, an extension of Code-Pointer Integrity identifies sensitive data (e.g., cryptographic keys) and protects the confidentiality of this data alongside the control data structures. Data Confidentiality ensures that vulnerabilities cannot be used to exfiltrate sensitive data from a program and therefore also protects against vulnerabilities like Heartbleed.
Compiler-based solutions require a recompilation of software to enforce protection. Unfortunately, we do not always have access to the source code of a system. Lockdown leverages binary analysis to recover control flow graphs of an application and enforces Control-Flow Integrity, a well accepted security policy that protects against code reuse attacks, on legacy, binary-only software at reasonably low overhead. Lockdown is limited by the precision of the binary analysis but makes attacks against legacy software significantly harder and is a convincing option for binary-only software.
Vulnerabilities are common both in software where we have source code and also in legacy systems. Source-based solutions allow lower performance overhead and stronger security guarantees while binary-only solutions protect legacy systems with strong policies at reasonable overhead. We design and develop novel deterministic defense mechanisms that protect software against classes of vulnerabilities (compared to partial solutions that only continue the arms race between attackers and defenders). Our current focus is to design protection mechanisms against memory corruption, the most common type of vulnerability used for attacks. But we are also looking at type confusion and other types of vulnerability classes, extending our framework to protect software against different types of vulnerabilities.
Students: Scott Carr Ahmed Hussein (co-advised with Tony Hosking) Nathan Burow Kyriakos Ispoglou Priyam Biswas Derrick McKee Hui Peng Yuseok Jeon Abe Clements (co-advised with Saurabh Bagchi)
Control-Flow Bending: On the Effectiveness of Control-Flow Integrity
Nicholas Carlini, Antonio Barresi, Mathias Payer, David Wagner, and Thomas R. Gross.
In SEC'15: 24th Usenix Security Symposium, 2015
Fine-Grained Control-Flow Integrity through Binary Hardening
Mathias Payer, Antonio Barresi, and Thomas R. Gross.
In DIMVA'15: 12th Conference on Detection of Intrusions and Malware and Vulnerability Assessment, 2015
Volodymyr Kuznetsov, Mathias Payer, Laszlo Szekeres, George Candea, Dawn Song, and R. Sekar.
In OSDI'14: 11th Usenix Symposium on Operating Systems Design and Implementation, 2014
Keywords: compiler-based and runtime defenses, memory safety, software systems