03computer and network securitya---Control Hijacking

The course is mainly about Control Hijacking.Generally covered Defenses:Preventing hijacking attacks;Platform Defenses:Marking memory as non-execute,ASLR Example,kBouncer;Hardening the executable:Canary Types;Control Flow Integrity and so on.
展开查看详情

1.Control Hijacking Control Hijacking: Defenses

2.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 ⋮

3.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

4.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

5.Preventing hijacking attacks Fix bugs : Audit software Automated tools: Coverity , Prefast /Prefix. Rewrite software in a type safe languange (Java, Go, Rust) 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

6.Control Hijacking Platform Defenses

7.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 DEP: since XP SP2 ( 2004) Visual Studio: / NXCompat [:NO] Limitations : Some apps need executable heap (e.g. JITs). Can be easily bypassed using Return Oriented Programming (ROP)

8.Examples: DEP controls in Windows DEP terminating a program

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

10.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) ret execve ("/ bin / sh ") ret Stack (set by attacker): overflow- str 0x408400 0x408500 0x408300 Stack pointer moves up on pop ret- addr

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

12.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 )

13.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

14.A very different idea: 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) pop rdi ret pop rsi ret pop rax ret syscall ret kernel kBouncer

15.A very different idea: 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 ret s are normal Requires no app. code changes, and minimal overhead Limitations: attacker can ensure 16 calls prior to syscall are valid pop rdi ret pop rsi ret pop rax ret syscall ret kernel kBouncer

16.Control Hijacking Defenses Hardening the executable

17.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. str ret sfp local top of stack canary str ret local canary Frame 1 Frame 2 sfp

18.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.

19.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

20.StackGuard enhancements: ProPolice ProPolice (IBM) - gcc 3.4.1. ( - fstack -protector ) Rearrange stack layout to prevent ptr overflow. args ret addr SFP CANARY local string buffers local non-buffer variables Stack Growth pointers, but no arrays String Growth copy of pointer args Protects pointer args and local pointers from a buffer overflow

21.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

22./GS stack frame args ret addr SFP CANARY local string buffers local non-buffer variables Stack Growth pointers, but no arrays String Growth copy of pointer args exception handlers Canary protects ret- addr and exception handler frame

23.Evading /GS with exception handlers When exception is thrown, dispatcher walks up exception list until handler is found (else use default handler) high mem next handler next handler next handler 0xffffffff buf SEH frame SEH frame 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 next

24.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.

25.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)

26.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 ⋯ ret addr C A N A R Y local buffer ⋯ ret addr C A N A R Y local buffer ⋯ ret addr C A N A R Y local buffer ⋯ A B C C A crash crash No crash No crash

27.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 ⋯ ret addr C A N A R Y local buffer ⋯ ret addr C A N A R Y local buffer ⋯ ret addr C A N A R Y local buffer ⋯ A B C C A crash crash No crash No crash

28.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 dest ret-addr sfp top of stack src buf ret-addr sfp Libsafe strcpy main

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