Week 15.b CS 5600 04/27 2022 On the board ------------ 1. Last time 2. Stack frame, revisited 3. Stack smashing 4. Defences -------------------------------------------------------------- Admin: - Final exam review session -- one page cheat sheet - labs resubmission? -- (likely) 50% penalty -- email "new submission: LabX" 1. Last time -- access control; subj accesses obj, pass or reject? -- Unix access control: UID/GID, file permission, process -- setuid: a (dangerous) way to raise privilege level -- there are multiple attacks 2. stack frame & calling convention, revisited -- revisit the first handout -- recall what stack frame looks like -- recall how calling convention works 3. Stack smashing There are many ways to attack computers. Today we study the "classic" method: buffer overflow. ('buffer overflow' is one way to conduct a stack smashing attack.) Introduction to buffer overflow attacks This method has been adapted to many different types of attacks, but the concepts are similar. We study this attack not to teach you all to become hackers but rather to educate you about vulnerabilities: what they are, how they work, and how to defend against them. Please remember: _although the approaches used to break into computers are very interesting, breaking in to a computer that you do not own is, in most cases, a criminal act_. A. demo Three users: - root runs a buggy echo server - ubuntu holds some secret (final.pdf) - nobody56 is unable to access the secret. the echo server (run by root) accepts network request of "(len, msg)", echos the received msg a client (run by nobody56) connects to server, send request "(len, msg)" [demo] B. Let’s examine a vulnerable server, buggy−server.c C. Let’s examine how an unscrupulous element (a hacker, a script kiddie, a worm, and so on) might exploit the server. 4. Defences Three main approaches -- (a) nonexecutable stack (NX) -- (b) stack canaries -- (c) randomization Targeting three requirements of previous attack: -- code injection into stack [by (a)] -- overwriting data on stack [by (b)] -- knowing memory addresses of stack [by (c)] Then...how could demo work? We return the stack address in the code... (regarding (c)) ...and we compile the code with gcc flags: "-fno-stack-protector -zexecstack" [we shut down (a) and (b)] A. nonexecutable stack --defenders create W ^ X policy (see below) so that memory cannot be both writable and executable. --what is W ^ X? map the stack pages as non-executable, if the hardware allows it. --Hardware these days allows it: there's an NX bit in the page table entries. You generally want to set that bit. [response: return-oriented programming (ROP) smash the stack with a bunch of return addresses. each return address points to the needed instruction followed by "ret" (requires the attacker to have previously identified these instructions in the code, so the assumption is that the attacker has access to the source code or binary). not too hard in CISC code like on x86, where there are lots of sequences of code embedded in the binary, even sequences that the programmer didn't mean (because instructions are not fixed length). result: the control flow bounces around all of these byte sequences in memory, executing exactly what the attacker wanted, but not executing off of the stack.] B. stack canaries --what about the defense of canary values near the return address? StackGuard (in gcc), PaX, etc. C. randomization --what about the defense of address space layout randomization (ASLR)? This provides some help but obviously doesn't help our vulnerable server because our server tells the client where the buffer is. --And on 32-bit systems, the randomness can be defeated through brute force. There's only 20 bits of randomness conceivable (the VPN bits), and ASLR implementations left the top four alone, to avoid fragmenting VM. --Linux usually maps executable code in a fixed address and randomize dynamic libraries and other data memory regions. So, attackers can BROP the executable directly. --On 64-bit systems, this defense can be defeated, if the server simply reforks children instead of restarting.