Control Hijacking: Defenses

Slides:



Advertisements
Similar presentations
ROP is Still Dangerous: Breaking Modern Defenses Nicholas Carlini et. al University of California, Berkeley USENIX Security 2014 Presenter: Yue Li Part.
Advertisements

Defenses. Preventing hijacking attacks 1. Fix bugs: – Audit software Automated tools: Coverity, Prefast/Prefix. – Rewrite software in a type safe languange.
CS457 – Introduction to Information Systems Security Software 4 Elias Athanasopoulos
David Brumley Carnegie Mellon University Credit: Some slides from Ed Schwartz.
CS457 – Introduction to Information Systems Security Software 3 Elias Athanasopoulos
Introduction to Information Security ROP – Recitation 5 nirkrako at post.tau.ac.il itamarg at post.tau.ac.il.
Computer Security: Principles and Practice EECS710: Information Security Professor Hossein Saiedian Fall 2014 Chapter 10: Buffer Overflow.
Computer Security: Principles and Practice First Edition by William Stallings and Lawrie Brown Lecture slides by Lawrie Brown Chapter 11 – Buffer Overflow.
Lecture 16 Buffer Overflow modified from slides of Lawrie Brown.
Basic Control Hijacking Attacks
CMSC 414 Computer and Network Security Lecture 22 Jonathan Katz.
Part III Counter measures The best defense is proper bounds checking but there are many C/C++ programmers and some are bound to forget  Are there any.
Review: Software Security David Brumley Carnegie Mellon University.
Breno de MedeirosFlorida State University Fall 2005 Buffer overflow and stack smashing attacks Principles of application software security.
1 Information Security – Theory vs. Reality , Winter 2011 Lecture 8: Control hijacking attacks Eran Tromer Slides credit: Dan Boneh, Stanford.
Preventing Buffer Overflow Attacks. Some unsafe C lib functions strcpy (char *dest, const char *src) strcat (char *dest, const char *src) gets (char *s)
Windows XP SP2 Stack Protection Jimmy Hermansson Johan Tibell.
Control Hijacking Attacks Note: project 1 is out Section this Friday 4:15pm.
Defenses from Malware. Preventing exploits Fix bugs: – Audit software Automated tools: Coverity, Prefast/Prefix. – Rewrite software in a type safe languange.
Andrea Bittau, Adam Belay, Ali Mashtizadeh, David Maziéres, Dan Boneh
1 RISE: Randomization Techniques for Software Security Dawn Song CMU Joint work with Monica Chew (UC Berkeley)
Eran Tromer Slides credit: Avishai Wool, Tel Aviv University
Lecture 16 Buffer Overflow
CAP6135: Malware and Software Vulnerability Analysis Buffer Overflow II: Defense Techniques Cliff Zou Spring 2012.
CAP6135: Malware and Software Vulnerability Analysis Buffer Overflow II: Defense Techniques Cliff Zou Spring 2013.
Security Exploiting Overflows. Introduction r See the following link for more info: operating-systems-and-applications-in-
Control Hijacking Attacks
Mitigation of Buffer Overflow Attacks
Lecture slides prepared for “Computer Security: Principles and Practice”, 3/e, by William Stallings and Lawrie Brown, Chapter 10 “Buffer Overflow”.
Buffer Overflow CS461/ECE422 Spring Reading Material Based on Chapter 11 of the text.
Exploitation possibilities of memory related vulnerabilities
Buffer Overflow Proofing of Code Binaries By Ramya Reguramalingam Graduate Student, Computer Science Advisor: Dr. Gopal Gupta.
Buffer Overflow Group 7Group 8 Nathaniel CrowellDerek Edwards Punna ChalasaniAxel Abellard Steven Studniarz.
Buffer Overflow Attack Proofing of Code Binary Gopal Gupta, Parag Doshi, R. Reghuramalingam, Doug Harris The University of Texas at Dallas.
Control Hijacking Attacks Note: project 1 is out Section this Friday 2pm (Skilling 090)
CNIT 127: Exploit Development Ch 8: Windows Overflows Part 2.
Buffer overflow and stack smashing attacks Principles of application software security.
SEH overwrite and its exploitability Shuichiro Suzuki Fourteenforty Research Institute Inc. Research Engineer.
CNIT 127: Exploit Development Ch 14: Protection Mechanisms.
Foundations of Network and Computer Security J J ohn Black CSCI 6268/TLEN 5550, Spring 2013.
Security Attacks Tanenbaum & Bo, Modern Operating Systems:4th ed., (c) 2013 Prentice-Hall, Inc. All rights reserved.
Control Hijacking Attacks Note: project 1 is out Section this Friday 4:15pm (Gates B03)
CNIT 127: Exploit Development Ch 8: Windows Overflows Part 1.
VM: Chapter 7 Buffer Overflows. csci5233 computer security & integrity (VM: Ch. 7) 2 Outline Impact of buffer overflows What is a buffer overflow? Types.
Buffer Overflows: Attacks and Defenses for the Vulnerability of the Decade Crispin Cowan SANS 2000.
Chapter 10 Buffer Overflow 1. A very common attack mechanism o First used by the Morris Worm in 1988 Still of major concern o Legacy of buggy code in.
1 Introduction to Information Security , Spring 2016 Lecture 2: Control Hijacking (2/2) Avishai Wool.
CS703 - Advanced Operating Systems By Mr. Farhan Zaidi.
Introduction to Information Security
Mitigation against Buffer Overflow Attacks
Buffer Overflow Buffer overflows are possible because C doesn’t check array boundaries Buffer overflows are dangerous because buffers for user input are.
Basic Control Hijacking Attacks
Introduction to Information Security
The Hardware/Software Interface CSE351 Winter 2013
Basic Memory Corruption Attacks
CAP6135: Malware and Software Vulnerability Analysis Buffer Overflow II: Defense Techniques Cliff Zou Spring 2016.
Introduction to Information Security
Basic Memory Corruption Attacks
CSC 495/583 Topics of Software Security Return-oriented programming
Recitation: Attack Lab
CMSC 414 Computer and Network Security Lecture 21
Software Security.
CS 465 Buffer Overflow Slides by Kent Seamons and Tim van der Horst
Preventing Buffer Overflow Attacks
CAP6135: Malware and Software Vulnerability Analysis Buffer Overflow II: Defense Techniques Cliff Zou Spring 2011.
CAP6135: Malware and Software Vulnerability Analysis Buffer Overflow II: Defense Techniques Cliff Zou Spring 2009.
CNT4704: Analysis of Computer Communication Network Special Topic: Buffer Overflow II: Defense Techniques Cliff Zou Fall 2011.
Return-to-libc Attacks
Presentation transcript:

