650 likes | 1.23k Views
Defending Embedded Systems Against Buffer-Overflow Attacks via Hardware/Software Zili Shao, Ph.D. Candidate Dept. of Computer Science University of Texas at Dallas Email: zlshao@student.utdallas.edu Hompage: http://www.utdallas.edu/~zlshao Stack Overflow – Intel Low Address
E N D
Defending Embedded Systems Against Buffer-Overflow Attacks viaHardware/Software • Zili Shao, Ph.D. Candidate • Dept. of Computer Science • University of Texas at Dallas • Email: zlshao@student.utdallas.edu • Hompage: http://www.utdallas.edu/~zlshao
Stack Overflow – Intel Low Address • copy(char *msg) • { • char buf[5]; • strcpy(buf, msg); • } • main(int argc, char *argv[]) • { • if( argc> 1) • copy(argv[1]); • } Buf[0] Buf[1] Attack Code Buf[2] Buf[3] Buf[4] bp main-bp ret addr. argv[1] bp main-ret-bp main-ret-bp before High Address
Stack Overflow – Sun Sparc sp • Harder than Intel, still easy • Ret. Addr. in register i7 • 4-byte alignment • copy(char *msg) • { • char buf[5]; • strcpy(buf, msg); • } • main(int argc, char *argv[]) • { • if( argc> 1) • copy(argv[1]); • } Current Register Windows buf[0] buf[4] fp sp l 0 Attack Code Current Register Windows i6 - fp’s value i7 - ret addr. from main() i 6 i 7 fp High Address Before call copy() After call copy()
Organization • Motivation • Background for Buffer Overflow • The Previous Work • Hardware/Software Defender (HSDefender) • Conclusion
Buffer Overflow Attack Causes Serious Problems • At least 50% of today's widely exploited vulnerabilities are buffer overflows and the ratio is increasing over time. • In 2003, buffer overflow related vulnerabilities account for 85.7% (24 of 28) of the serious vulnerability reports from CERT advisories. • Almost all effective worms use this vulnerability to attack.
Worm & Buffer Overflow • Almost all the worms used it. Some famous examples caused serious damages: • Internet worm in 1988 - Buffer overflow in fingerd • Code Red, Code Red II, etc. in 2001, MS Index Service DLL • Sapphire (SQL Slammer) in Jan. 2003, MS SQL Server • MS Blaster in August 2003, MS DCOM RPC • Witty Worm in Mach 20, 2004, ISS Protocol Analysis • Model for ICQ Instant Message Protocol • Sasser Worm in May 2004, LSASS buffer overflow
2003 CERT Serious Vulnerability Reports • 2003 serious vulnerability reports from CERT (Total: 28, buffer overflow-related: 24) • 19 directly used stack overflow or heap overflow • 2 used integer overflow that causes heap overflow • 2 used memory de-allocation bug that causes heap overflow • 1 used format string vulnerabilities that is exploited similar to buffer overflow • The other 4 reports are related: - Protocol-based attacks - Weak password attacks for home computers - CISCO packet error - kmod/ptrace bug in Linux.
The Security for Critical Systems • Buffer overflow attack is serious for special purpose systems • Routers • Network base stations, Wireless devices • Important security concern for networked embedded systems: • a battleship with thousands of embedded processors • an aircraft control system • a nuclear plant with network embedded controller • For such critical or military application, the hostile penetration by using buffer overflow will cause serious damages
Software in Embedded Systems • Most software written in assembly or C • Usually no access control mechanism • Maximum-degree security is required. • Strict requirements: • Timing: Real time system – Performance overhead • Limited memory space – Code Size • Power consumption, area, hardware cost, etc. • Off-the-shelf software components – Source code may not be available for a system integrator.
The Design Flow from System Integrator’s point view System Integrator 1. Requirements & Rules Third-party Software Developer Software Components 3. Checking 2. Generate 1. Requirements & Rules Third-party Software Developer Software Components 3. Checking 2. Generate
Effective Protection & Efficient Checking • A solution should solve two problems: • A complete protection from buffer overflow attacks and the simple rules so software developers can easily follow. • An efficient checking mechanism for a system integrator.
Types of Buffer Overflow Memory Layout • Stack overflow • the most common case • Heap/bss overflow • more and more popular • Related vulnerabilities: • format-string vulnerability • integer overflow Low text section Address data section bss section heap stack High Env. Variables & Command line Parameters Address
Basic Ideas of Stack Overflow • Find a program with stack-overflow vulnerability • Prepare a buffer • Contain a hostile code such as to execute a “shell” • Long enough to overflow a stack frame so the return address is replaced. • Send this buffer as the input to the attacked program • Make the new return address jump to the inserted hostile code that was originally put in the buffer
Stack Overflow – Intel Low Address • copy(char *msg) • { • char buf[5]; • strcpy(buf, msg); • } • main(int argc, char *argv[]) • { • if( argc> 1) • copy(argv[1]); • } Buf[0] Buf[1] Attack Code Buf[2] Buf[3] Buf[4] bp main-bp ret addr. argv[1] bp main-ret-bp main-ret-bp before High Address
Stack Overflow – Sun Sparc sp • Harder than Intel, still easy • Ret. Addr. in register i7 • 4-byte alignment • copy(char *msg) • { • char buf[5]; • strcpy(buf, msg); • } • main(int argc, char *argv[]) • { • if( argc> 1) • copy(argv[1]); • } Current Register Windows buf[0] buf[4] fp sp l 0 Attack Code Current Register Windows i6 - fp’s value i7 - ret addr. from main() i 6 i 7 fp High Address Before call copy() After call copy()
1st Trick for Stack Overflow (Intel) Low Address 2nd overflow: we can write anything there • Example program: • main(int argc, char *argv[]) • { • char *p; • char buf[512]; • p=buf; • strcpy(p,argv[1]); • strcpy(p,argv[2]); • printf(“Finish!\n”); • } Buf[0] Buf[511] GOT p bp old-bp 1st overflow: we can point p to anywhere ret addr. argc argv[1] argv[2] High Address
2nd Trick for Stack Overflow (Intel) Low Address • int good(const char *str); • main(int argc, char *argv[]) • { • int (*fptr)(const char *str); • char buf[512]; • fptr=(int (*)(const char *str)) good; • strcpy(buf,argv[1]); • (void) (*fptr)( argv[2] ); • } • int good(const *str) • { • printf(“I am a good fun.\n”); • return 0; • } Buf[0] Attack Code Buf[511] fptr bp old-bp ret addr. argc argv[1] argv[2] High Address
Heap/bss Overflow • int good(const char *str); • main(int argc, char *argv[]) • { • static char buf[512]; • static int (*fptr)(const char *str); • fptr=(int (*)(const char *str)) good; • strcpy(buf,argv[1]); • (void) (*fptr)( argv[2] ); • } • int good(const *str) • { • printf(“I am a good fun.\n”); • return 0; • } BSS Low Address Buf[0] Attack Code Buf[511] fptr High Address
Previous Work – Summary • Stack Smashing Protection • Non-executable stack • Libsafe • StackShield • Compiler-assisted: StackGuard, Microsoft GS, IBM SSP, StackGhost • Buffer overflow vulnerability checking • The static checking • The dynamic checking • Array & Pointer Protection • Array boundary checks • PointerGuard • Pure Hardware Approach: XOM
Previous Work – Stack Smashing Protection • Non-executable stack • Method: Make the stack be non-executable • Not effective. The attack code can be run from somewhere else, for example, heap/bss attacks • Libsafe • Method: Intercept vulnerable library functions and force verification of critical elements of stacks • Very limited: - Do not work for user defined functions - A lot of attacks that are correct from the verification of vulnerable library functions - Can not protect heap/bss smashing attacks
Previous Work – Stack Smashing Protection • Stack Shield - Runtime Stack Protection • Method: • Store the return address into a different stack • Protect the integrity of return addresses • Disadvantages: • Can only prevent from the attacks that need to overwrite the return address. • Can not defend the attacks like 1st trick and 2nd trick • Can not defend heap/bss overflow
Previous Work – Stack Smashing Protection • StackGuard – Compiler-assisted Runtime Stack Protection • Method: • Changes the prologue and epilogue of a function call. • Push a canary (such as NULL) before the return address in the prologue and check whether the canary has been changed in the epilogue • Preventing the attacks that overwrite the return address. • Disadvantages • Frame pointer is not protected • Can not defend the attacks like 1st trick and 2nd trick • Can not defend heap/bss overflow attacks
Previous Work – Stack Smashing Protection • IBM SSP - Compiler-assisted Runtime Stack Protection • Method: similar to StackGuard. • Put random canary on top of frame pointer and return address • Check before the function is returned. (both fp and ret addr are “protected.”) • Reorder local variables so the pointers cannot be overwritten. • Disadvantages • Can not defend against heap/BSS overflow attack • For some cases, pointers in local variables and function arguments cannot be reordered
Previous Work – Buffer Overflow Checking • The static checking method • Use software tools to analyze the code. • The buffer overflow detection problem is undecideable. • Can not provide a complete solution • The dynamic checking method: Program Testing • Executing program with specific inputs.
Previous work – Pointer Protection • Array & Pointer Boundary Checking • Compiler adds instructions • Too much overhead • Security Checking is not considered • PointerGuard: encrypting pointer values while they are in memory and decrypting pointer values before de-reference. • Easy to cause system crash if system is compromised • Security Checking is not considered
Pure Hardware Approach: XOM • CPU manufacturer puts a unique pair of private key and public key. • A secret key is generated which is used to encrypt all the code and data external to the CPU. • Strong protection for code confidentiality and integrity. • Large hardware overhead. • Even it is not enough: system will be crashed when a warm exploits a stack overflow vulnerability. • Our approach can be combined with XOM.
Part III: Our HSDefender Technique (Hardware/Software Defender)
The Basic Ideas • Hardware / Software Co-design is a common practice in embedded system design. • Design new special “secure call” instruction • Require software developers only use “secure call” instructions for function calls. • The checking for a system integrator is very simple. It is close to one-pass O(n) scan where n is the number of instructions in the program.
HSDefender: Hardware/Software Defender • HSDefender provides an effective solution by the combination of hardware (new instructions) and compiler • HSDefender protects any jump pointer • A jump pointer is a location that stores an address to a codesegment, and the program may jump to the address stored in ajump pointer. A jump pointer can be: • return address in a stack frame • a function pointer • an entry in a shared function pointer table such as GOT.
Classification of Buffer Overflow Attacks • Stack smashing attacks • Most common attacks • Change return address or frame pointer so hostile code can be executed. • Function pointer attacks: • Exploit a function pointer by stack/heap/bss overflow to point to the attack code • Further classify into two sub-categories: - Shared function pointer attacks - Local function pointer attacks
Function Pointer Attacks • Shared function pointer attacks • It is common to have a table of function pointers that point to each shared library functions such as GOT. • Similar to Trick 1. Change some function pointers there by first overflowing stack, heap or BSS. • Local function pointer attacks • First overflow stack, heap, or BSS so a pointer that points to a local function pointer is changed. • Change the function pointer such that it points to the prepared hostile code. Similar to Trick 2.
Two Components of HSDefender • Stack Smashing Attack Protection - two methods: • Hardware Boundary Check • Secure Function Call • Function Pointer Attack Protection • New secure instruction for jumping function pointer: SJMP
Stack Smashing Protection - Method 1: Hardware Boundary Check - Basic Idea • Basic Idea: • Hardware boundary check performs address check with current frame pointer • “address check” is done in parallel with a “write” operation. • If the target address is equal to or bigger than the value of frame pointer, a buffer overflow exception is produced.
Hardware Boundary Check low local vars des-addr should be less than fp previous fp fp return addr. Compare with fp arguments. write to des-addr high
Stack Smashing Protection - Method 1: Hardware Boundary Check - Requirements • Hardware boundary checking protects: • Frame pointers • Return addresses • Function arguments • Requirements for software developers: • If a variable needs to be changed in its child function, then define it as global or static variable or dynamic memory allocation. • Using fp in call convention is required.
Stack Smashing Protection - Method 1: Hardware Boundary Check - Analysis • Easy security checking for system integrator: • Execute the tested program and see whether the stack overflow exception occurs. • System crash can be avoid: • Call a recovery program in the stack overflow exception handler program. • The writing and the boundary checking can be executed parallel; therefore, there is almost no performance overhead. • The extra protection code are not needed
Stack Smashing Protection - Method 2: Secure Function Call – Basic Idea • Basic Idea: • Design two secure function call instructions: “SCALL” and “SRET” to replace old “CALL” and “RET” instructions. • Each process is randomly assigned a key when the process is created and the key is kept in a special register R. • SCALL – Generate a signature of the return address with • the key when a function is called. • SRET – Check the signature with the key before returning from a function.
Secure Function Call low local vars previous fp Generate a Check the signature signature from signature and return address return address return addr. when call when return arguments. high
Stack Smashing Protection - Method 2: Secure Function Call – “SCALL” Design • “SCALL” has four operations: • Push the return address into the stacks; • Generate a signature S by S=XOR(R,Ret), where R stores the key and Ret is the return address; • Push S into the stack; • Put the address of function into Program Counter.
Stack Smashing Protection - Method 2: Secure Function Call – “SRET” Design • “SRET” has 3 operations: • Load T1(SP) T2 (SP+4) where T1, T2 are two temporary registers storing the signature and the return address that were pushed by SCALL. • Calculate S’=XOR(R, T2). • Compare S and S’: If equal, move T2 to the Program Counter; • Otherwise, generate a stack overflow exception.
Stack Smashing Protection - Method 2: Secure Function Call – Analysis • The key is randomly generated for each process, it is extremely hard for a hacker to guess the key. • If the return address is changed by a hacker, it can be found • since two signatures S and S’ will be different. • This is more powerful than StackGuard using a canary, which can be exploited by skipping around the canary to change ret. addr.
Stack Smashing Protection - Method 2: Secure Function Call – Analysis • Easy security checking for system integrators: • Whether there are the original “CALL” instructions in a component based on binary code • Execute it to see whether there is stack overflow exception. • System Crash can be avoided by calling a recovery program in the exception handler program.
Function Pointer Protection – Basic Idea • New secure instructions for the call through function pointer: • Call_SJMP: Ordinary Call (Method 1) + SJMP • Scall_SJMP: Secure Call (Method 2) + SJMP • “SJMP” has two operations: • Generate the Real Address by XORing the input address with • the key • Compare the instruction in the XORed address with a pre-defined flag instruction: • If they are equal, jump to this XORed address; • Otherwise, issue a buffer overflow exception.
Function Pointer Protection – Requirements • Two requirements for software developers: • Software developers must use these secure instructions (“Call_SJMP” or “Scall_SJMP”) for the calls through function pointers. • When assigning the address of function to a function pointer, the address is first XORed with the key and then the XORed result is assigned to the function pointer.
Function Pointer Protection – Analysis • The attack code can not be activated if a hacker changes a function pointer and makes it point to the attack code • The real address that the program will jump to is the XORed address with the key. • The system crash can be avoid in most cases by comparing the instruction in the XORed address with the flag • A system integrator can easily check whether “Call_SJMP” or “Scall_SJMP” has been used in all function calls that use function pointers.
Call Using BL (Branch and Link) • Processors such as ARM, PowerPC, etc. use BL (Branch and Link) call a function, which puts return address into a register lr before Program Counter is changed. And BLR to copy LR to PC. • Secure CALL: use function pointer protection approach to encrypt the value of the return address before it is stored to lr. • Secure RET: decrypt the value and/or check the flag instruction before PC is reset.
Case Study: A FFT/IFFT Program • /* Check whether a pointer is empty*/ • void CheckPointer( ) { } • /* FFT/ IFFT Transformation */ • void fft_float( ) { • /* The added function pointer*/ • void (* fptr) (void *p, char *name); • …… • /* Assign CheckPointer to fptr */ • fptr = (void (*) (void *p, char * name )) • CheckPointer; • /* Perform FFT/IFFT; need to call CheckPointer*/ • …… • (void *) fptr(…); • …… • } • main( int argc, char ** argv) • { • /* Prepare the inputs */ • …… • /* Call fft_float */ • fft_float( ); • …… • }