There's a Hole in the Bottom of the C: On the Effectiveness of Allocation Protection

Memory corruption attacks have been a major vector of compromised computer systems for decades. Memory safety techniques proposed in the literature provide spatial and temporal safety properties to prevent such attacks. Since enforcing full memory safety on legacy languages such as C/C++ often incurs large runtime overhead, recent techniques have created a trade-off between the granularity of enforcement and overhead. By enforcing safety properties at the granularity of allocations instead of objects, these technique incur only a fraction of the overhead. Of particular note, are the recent software-based, so-called "low-fat" schemes, that encode a pointer's bound information in the pointer value itself, thus avoiding a separate metadata store, and additional lookup overhead. In this paper, we show that trading granularity with overhead is insecure. Specifically, we illustrate a new type of attack, which we call Pointer Stretching, that can bypass the recently proposed low-fat schemes using intra-object spatial corruption. Because of the limitations imposed by the low-fat schemes we devise some tricks that allows us to chain ROP gadgets together before a successful stack pivot. We illustrate a real-world exploit against Nginx that successfully hijacks control even when both stack and heap are protected with the software-based low-fat schemes. Furthermore, we show that the vulnerability is inherent in the design of such techniques, and not easily fixable without significant additional implementation and overhead. In addition, we develop an analysis tool to find such vulnerabilities and analyze many popular applications and servers. We find that the exploitable conditions are abundantly found in real-world code bases. Our findings strongly suggest that effective memory defenses must operate at the granularity of objects (and sub-objects) for them to provide meaningful protection against memory corruption attacks.

[1]  James Cheney,et al.  Cyclone: A Safe Dialect of C , 2002, USENIX Annual Technical Conference, General Track.

[2]  Per Larsen,et al.  Address Oblivious Code Reuse: On the Effectiveness of Leakage Resilient Diversity , 2017, NDSS.

[3]  Ahmad-Reza Sadeghi,et al.  Counterfeit Object-oriented Programming: On the Difficulty of Preventing Code Reuse Attacks in C++ Applications , 2015, 2015 IEEE Symposium on Security and Privacy.

[4]  James P Anderson Computer Security Technology Planning Study. Volume 2 , 1972 .

[5]  Miguel Castro,et al.  Baggy Bounds Checking: An Efficient and Backwards-Compatible Defense against Out-of-Bounds Errors , 2009, USENIX Security Symposium.

[6]  Roland H. C. Yap,et al.  Heap bounds protection with low fat pointers , 2016, CC.

[7]  Jonathan M. Smith,et al.  Low-fat pointers: compact encoding and efficient gate-level implementation of fat pointers for spatial safety and capability-based security , 2013, CCS.

[8]  Paul H. J. Kelly,et al.  Backwards-Compatible Bounds Checking for Arrays and Pointers in C Programs , 1997, AADEBUG.

[9]  George Candea,et al.  Code-pointer integrity , 2014, OSDI.

[10]  Milo M. K. Martin,et al.  CETS: compiler enforced temporal safety for C , 2010, ISMM '10.

[11]  Milo M. K. Martin,et al.  SoftBound: highly compatible and complete spatial memory safety for c , 2009, PLDI '09.

[12]  Hovav Shacham,et al.  Return-oriented programming without returns , 2010, CCS '10.

[13]  George C. Necula,et al.  CCured: type-safe retrofitting of legacy code , 2002, SIGP.

[14]  Roland H. C. Yap,et al.  Stack Bounds Protection with Low Fat Pointers , 2017, NDSS.

[15]  Wouter Joosen,et al.  PAriCheck: an efficient pointer arithmetic checker for C programs , 2010, ASIACCS '10.

[16]  Ahmad-Reza Sadeghi,et al.  Isomeron: Code Randomization Resilient to (Just-In-Time) Return-Oriented Programming , 2015, NDSS.

[17]  Per Larsen,et al.  Readactor: Practical Code Randomization Resilient to Memory Disclosure , 2015, 2015 IEEE Symposium on Security and Privacy.

[18]  Olatunji Ruwase,et al.  A Practical Dynamic Buffer Overflow Detector , 2004, NDSS.

[19]  A. One,et al.  Smashing The Stack For Fun And Profit , 1996 .

[20]  Ahmad-Reza Sadeghi,et al.  Just-In-Time Code Reuse: On the Effectiveness of Fine-Grained Address Space Layout Randomization , 2013, 2013 IEEE Symposium on Security and Privacy.

[21]  Fan Long,et al.  Control Jujutsu: On the Weaknesses of Fine-Grained Control Flow Integrity , 2015, CCS.

[22]  Dinakar Dhurjati,et al.  Backwards-compatible array bounds checking for C with very low overhead , 2006, ICSE.

[23]  Hovav Shacham,et al.  The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86) , 2007, CCS '07.

[24]  Zhenkai Liang,et al.  Jump-oriented programming: a new class of code-reuse attack , 2011, ASIACCS '11.

[25]  Dawn Xiaodong Song,et al.  SoK: Eternal War in Memory , 2013, 2013 IEEE Symposium on Security and Privacy.

[26]  David A. Wagner,et al.  Control-Flow Bending: On the Effectiveness of Control-Flow Integrity , 2015, USENIX Security Symposium.