David Brumley, PongsinPoosankam, Dawn Song and Jiang Zheng Automatic Patch-Based Exploit Generation is Possible:Techniques and Implications Presented by Nimrod Partush
Outline • Introduction & Motivation • Problem Definition • Problem Solution • 3 Step Plan • Demos • Discussion & Conclusions
Security patches are good • Good software vendors constantly review and test their products’ security • They periodically release patches for new found security bugs • This is bad, apparently.
Security patches are bad • Common attacker practice: manually review the patch in reference to the original program • Changes can infer security bugs in the original program • Quickly create an attack (exploit) and compromise un-patched systems • Our goal: Make the attacker’s life easier. • Not really
The Automatic Patch-Based Exploit Generation Problem • Given a program P and a patched version of the program P’, automatically generate an exploit for the potentially unknown vulnerability present in P but fixed in P’ • Show this is feasible. • Thus raise awareness that an attacker with a patch should be considered as armed with an exploit
A scary equation • Windows Update takes 24 hours to reach 80% of the clients + • A worm (slammer for instance) can spread to most vulnerable clients in minutes + • The paper claims to generate an exploit within minutes = • Millions of compromised clients for every patch release
The attacker experience if (input % 2 == 0) goto 2 else goto 4; s := input+2; goto 5; s := input+3; ; ptr := realloc(ptr,s); // use ptr, ptr, … ptr[input-1] • Exploit this: • How about now? * Based on the DSA_SetItem IE Vulnerability 232 – 3 ≤ input ≤ 232 – 1 if (input % 2 == 0) goto 2 else goto 4; s := input+2; goto 5; s := input+3; if (s>input) goto 6 else goto ERROR; ptr := realloc(ptr,s); // use ptr, ptr, … ptr[input-1]
Exploitable inputs All Inputs Safe Inputs
Challenges • Pin-point the bug • Within millions of binary instructions • Correlate it to the original code • Not every code addition is a vulnerability fix • Ignore feature addition, etc. • A line of code is just a line of code • Remember that input is needed to exploit the bug.
Input sanitation is key • Observation: input validation bugs are usually fixed by adding missing sanitation checks. • Pick on those, leave the rest. • Intuition: input that fails the sanitation check in P’ is likely an exploit for P. • Easily verified by running them
Game Plan • Identify new sanitation checks in P’ • Generate candidate exploit input • Calculate weakest precondition to fail the check, a formula is generated • Use a solver to find an input that satisfies the formula • Verify as an exploit • Define a “security policy” • Check for violations using external checkers
Step 1: Binary Diffing • An off-the-shelf solution, EBDS, is used to find new sanitation checks. • Within function bounds • Purely syntactical • Problem: • i > 10 differs from i – 1 > 9 • Solution: • The verification step will overcome this.
Step 2: Generate candidate exploit if (input % 2 == 0) goto 2 else goto 4; s := input+2; goto 5; s := input+3; if (s>input) goto 6 else goto ERROR; ptr := realloc(ptr,s); // use ptr • We generate a formula that encapsulates the program paths that lead to the sanitation check • We do this by collecting constrains deduced from the instructions and conditionals. • The X86 instruction set was modeled in Vine. • F(input) = ((input % 2 == 0) and (s == input +2(mod 232))) and !(s > input) • Problem: Usually only a fraction of all paths that lead to the check are exploitable
Static Vs. Dynamic if (input % 2 == 0) goto 2 else goto 4; s := input+2; goto 5; s := input+3; if (s>input) goto 6 else goto ERROR; ptr := realloc(ptr,s); // use ptr • Reducing the number of paths will result in faster and more successful analysis • 3 approaches: • Pure Static • Consider all possible executions that lead to the test. • F(input) =(( (input % 2 == 0) and (s == input +2(mod 232)) ) or ( (input % 2 != 0) and (s == input +3(mod 232)) ))and !(s > input) • Pure Dynamic • Pick an path from a known trace, build constraints and fail the test. • F(input) =( (input % 2 == 0) and (s == input +2(mod 232)) ) and !(s > input) • Half and half • For a known input, build constraints for a potion of the path and consider all paths for the rest.
Formula -> Exploit • The STP constraint solver was used to generate exploits • Supports bit operations • An iterative process.
Step 3: Verify the exploit • Define a “Security Policy” • A predicate on the program state space that indicates whether a certain attack occurred • Generic • Control flow hijacking – return address integrity. • Information disclosure – read beyond bounds. • Denial of service – crash. • Basically a monitoring tool is used to see if warnings are raised. • Sometimes TEMU • Mostly run and crash
Results • 5 real world exploits for MS programs derived from patches. • Some previously unknown • Patch generated within minutes. • Polymorphic exploits • Abuse anti-virus signature writers
Advantages • Real life exploits exposed • Fast and (semi) automatic exploit production • Interesting dynamic + static integration • Work on binaries
Disadvantages • As strong as the weakest tool its build upon • Binary diffing is sometimes weak. • Input sanitation oriented • Easily manipulated • Needs run traces • The purely static approach usually fails • Works on binaries
Conclusions & Solutions • Finding and fixing security bugs will expose the software to attacks • Patch release strategies need to change • Fast patch distribution • P2P • Patch encryption • Patch obfuscation