… in memory: an evolution of attacks
Mathias Payer <mathias.payer@nebelwelt.net> UC Berkeley
Images (c) MGM, WarGames, 1983
in memory: an evolution of attacks Mathias Payer - - PowerPoint PPT Presentation
in memory: an evolution of attacks Mathias Payer <mathias.payer@nebelwelt.net> UC Berkeley Images (c) MGM, WarGames, 1983 Memory attacks: an ongoing war Vulnerability classes according to CVE Memory attacks: an ongoing war David
Mathias Payer <mathias.payer@nebelwelt.net> UC Berkeley
Images (c) MGM, WarGames, 1983
Vulnerability classes according to CVE
memory safety for performance
– Programmer in control of all checks
written in C / C++ prone to memory bugs
– Protect integrity through low-level security policy
due to missing / faulty safety check
– Exploitable only if address or value input dependent – Attacker sees all memory, controls writable memory
void vulnerable(int user1, int *array) { // missing bound check for user1 array[user1] = 42; }
void vulnerable(char *buf) { free(buf); buf[12] = 42; }
void vulnerable() { char buf[12]; char *ptr = buf[11]; *ptr++ = 10; *ptr = 42; }
1 3 2 4 4'
– Function return – Indirect jump – Indirect call
– Return-oriented programming – Jump-oriented programming
void vuln(char *u1) { // assert(strlen(u1)) < MAX char tmp[MAX]; strcpy(tmp, u1); return strcmp(tmp, "foo"); } vuln(&exploit); return address saved base pointer tmp[MAX] 1st argument: *u1 next stack frame
Memory safety Integrity Randomization Flow Integrity Attack
*C &C *&C Violation
Control-flow hijack
void vuln(char *u1) { // assert(strlen(u1)) < MAX char tmp[MAX]; strcpy(tmp, u1); return strcmp(tmp, "foo"); } vuln(&exploit); return address saved base pointer tmp[MAX] 1st argument: *u1 next stack frame don't care don't care points to &system() ebp after system call 1st argument to system()
Code Heap Stack C
Memory safety Integrity Randomization Flow Integrity Attack
*C &C *&C Violation
Control-flow hijack
Stop memory corruption
– Safe dialects of C/C++:
CCured, Cyclone
– Retrofit on C/C++:
SoftBounds+CETS
– Rewrite in safe language:
Java/C#
Memory safety Integrity Randomization Flow Integrity Attack
*C &C *&C Violation
Control-flow hijack
Enforce integrity of reads/writes
– Write Integrity Testing – (DEP and W^X for code)
Memory safety Integrity Randomization Flow Integrity Attack
*C &C *&C Violation
Control-flow hijack
Probabilistic defenses
– Randomize locations,
code, data, or pointer values
Memory safety Integrity Randomization Flow Integrity Attack
*C &C *&C Violation
Control-flow hijack
Protect control transfers
– Data-flow integrity – Control-flow integrity
static control flow graph (CFG)
– Use points-to analysis to get CFG – Runtime check if target in static set
– Imprecision of static analysis, runtime concerns – One set each for indirect calls, jumps, and returns
1 3 2 4
– Imprecision leads to ambiguities
– Support for dynamic libraries challenging
– Current implementations (greatly) over-approximate
target set to achieve performance and compatibility
Memory safety Integrity Randomization Flow Integrity Bad things
C *C D *D &C *&C &D *&D Memory corruption
Code corruption Data-only Control-flow hijack
– Simple, powerful and hard to detect
Code Heap Stack D
– Execute code if eXecutable bit set
– Mitigates against code corruption attacks – Low overhead, hardware enforced, widely deployed
– No-self modifying code supported
Memory safety Integrity Randomization Flow Integrity Bad things
C *C D *D &C *&C &D *&D Memory corruption
Code corruption Data-only Control-flow hijack
– Probabilistic defense – Depends on loader and OS
– Prone to information leaks – Some regions remain static (on x86) – Performance impact (~10%)
– Performance degradation on x86
Memory safety Integrity Randomization Flow Integrity Bad things
C *C D *D *&C *&D Memory corruption
Code corruption Data-only Control-flow hijack
&C &D
– Compiler modifies stack layout – Probabilistic protection
– Prone to information leaks – No protection against targeted writes / reads
Memory safety Integrity Randomization Flow Integrity Bad things
C D *D &C *&C &D *&D Memory corruption
Code corruption Data-only Control-flow hijack
*C
– Code integrity: W^X – Code pointer integrity: canaries and safe exceptions – Data integrity: none
– Address Space Layout Randomization
Memory safety Integrity Randomization Flow Integrity Bad things
C *C D *D &C *&C &D *&D Memory corruption C
Code corruption Data-only Control-flow hijack
*C &C &D
Code corruption Data-only Control-flow hijack
Memory safety Integrity Randomization Flow Integrity Bad things
C *C D *D &C *&C &D *&D Memory corruption C
Code corruption Data-only Control-flow hijack
*C &C &D
Code corruption Data-only Control-flow hijack
consideration, sir, I've come to the conclusion that your new defense system sucks.
– More than 10% is not feasible
– Shared library support, no code modifications
– Protection against complete classes of attacks
(c) MGM
– … but memory safety has high overhead – SoftBounds+CETS reports up to 250% overhead
– Compiler analysis can help – Tricky engineering to make it work
– Enables preciser security checks
Application Kernel
Sandbox Application Kernel Loader System call policy
Original code
1 3 2 4
Protected code
1' 3' 2' 4' Dynamic binary translator
– We need protection against memory vulnerabilities – Performance, legacy, compatibility
– Secure execution platform for legacy code
Pictures (c) MGM