secure programming lecture 6: memory corruption iv ... · É a safe compiler to automatically...
TRANSCRIPT
Secure Programming Lecture 6: MemoryCorruption IV (Countermeasures)
David Aspinall, Informatics @ Edinburgh
30th January 2014
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Lab session tomorrow
The first Secure Programming Laboratory will betomorrow!
Friday 31st January, 2pm-5.30pm in AT 5.04.
Please arrive on time, the lab will start with a demointroduction.
Recommended:
É find someone to work with (pairs rather than largergroups).
É preparation: study the lectures on overflowscarefully, try out some examples.
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Memory corruption attacks
We’ve seen memory corruption attacks on the heap, onthe stack and elsewhere.
Overflow vulnerabilities in code are caused by, forexample:
É unchecked buffer boundariesÉ out-by-one errorsÉ integer overflowÉ type confusion errors
Memory corruption countermeasures
Two basic programming-related countermeasures:
1. Treat the symptoms:É special technologies in execution or compilationÉ limit the damage that can be done by attacksÉ containment and curtailment
2. Treat the causeÉ ensure that code does not contain vulnerabilitiesÉ secure programming through code review,
analysis tools
Question. Why might choice 2 be impossible?
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Generic defences
Defensive technologies are not a real substitute forproper fixes, but:
É give defence in depth security that can protect incase of accidently running malware or regressionsto vulnerable code;
É sometimes code replacement is simply prohibitivelyexpensive or impossible (e.g. non-upgradeablefirmware)
Defences against overflows
Several generic protection mechanisms have beeninvented to prevent overflow attacks and new ones areevolving.
These reduce the attackers chance of reliably exploitinga bug on the host system.
We will look at:
É Tamper detectionÉ Memory protection in OS and hardwareÉ Diversification methods
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Canaries on the stack
Each stack frame includes vulnerable location pointerswhich may be corrupted in a stack overflow attack.
Idea:
É wrap frame with protective layer, a “canary”É canary sits below return addressÉ attacker overflows stack buffer to hit return address
É necessarily overwrites canary
É generated code adds and checks canaries
Early proposal: StackGuard compiler.
Stack without canaries
Stack with canary
Question. How might this mechanism be defeated?
GCC’s Stack Smashing Protector
Consider this C program:
#include <stdio.h>#include <string.h>
int fun1(char *arg) {char buffer[1024];strcpy(buffer,arg);
}
void main(int argc, char *argv[]) {fun1(argv[1]);
}
fun1: ; code without SSPpushl %ebpmovl %esp, %ebpsubl $1048, %espmovl 8(%ebp), %eaxmovl %eax, 4(%esp)leal -1032(%ebp), %eaxmovl %eax, (%esp)call strcpyleaveret
main:pushl %ebpmovl %esp, %ebpandl $-16, %espsubl $16, %espmovl 12(%ebp), %eaxaddl $4, %eaxmovl (%eax), %eaxmovl %eax, (%esp)call fun1leaveret
fun1: ;; code with SSP (main function stays the same);; Note: GS register points to per-CPU thread;; memory storagepushl %ebpmovl %esp, %ebpsubl $1064, %espmovl 8(%ebp), %eaxmovl %eax, -1052(%ebp)movl %gs:20, %eax ; set EAX=canary valuemovl %eax, -12(%ebp) ; store near return addressxorl %eax, %eaxmovl -1052(%ebp), %eaxmovl %eax, 4(%esp)leal -1036(%ebp), %eaxmovl %eax, (%esp)call strcpymovl -12(%ebp), %edx ; EDX=canary from stackxorl %gs:20, %edx ; has it changed?je .L3 ;call __stack_chk_fail ; if it has, we’ll abort
.L3:leaveret
the stack protection spots an overflow with 1026characters:
$ gcc -m32 overflow.c -o overflow.out$ ./overflow.out xxxx$ ./overflow.out ‘perl -e ’print "x"x1025’‘*** stack smashing detected ***: ./overflow.out terminatedAborted (core dumped)
Canary arms race
The arms race in general: attackers respond to newprotection mechanisms by looking for vulnerabilities inthose mechanisms. . .
For example:
É Attack code/probing discovers a constant canaryÉ e.g., canary is 0x0af237ab6, so write that near
return address
É Canary defence uses pseudorandom sequenceÉ attacker learns sequence or discovers seed
É Canary defences uses cryptographic PRNGÉ attacker finds where value is storedÉ finds another exploit to copy it
Effectiveness
É Doesn’t protect against local variable overwritingÉ related protection mechanisms reorder local
variables
É Other attacks work by overwriting parametersÉ aim to change where subsequent writes occurÉ overwrite return address, but don’t return
É Hardened heap implementations have also beendevelopedÉ glibc and Windows since XP SP2 have heap canaries
É Self-managed memory mechanisms not addressedÉ e.g., HLL runtimes, application specific heaps
É Return-oriented programming (ROP)É state-of-the-art: use existing executable codeÉ evades canaries, also defeats NX (see below)
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Operating system separation (review)
Isolation different processes have different resources(address spaces, file systems, . . . )
Sharing resources are shared between processes,partial isolation. Sharing may be:
É all or nothingÉ mediated with access controlsÉ mediated with usage controls (capabilities)
Concern: granularity of protection.
OSes have provided separation mechanisms since theearly days of multi-user systems. For memory, directsupport was added to the CPU and memory systemhardware.
Hardware memory protection mechanisms
Original mechanisms introduced to provide separation(mainly for safety) between different programs onmulti-user systems:
É Fences: separate memory accesses between OSand user code (one boundary, one way protection).
É Base and bounds registers: enforce separationbetween several programs allowing access controlon memory ranges.
É Tagged architecture: more fine-grained, tags oneach memory location set access rights to storedword (R, RW, X). Supervisor mode instructionsrequired to set tag. Not currently supported inmodern architectures.
OS memory segmentation
Segmentation splits a program into many variablesized pieces, each with a name.
É mainÉ dataÉ moduleÉ libraryÉ . . .
É Programs access memory using names and offsets.É Segmentation table maintained by OS, use
segment registers for indexing.
OS memory segmentation
Pros:
É memory locations abstract from physical memoryÉ OS can move things aroundÉ segments can be shared between programsÉ different segments may have different access
rightsÉ user programs cannot access locations outwith
their segments
Cons:
É seg names mapped to the numbers for efficiencyÉ segfaults: must dynamically check boundsÉ fragmentation of memory
OS paging
Paging splits a program into fixed-sized pieces. Theseget mapped onto memory which is split intoequal sized page frames.
Pros:
É fixed sizes easier to manage, avoid fragmentationÉ transparent to programming model
Cons:
É vs segmentation, lose logical control over regionsÉ access control granularity increasedÉ potential for wasted space
Combined paging and segmentation
É Access via segment table + page translationÉ Combines advantages of each.É Designed for efficient memory allocation/relocationÉ Memory protection useful secondary benefit
Modern solution since Multics. Relies on only twoprotection levels supported in the hardware.
Exercise. Why might more protection levels be better?What is the reason only two levels are currentlysupported?
However, complex/portable OSes prefer to use softwareand work over a flat memory model. The x86 and Linuxwork over a flat model.
Non-executable memory pages
CPU have often included R, RW, X protection formemory pages.
É x86 series CPUs added page-level XD/NX in 2001-4
By enforcing non-executable regions, if the programkeeps code and data separate, shellcode can beprevented from running when it’s injected into dataregions on the heap or stack.
É Compared with C, more tricky for certainlanguages/compilers/interpreters, which maymanipulate executable code during runtime.
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Address Space Layout Randomization (ASLR)
Concept: use diversification to make many versions ofsame program; thwarts general attacks that makeassumptions about fixed structure.
ASLR: make it harder to find data or code locations, byrandomising layout during load time. Breakshard-coded static locations.
Implemented in Linux by the PaX Team.
Effectiveness: good, but doesn’t remove mainvulnerability and vulnerabilities in ASLR implementationbecome target of attack. Early implementationsrandomised by small amounts (e.g. 256 addresses), soattacker could use brute force to find the vulnerablelocations. Such attacks may attract attention (sincefailures cause crashes).
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Defensive programming: bounds checking
Defensive programming to avoid overflow requiresbounds checking.
É Check data lengths before writingÉ Check array subscripts are within limitsÉ Check boundary conditions to avoid OBOÉ Constrain size of inputsÉ Beware of dangerous API calls to risky code
Responsibility for bounds checking
Like many security checks, this is a sharedresponsibility. It requires checking at each point, bythe:
É programmerÉ programming language, compilerÉ OSÉ hardware
Exercise. For each role, give an example of what theydo to check bounds.
Bounds checks by programmer
int a[20], i;for (i=0, i<20; i++) {
a[i] = 0;...
}
É How can this go wrong?
Bounds checks by programmer
int a[20], i;for (i=0, i<20; i++) {
if (i<0) signal error;if (i >= 20) signal error;a[i] = 0;...
}
É Checking every time seems inefficientÉ Are both checks required?É Tempting to skip. . .
Bounds checks by programmer
int a[20], i, max;...
for (i=0, i<max; i++) {if (i<0) signal error;if (i >= 20) signal error;a[i] = 0;...
}
É If bound is computed, both checks essentialÉ Code reviews, programmer reasoning are brittle
Safety from programming languages
Programming languages may provide memory safetyand type safety, automatically for all programs:
Memory safety disallow reading/writing with arbitrarymemory addressing.Prevents overflow attacks from corruptingmemory.
Type safety prevent storing arbitrary data into datavalues.Makes it harder for attacker to inject data thatwill be executed as binary code.
Safety from compilers and tools
To try to ensure safety with an unsafe language, wemay use:
É a safe compiler to automatically generatechecking code that checks bounds or typesdynamically, during execution.
É a verifying compiler that checks statically atcompile time that the code it produces is safe.
É security testing tools that generate inputs toprograms to try to find security bugs.
É program analysis tools that ensure that inputsource code is free from certain vulnerabilities.
We’ll look at these technologies in more detail later inthe course.
Safety from OS, libraries
É See lists of unsafe functions and explanations:É Microsoft’s recommendationsÉ CERT Secure C Coding
É Use a code security scanning toolÉ Have lists of dangerous API calls built inÉ Simple to find these in code, need deeper analysis
to identify certain vulnerabilitiesÉ Examples: RATS, cppcheck, SPLint, Clang.
É Switch to using safe(r) library functionsÉ The Safe C Library introduced in VS 2005.É Bounds checking functions part of the latest C11
standard (appendix K, also ISO/IEC TR 24731-1)É But has been contentious, not clear how
widely/quickly will be adopted.
Outline
Announcement
Recap
Containment and curtailment
Stack tamper detection
Memory mode protection
Diversification
Secure programming
Summary
Review questionsOverflow protection mechanisms
É Describe how StackGuard’s “canaries” work to stopbuffer overflows. What kind of attacks are they noteffective against?
É Describe how hardware-assisted memoryprotection can prevent the worst kinds of overflowattacks. In what cases may it be difficult to use?
É Explain the strategy of program diversification andhow it is achieved in ASLR.
Avoiding overflow vulnerabilities
É Explain where bounds checking should beperformed, especially to ensure “defence-in-depth”.
É List some checks which a programmer or staticanalysis tool should do to prevent overflowvulnerabilities in released code.
Coming next
Lab session tomorrow!
Next week: looking at injections.
References and credits
TBD