Control Hijacking: Defenses

Recap: control hijacking attacks Stack smashing: overwrite return address or function pointer Heap spraying: reliably exploit a heap overflow Use after free: attacker writes to freed control structure, which then gets used by victim program Integer overflows Format string vulnerabilities ⋮

The mistake: mixing data and control An ancient design flaw: enables anyone to inject control signals 1971: AT&T learns never to mix control and data

Control hijacking attacks The problem: mixing data with control flow in memory local variables SFP ret addr arguments stack frame data overwrites return address Later we will see that mixing data and code is also the reason for XSS: a common web vulnerability

Preventing hijacking attacks Fix bugs: Audit software Automated tools: Coverity, Prefast/Prefix. Rewrite software in a type safe languange (Java, ML) Difficult for existing (legacy) code … Platform defenses: prevent attack code execution Add runtime code to detect overflows exploits Halt process when overflow exploit detected StackGuard, CFI, LibSafe, … Transform: Complete Breach Denial of service

Control Hijacking Platform Defenses

Marking memory as non-execute (DEP) Prevent attack code execution by marking stack and heap as non-executable NX-bit on AMD Athlon 64, XD-bit on Intel P4 Prescott NX bit in every Page Table Entry (PTE) Deployment: Linux (via PaX project); OpenBSD Windows: since XP SP2 (DEP) Visual Studio: /NXCompat[:NO] Limitations: Some apps need executable heap (e.g. JITs). Can be easily bypassed using Return Oriented Programming (ROP) /NXCOMPAT: tells linker that app is compatible with DEP. :NO indicates don’t use DEP. DEP: data execute prevention

