DOC PREVIEW
Berkeley COMPSCI 161 - Lecture Notes

This preview shows page 1-2 out of 7 pages.

Save
View full document
View full document
Premium Document
Do you want full access? Go Premium and unlock all 7 pages.
Access to all documents
Download any document
Ad free experience
View full document
Premium Document
Do you want full access? Go Premium and unlock all 7 pages.
Access to all documents
Download any document
Ad free experience
Premium Document
Do you want full access? Go Premium and unlock all 7 pages.
Access to all documents
Download any document
Ad free experience

Unformatted text preview:

CS 161 Computer SecurityFall 2008 Dawn Song Notes 7Common implementation flawsWe will discuss several classes of common implementation flaws.1 Buffer overrunsC is essentially a portable kind of assembler: in many ways, the programmer is exposed to the bare machine.In particular, C does not provide any sort of automatic bounds-checking for array or pointer accesses. Inthe case of a buffer overrun vulnerability (sometimes also called a buffer overflow), out-of-bounds memoryaccesses are used to corrupt the intended behavior of the program and cause it to run amok.Let us start with a simple example.char buf[80];void vulnerable() {gets(buf);}In this example, gets() reads as many bytes of input as are available on standard input, and stores theminto buf[]. If the input contains more than 80 bytes of data, then gets() will write past the end of buf,overwriting some other part of memory. This is a bug. Obviously, this bug might cause the program to crashor core-dump if we are unlucky, but what might be less obvious is that the consequences can be far worsethan that.To illustrate some of the dangers, we modify the example slightly.char buf[80];int authenticated = 0;void vulnerable() {gets(buf);}Imagine that elsewhere in the code is a login routine that sets the authenticated flag only if the userproves knowledge of a super-secret password, and other parts of the code test this flag to provide specialaccess to such users. We can see the risk. An attacker who can control the input to this program cancause buf to be overrun, so that data is written after the end of buf. Assuming the compiler stores theauthenticated variable in memory immediately after buf, then the authenticated flag will beoverwritten by this data. Consequently, the attacker can arrange to make the authenticated flag becometrue by supplying, say, 81 bytes of input, where the 81st byte takes on any non-zero value. This would givethe attacker special access even though the attacker doesn’t know the secret password, a security breach.We could conjecture a more serious version of this exploit, Suppose the code looked something like this:CS 161, Fall 2008, Notes 7 1char buf[80];int (*fnptr)();...Here we have a function pointer fnptr, which we assume is invoked somewhere else in the program. Thenthe attacker could cause more serious harm: he could overwrite fnptr with any address of his choosing,and thereby cause program execution to be re-directed to any desired memory address. A crafty attackermight first arrange to introduce a malicious sequence of machine instructions somewhere in the machine’saddress space, and then use the buffer overrun to write into fnptr the address of the malicious code, sothat when fnptr is next invoked, the flow of control is re-directed to the malicious code. Introduction ofmalicious code isn’t very hard, if the attacker controls the inputs to the program: since those inputs are likelystored into buffers as they are read in, the attacker could send the malicious code as data in any part of theinput, and then arrange for fnptr to point to the appropriate input buffer. This is a malicious code injectionattack.This demonstrates that, in some cases, an adversary may be able to take advantage of a buffer overrun bugto seize control of the program. This is very bad. For instance, consider a web server that receives requestsfrom clients across the network and processes them. If the web server contains a buffer overrun in the codethat processes such requests, a malicious client would be able to seize control of the web server process. Ifthe web server is running as root, the attacker has gained access to a root account on the system, and theattacker can leave a backdoor to regain access later; the system has been “owned.” It is no surprise that suchbuffer overrun vulnerabilities and malicious code injection attacks are a favorite method that worm writerslike to use to spread infection.This illustrates one way that buffer overrun bugs might be used to subvert system security. At this point,though, the skeptical might be inclined to suspect that the conditions required to exploit buffer overruns inthis particular way are rare. This seems to be more or less true1. However, hackers have discovered muchmore effective methods of malicious code injection, which we shall illustrate next.First, we have to back up and go over some background on how memory is layed out in a typical C program.Memory usually contains: (a) the text region, executable code of the program to be executed; (b) the heap,where dynamically allocated data is stored; (c) the stack, where local variables are stored. The heap growsand shrinks as objects are allocated and freed; the stack grows and shrinks as functions are called and return.To allow them to use memory as efficiently as possible, they are usually layed out like this:text region heap · · · stack0x00..0 0xFF..FHere the text regions starts at smaller-numbered memory addresses (e.g., 0x00..0), and the stack region endsat larger-numbered memory addresses (0xFF..F). When a function is called, a new stack frame is pushed ontothe program stack. This stack frame contains space for all the local variables to be used by that function, andanything else the compiler wants to store assorted with this function execution. On Intel (x86) machines,pushing frames on the stack causes the stack to grow “down” (towards smaller memory addresses). Usuallythere is a special register, called the stack pointer (SP), that points to the beginning of the current stackframe. Thus, the stack extends from the address given in the SP until the end of memory.It’s also worth saying something about how the CPU executes instructions. There is a special register, calledthe instruction pointer (IP), that points to the next machine instruction to be executed. When executing1However, it is worth noting that the famous Internet worm (the first of its kind) spread using several attacks, one of which useda buffer overrun to overwrite an authenticated flag in in.fingerd, the network finger daemon.CS 161, Fall 2008, Notes 7 2straight-line code, the machine reads the instruction pointed to by IP, executes that instruction, and thenincrements the IP. Jump and procedure-call instructions cause the IP to be updated differently. A jump in-struction causes the IP to be updated to whatever value is specified by the jump instruction. A call instructionis special: it pushes the current value of IP onto the stack (this


View Full Document

Berkeley COMPSCI 161 - Lecture Notes

Documents in this Course
Rootkits

Rootkits

11 pages

Load more
Download Lecture Notes
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Lecture Notes and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Lecture Notes 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?