2005. Programming Languages Security - A Survey (798438), страница 9
Текст из файла (страница 9)
This helps inproviding complete security, as an attacker that acquirescontrol of the execution, cannot sidestep the checks andskip straightaway to the sandboxed operation. This ispossible due to the control transfer restrictions.The shepherding techniques have been implemented in DynamoRIO (Runtime Introspection and Optimization) [8, 9] arun-time code modification system that allows code transformations on any portion of a program, while it executes. “Theresulting system imposes minimal or no performance overhead, operates on unmodified native binaries, and requires nospecial hardware or operating system support” [48].To reduce interpretation overhead, program shepherdingperforms security checks only once, and if the code compliesit is placed in a code cache. The code cache is protected frommalicious modification, so future executions of the trustedtypedef {<type> *value;<type> *base;unsigned size;enum Heap=O, Local, Global storageClass;16int capability; /*plus FOREVER and NEVER*/} SafePtr<type>;arguments tofunctionMemory bounds errors are checked at run-time by comparing against the base and size fields of the extended pointerstructures.The compiler transforms conventional C programs in threesteps:function’s return addressstackgrowthcanaryhigher addressedmemorystringgrowthsaved frame pointer• pointer conversion: pointer definitions and declarationsare transformed to the extended structures that incorporate object attributes.local variables(including buffers)• run-time check insertion: checks are inserted ahead ofevery pointer and array access to detect memory accesserrors.lower addressedmemoryFigure 4: The StackGuard Stack Structure• operator conversion: operations on pointers must bemodified to interact properly with the extended safepointer structure.base address of the contiguous region it is pointing to, o is theoffset to that region and f is a cast flag that indicates if thepointer may refer to a value other than its static type.The integer rendering of a pointer is its base + offset.
Whena pointer is cast to an integer the result is a fat integer of theform – ptr(b, o, 1), allowing the integer to be cast backto a pointer if desired.Dereferencing of invalid pointers (pointers that refer to alocation outside of a valid region) is prevented by insertion ofbounds checks. These checks use the base address and offsetof the pointer.If the cast flag of a pointer is unset (i.e. f = 0), the correct type of value is guaranteed to be read and hence no typechecking is required during such pointer dereferences.
Alternatively a value read using a pointer with f = 1 may have anincorrect type, and hence type checking of such values is required.Dangling pointer dereferences are prevented by markingfreed memory regions as “already released” but not actuallyreleasing them. The size field of such fields is set to zero. Thisforbids access to that block, preventing dangling pointers.Programs compiled by the current Fail-Safe C compilerhave been found to be 30% to 500% slower than the originalC programs [65].Details about the Fail-Safe C Project can be obtained fromits webpage [27].The run-time library prevents dangling pointer dereferences by maintaining a capability store. The capability storekeeps track of all dynamically allocated storage by monitoring allocation, deallocation and memory access events [53].The set of capabilities in the capability store represents all thedynamic storage that is currently active.Safe-C requires few modifications to C source code and isa good tool for making legacy code safe.
It however provideslimited safety guarantees at a high price (130% to 540%) dueto exhaustive run-time checks (memory bounds checks andcapability database queries). Also, the extended pointer structures increase the spatial overhead, as each pointer now holdsadditional information. It is mainly useful for program debugging.The source release for SCC version 1.0.0 is not publiclyavailable, details on its distribution can be obtained from itswebpage [77].Fail-Safe ANSI-C compilerThe Fail-Safe ANSI-C compiler [66] supports the fullANSI C standard while preventing unsafe operations. Theauthors of the compiler define an “unsafe operation” to bean “operation that leads to “undefined behavior”, such as array boundary overrun and dereference of a pointer in a wrongtype.”The compiler introduces run-time checking code into programs to prevent corruption of memory data structures bybuffer overflows or dangling pointer deferences.
Violationsof these checks causes an error to be reported and programexecution to be terminated.The compiler uses fat pointers which are a combinationof three values, denoted by ptr(b, o, f), where b is theStackGuardStackGuard [19] is an extension to gcc (GNU C Compiler,part of the GNU Compiler Collection), that can be configuredto either detect or prevent stack smashing attacks.To modify the function’s return address, buffer overflowattacks need to overwrite all the stack data contained betweenthe overflown buffer and the higher addressed function returnaddress. Stackguard attempts to detect a return address modi17arguments tofunctionhigher addressedmemoryProPolice places the “canary” before the frame pointer soas to detect attacks that leave the return address intact butmodify the frame pointer [49].
It supports only a randomXOR canary. The ProPolice stack structure is shown in inFigure 5.Since it is a compile-time tool, it is able to alter the structure of the stackframe. It does this to place all buffers afterpointers to prevent pointer subversion that could be used tooverwrite arbitrary memory addresses. Functions are also provided protected from argument overwriting by creating localcopies of pointer arguments.ProPolice was implemented as a patch to GCC 3.x andis currently standard and enabled by default in some Unixoperating systems such as, OpenBSD, DragonFly BSD andIPCop Linux distribution. It is also standard in GentooLinux, but here the protection is not turned on by default.An unintrusive implementation is included in the GCC 4.1release.function’s return addressstackgrowthsaved frame pointercanarystringgrowthbufferslocal variableslower addressedmemoryFigure 5: The ProPolice Stack Structurefication by placing a “canary” (known value placed between abuffer and control data) before the return address on the stack.When the function returns, the canary value is checked priorto jumping to the return address, if it has been altered an erroris reported and the program terminated, if it has not, the canary is removed and the function returns normally.
The StackGuard stack structure is shown in in Figure 4.Stackguard supports three types of canaries:RADReturn Address Defender (RAD) [14] is a compiler patchthat stores a copy of return addresses in safe areas that it creates, and inserts necessary safeguarding code into functionprologues and epilogues to defend against buffer overflow attacks. It does not require a change in the structure of stackframes, and so binary code generated by it is compatible withother existing object files and libraries. The copy of the returnaddresses are stored in a region of the data segment called Return Address Repository (RAR), the incorruptibility of whichis ensured by marking surrounding regions as read-only.
Priorto returning from a called function, the return address on thestackframe is checked against the address in the RAR, only ifthey match is the return address considered safe.RAD provides two ways to protect the return addresses inRAR:• Random canary – a random value (32-bit number) unknown to the attacker that is generated at program initialization.• Terminator canary – a known value built of terminationsymbols for standard C library functions; 0 (NULL), CR,LF, and -1 (EOF).• Random XOR canaries – random canaries that areXORed with the return address.
If either value is corrupted the canary value is wrong.• Minezone RAD : The mid-section of a global integer array is declared as RAR, and the initial and final sections are marked as read-only (minezones). This preventsoverwriting the middle of the RAR, where the return addresses are stored.There are several ways to bypass StackGuard [74].StackGuard existed as patches for gcc versions up to 2.95,but is no longer available.ProPoliceThe “Stack-Smashing Protector” or SSP, also known asProPolice [25] is a patchset for gcc, designed to protect applications from buffer overflow attacks, based on a protectionmethod that automatically inserts checking code into an application at compile time.The main ideas are the rearranging of local variables soas to place pointers before buffers in memory so as to avertpointer corruption, and the skipping of instrumentation codefrom some functions to reduce performance overhead.• Read-Only RAD : The whole RAR is marked as readonly and is writable only in function prologues whena new address is to be added to it.
As the RAR isset as read-only, updating it in function prologues requires adding two extra system calls to each functioncall, which results in a serious performance penalty.“MineZone RAD is more efficient while Read-Only RARis more secure” [14].18Possible address storage inconsistencies that could becaused by the system calls setjmp() and longjmp() arealso dealt with correctly.System administrators are able to detect intrusions whenthey happen as when an attack is detected, RAD sends out anemail in real-time before it terminates the attacked program.Programs protected by RAD undergo a deteriorationin performance of between 1.01 to 1.31. It is a patch togcc-2.95.2; further details on availability can be got fromhere [72].The protection offered by these tools can usually be enabledor disabled via specific flags.Bhatkar, Sekar and DuVarneyBhatkar et al. have implemented an address space randomization (ASR) technique, whereby the absolute locations aswell as relative distances of all code and data objects are randomized at the start of program execution (i.e.
different randomizations each time the program is run). It is implementedas a source-to-source transformation which is compatible withlegacy C code. Experimental results demonstrate an averagerun-time overhead of about 11%. The approach has a limitedgoal: “it only seeks to ensure that the results of any invalidaccess are unpredictable” [76]The approach is based on the address obfuscation [4]concept, whose goal is to obscure the location of objectsin memory by rearranging their positions. The techniques[4, 28, 69, 99] that have been developed to achieve this donot provide comprehensive protection against all memory error exploits, and are vulnerable to relative-address attacks, information leakage attacks, and brute-force attacks [83].