Examples: DEP controls in Windows DEP terminating a program

Attack: Return Oriented Programming (ROP) Control hijacking without injecting code: stack libc.so args ret-addr exec() sfp printf() local buf “/bin/sh” NX wasted effort?

ROP: in more detail To run /bin/sh we must direct stdin and stdout to the socket: dup2(s, 0) // map stdin to socket dup2(s, 1) // map stdout to socket execve("/bin/sh", 0, 0); Gadgets in victim code: dup2(s, 1) ret dup2(s, 0) execve("/bin/sh") Stack (set by attacker): overflow-str 0x408400 0x408500 0x408300 Stack pointer moves up on pop ret-addr

ROP: in even more detail dup2(s,0) implemented as a sequence of gadgets in victim code: 0x408100 0x408200 0x408300 0x408400 5f pop rdi ret 5e pop rsi ret pop rax ret syscall ret c3 c3 Stack (by attacker): overflow-str 0x408100 s 0x408200 0 0x408300 33 0x408400 Dup2(s,0): duplicated socket as stdin. RDI register is socket, RSI register is stdin, RAX is syscall # ret-addr (rdi ⟵ s) (rsi ⟵ 0) (rax ⟵ 33) syscall #33

What to do?? Randomization ASLR: (Address Space Layout Randomization) Map shared libraries to rand location in process memory ⇒ Attacker cannot jump directly to exec function Deployment: (/DynamicBase) Windows 7: 8 bits of randomness for DLLs aligned to 64K page in a 16MB region ⇒ 256 choices Windows 8: 24 bits of randomness on 64-bit processors Other randomization methods: Sys-call randomization: randomize sys-call id’s Instruction Set Randomization (ISR) Combination of NX and ASLR is effective. /DynamicBase: Visual Studio flag to indicate that application works with ASLR.

ASLR Example Booting twice loads libraries into different locations: Note: everything in process memory must be randomized stack, heap, shared libs, base image Win 8 Force ASLR: ensures all loaded modules use ASLR

A very different idea: kBouncer kernel pop rdi ret pop rsi ret pop rax ret syscall ret kBouncer Observation: abnormal execution sequence ret returns to an address that does not follow a call Idea: before a syscall, check that every prior ret is not abnormal How: use Intel’s Last Branch Recording (LBR)

A very different idea: kBouncer kernel pop rdi ret pop rsi ret pop rax ret syscall ret kBouncer Inte’s Last Branch Recording (LBR): store 16 last executed branches in a set of on-chip registers (MSR) read using rdmsr instruction from privileged mode kBouncer: before entering kernel, verify that last 16 rets are normal Requires no app. code changes, and minimal overhead Limitations: attacker can ensure 16 calls prior to syscall are valid

Hardening the executable Control Hijacking Defenses Hardening the executable

Run time checking: StackGuard Many run-time checking techniques … we only discuss methods relevant to overflow protection Solution 1: StackGuard Run time tests for stack integrity. Embed “canaries” in stack frames and verify their integrity prior to function return. Frame 2 Frame 1 top of stack local canary sfp ret str local canary sfp ret str

Canary Types Random canary: Random string chosen at program startup. Insert canary string into every stack frame. Verify canary before returning from function. Exit program if canary changed. Turns potential exploit into DoS. To corrupt, attacker must learn current random string. Terminator canary: Canary = {0, newline, linefeed, EOF} String functions will not copy beyond terminator. Attacker cannot use string functions to corrupt stack.

StackGuard (Cont.) StackGuard implemented as a GCC patch Program must be recompiled Minimal performance effects: 8% for Apache Note: Canaries do not provide full protection Some stack smashing attacks leave canaries unchanged Heap protection: PointGuard Protects function pointers and setjmp buffers by encrypting them: e.g. XOR with random cookie Less effective, more noticeable performance effects

StackGuard enhancements: ProPolice ProPolice (IBM) - gcc 3.4.1. (-fstack-protector) Rearrange stack layout to prevent ptr overflow. args String Growth ret addr Protects pointer args and local pointers from a buffer overflow SFP CANARY local string buffers Stack Growth pointers, but no arrays local non-buffer variables /ProPolice: replicates pointers in arguments to bottom of local vars area. ProPolicy: also called SSP – stack smashing protection. /GS: Arguments, return address, cookie, arrays, local variables, copies of some pointer arguments, alloca copy of pointer args

MS Visual Studio /GS [since 2003] Compiler /GS option: Combination of ProPolice and Random canary. If cookie mismatch, default behavior is to call _exit(3) Function prolog: sub esp, 8 // allocate 8 bytes for cookie mov eax, DWORD PTR ___security_cookie xor eax, esp // xor cookie with current esp mov DWORD PTR [esp+8], eax // save in stack Function epilog: mov ecx, DWORD PTR [esp+8] xor ecx, esp call @__security_check_cookie@4 add esp, 8 Enhanced /GS in Visual Studio 2010: /GS protection added to all functions, unless can be proven unnecessary ANI bug happened because /GS was not applied to function LoadAniIcon() since it did not contain string buffers. Visual Studio 2010 applies /GS protection more aggressively.

local non-buffer variables /GS stack frame args String Growth ret addr Canary protects ret-addr and exception handler frame SFP exception handlers CANARY local string buffers Stack Growth pointers, but no arrays local non-buffer variables /GS: Arguments, return address, cookie, arrays, local variables, copies of some pointer arguments, alloca copy of pointer args

Evading /GS with exception handlers When exception is thrown, dispatcher walks up exception list until handler is found (else use default handler) After overflow: handler points to attacker’s code exception triggered ⇒ control hijack ptr to attack code Main point: exception is triggered before canary is checked 0xffffffff SEH frame SEH frame high mem SEH: structured exception handler next handler buf next next handler next handler

Defenses: SAFESEH and SEHOP /SAFESEH: linker flag Linker produces a binary with a table of safe exception handlers System will not jump to exception handler not on list /SEHOP: platform defense (since win vista SP1) Observation: SEH attacks typically corrupt the “next” entry in SEH list. SEHOP: add a dummy record at top of SEH list When exception occurs, dispatcher walks up list and verifies dummy record is there. If not, terminates process. SAFESEH: safe structured exception handling SEHOP: structured exception handling overwrite protection. Enabled with a regkey DisableExceptionChainValidation.

Summary: Canaries are not full proof Canaries are an important defense tool, but do not prevent all control hijacking attacks: Heap-based attacks still possible Integer overflow attacks still possible /GS by itself does not prevent Exception Handling attacks (also need SAFESEH and SEHOP)

Even worse: canary extraction A common design for crash recovery: When process crashes, restart automatically (for availability) Often canary is unchanged (reason: relaunch using fork) Danger: canary extraction byte by byte ret addr C A N A R Y local buffer ⋯ A crash ret addr C A N A R Y local buffer ⋯ B crash ret addr C A N A R Y local buffer ⋯ C No crash ret addr C A N A R Y local buffer ⋯ C A No crash

Similarly: extract ASLR randomness A common design for crash recovery: When process crashes, restart automatically (for availability) Often canary is unchanged (reason: relaunch using fork) Danger: Extract ret-addr to de-randomize stack location Extract stack function pointers to de-randomize heap ret addr C A N A R Y local buffer ⋯ A crash ret addr C A N A R Y local buffer ⋯ B crash ret addr C A N A R Y local buffer ⋯ C No crash ret addr C A N A R Y local buffer ⋯ C A No crash

What if can’t recompile: Libsafe Solution 2: Libsafe (Avaya Labs) Dynamically loaded library (no need to recompile app.) Intercepts calls to strcpy (dest, src) Validates sufficient space in current stack frame: |frame-pointer – dest| > strlen(src) If so, does strcpy. Otherwise, terminates application top of stack sfp ret-addr dest src buf sfp ret-addr Libsafe strcpy main

How robust is Libsafe? Libsafe strcpy main low memory high memory sfp ret-addr dest src buf sfp ret-addr Libsafe strcpy main strcpy() can overwrite a pointer between buf and sfp.

More methods … StackShield At function prologue, copy return address RET and SFP to “safe” location (beginning of data segment) Upon return, check that RET and SFP is equal to copy. Implemented as assembler file processor (GCC) Control Flow Integrity (CFI) A combination of static and dynamic checking Statically determine program control flow Dynamically enforce control flow integrity

Control flow integrity (CFI) [ABEL’05, …] Ultimate Goal: ensure control flows as specified by code’s flow graph Lots of academic research on CFI systems: CCFIR (2013), kBouncer (2013), FECFI (2014), CSCFI (2015), … and many attacks … void HandshakeHandler(Session *s, char *pkt) { ... s->hdlr(s, pkt) } Compile time: build list of possible call targets Run time: before call, check validity of s->hdlr Builds table of valid function entry points at compile time.

Control Flow Guard (CFG) (Windows 10) Poor man’s version of CFI: Protects indirect calls by checking against a bitmask of all valid function entry points in executable ensures target is the entry point of a function

Control Flow Guard (CFG) (Windows 10) Poor man’s version of CFI: Protects indirect calls by checking against a bitmask of all valid function entry points in executable Does not prevent attacker from causing a jump to a valid wrong function Hard to build accurate control flow graph statically ensures target is the entry point of a function

An example void HandshakeHandler(Session *s, char *pkt) { s->hdlr = &LoginHandler; ... Buffer overflow in Session struct ... } void LoginHandler(Session *s, char *pkt) { bool auth = CheckCredentials(pkt); s->dhandler = &DataHandler; void DataHandler(Session *s, char *pkt); Attacker controls handler Static CFI: attacker can call DataHandler to bypass authentication

Cryptographic Control Flow Integrity (CCFI) Threat model: attacker can read/write anywhere in memory, program should not deviate from its control flow graph CCFI approach: Every time a jump address is written/copied anywhere in memory: compute 64-bit AES-MAC and append to address On heap: tag = AES(k, (jump-address, 0 ll source-address) ) on stack: tag = AES(k, (jump-address, 1 ll stack-frame) ) Before following address, verify MAC and crash if invalid Where to store key k? In xmm registers (not memory)

Back to the example void HandshakeHandler(Session *s, char *pkt) { s->hdlr = &LoginHandler; ... Buffer overflow in Session struct ... } void LoginHandler(Session *s, char *pkt) { bool auth = CheckCredentials(pkt); s->dhandler = &DataHandler; void DataHandler(Session *s, char *pkt); Attacker controls handler CCFI: Attacker cannot create a valid MAC for DataHandler address Example seems a bit complicated add a picture of heap showing Session + buffer next to it

References on heap spraying [1] Heap Feng Shui in Javascript, by A. Sotirov, Blackhat Europe 2007 [2] Engineering Heap Overflow Exploits with JavaScript M. Daniel, J. Honoroff, and C. Miller, WooT 2008 [3] Nozzle: A Defense Against Heap-spraying Code Injection Attacks, by P. Ratanaworabhan, B. Livshits, and B. Zorn [4] Interpreter Exploitation: Pointer inference and JiT spraying, by Dion Blazakis

THE END