Professional Documents
Culture Documents
BRANDON
S account for the largest share of CERT advi-
sories, as well as high-profile worms—from the
original Internet Worm in 1987 through
Blaster’s appearance in 2003. When malicious crackers
discover a vulnerability, they devise exploits that take ad-
real-world vulnera-
bilities. The Apache/Open_SSL Slapper worm1 was the
first high-profile worm to employ heap smashing.
The wide variety of exploits published for the stack
buffer overrun that Microsoft Security Bulletin MS03-
BAKER vantage of the vulnerability to attack a system. 0262 addressed (the vulnerability exploited by Blaster)
Microsoft The traditional approach to exploiting buffer over- further illustrates the viability of these new techniques.
runs is stack smashing: modifying a return address saved Table 1 shows a few examples.
on the stack (the region of memory used for parame- These new approaches typically first surface in non-
ters, local variables, and return address) to point to code traditional hacker publications. (For more discussion of
the attacker supplies that resides in a stack buffer at a this, including references to the origins of many of these
known location. Discussions of buffer overrun ex- techniques, see the “Nontraditional literature” sidebar on
ploitation in software engineering literature typically page 26.) A few brief summaries in the mainstream liter-
concentrate on stack-smashing attacks. As a result, ature,3,4 and recent books (such as Exploiting Software:
many software engineers and even security profession- How to Break Code5 and The Shellcoder’s Handbook: Discov-
als seemingly assume that all buffer overrun exploits ering and Exploiting Security Holes6), also discuss some of
operate in a similar manner. these techniques.
During the past decade, however, hackers have de- Understanding new approaches to exploitation is vital
veloped several additional approaches to exploit buffer for evaluating countermeasures’ effectiveness in address-
overruns. The arc injection technique (sometimes re- ing the buffer overrun problem. Failure to consider them
ferred to as return-into-libc) involves a control transfer leads people to suggest overly simplistic and worthless
to code that already exists in the program’s memory “solutions” (for example, “move all the buffers to the
space. Various pointer subterfuge techniques change the heap”) or to overstate the value of useful improvements
program’s control flow by attacking function pointers (for instance, valuable mitigation methods such as a
(pointer variables whose value is used as an address in a nonexecutable stack, which many mistakenly view as a
function call) as an alternative to the saved return ad- silver bullet).
dress, or modify arbitrary memory locations to create
more complex exploits by subverting data pointers. Exploiting buffer overruns
Heap smashing allows exploitation of buffer overruns A buffer overrun occurs when a program attempts to read
in dynamically allocated memory, as opposed to on or write beyond the end of a bounded array (also known
the stack. as a buffer). In runtime environments for languages such as
While these techniques appear esoteric, they are in Pascal, Ada, Java, and C#, the runtime environment de-
20 PUBLISHED BY THE IEEE COMPUTER SOCIETY ■ 1540-7993/04/$20.00 © 2004 IEEE ■ IEEE SECURITY & PRIVACY
Attacking Systems
stack when the buffer overrun occurs; depending on the lowed the attacker to run an arbitrary program. The
specific compiler used to compile f1a, this will typically term “arc injection” refers to how these exploits oper-
be somewhere around 108 bytes into arg. This new ate: the exploit just inserts a new arc (control-flow
value for the saved return address changes the program’s transfer) into the program’s control-flow graph, as op-
control flow: when the return instruction executes, con- posed to code injection-exploits such as stack smash-
trol is transferred to buff instead of returning to the call- ing, which also insert a new node.
ing procedure. A straightforward version of arc injection is to use a
Stack smashing is well described in mainstream liter- stack buffer overrun to modify the saved return address
ature,1 so we won’t discuss it in detail in this article. to point to a location already in the program’s address
However, two important enhancements to the standard space—more specifically, to a location within the sys-
stack-smashing technique are often used in conjunction tem function in the C standard library. The system
with some of the other approaches, and therefore are function takes an arbitrary command line as an argu-
worth describing. ment, checks the argument’s validity, loads it into a reg-
Trampolining lets an attacker apply stack smashing in ister R, and makes a system call to create the process.
situations in which buff’s absolute address is not known Eliding some details, pseudocode for the system
ahead of time. The key insight here is that if a program function is:
register R contains a value relative to buff, we can trans-
fer control to buff by first transferring control to a se- void system(char * arg) {
quence of instructions that indirectly transfers via R. check_validity(arg);
When an attacker can find such a sequence of instructions R = arg;
(known as the trampoline) at a well-known or predictable target:
address, this provides a reliable mechanism for transfer- execl(R, ...)
ring control to buff. Alternatively, a pointer to attacker- }
supplied data can often be found somewhere on the stack,
and so exploits often use sequences of instructions such as If an attacker can arrange for R to point to an attacker-
pop/pop/ret to trampoline without involving regis- supplied string and then jump directly to the location
ters. David Litchfield’s comparison of exploit methods target, thus bypassing the validity check and assign-
between Linux and Windows suggests that variations in ment, the system will treat the attacker-supplied string as
Linux distributions make trampolines a less popular ex- a command line and execute it. On many operating sys-
ploit approach on Linux.6 tems, the C standard library loads into most processes at a
Another concept first developed as a stack-smashing well-known location, and the computing target’s ab-
enhancement is the separation between transferring the solute address is straightforward.
payload and the buffer overrun operation that modifies This still leaves the attacker with the problem of
control flow. A situation in which this is particularly use- how to get R to point to an attacker-supplied string. In
ful is when the buffer being overrun is too small to con- many cases, this is trivial: programs routinely reuse reg-
tain an attacker’s payload. If the attacker arranges for the isters, and it could just so happen that the program also
payload to be supplied in an earlier operation and it’s still uses R in the procedure in which a buffer overrun oc-
available in the program’s memory space, then he or she curs. For example, if R happens to contain the address
can use it at the time of exploit. The sidebar briefly dis- of buff or arg in the compiled version f1 (from Fig-
cusses and gives references for several such clever tech- ure 1), then exploiting the buffer overflow via arc injec-
niques, including Murat Balaban’s approach of storing tion is trivial: all the attacker needs to do is ensure that
the payload in an environment variable, which are typi- the target’s location appears at the appropriate offset
cally accessible on Linux systems from well-known ad- in arg to replace the saved return address. When f1
dresses near the stack base. returns, control transfers to the middle of the system
function instead. (Because system is in the C standard
Arc injection library, known as libc on Unix and Linux systems,
As an alternative to supplying executable code, an at- these exploits are often referred to as return-into-libc
tacker might simply be able to supply data that—when exploits; however, variations exist that involve neither a
a program’s existing code operates on it—will lead to return statement nor libc, so we prefer the more general
the desired effect. One such example occurs if the at- term “arc injection.”)
tacker can supply a command line that the program The straightforward arc-injection approach serves as
under attack will use to spawn another process; this es- the basis for more complex exploits. One approach is to
sentially allows arbitrary code execution. Arc injection arrange the data after the saved return address so that f1
exploits are an example of this data-oriented ap- first “returns” to strcpy’s location rather than its origi-
proach—indeed, the first such published exploit al- nal caller (copying the data to an appropriate location);
Figure 3. A simplified example of vulnerable code with compiler-inserted checks for Exception-
buffer overruns. Pointer subterfuge attacks can be used to defeat compiler-inserted handler hijacking
checks for buffer overruns, as this simplified example of vulnerable code illustrates. Several variations of exploit tech-
niques target the Microsoft Win-
dows Structured Exception Handling
to the same effect as a function-pointer clobber. (SEH) mechanism. When an exception (such as an ac-
Another use of data-pointer modification is to mod- cess violation) is generated, Windows examines a
ify some location used in future security-critical deci- linked list of exception handlers (typically registered by
sions. An exploit published by Litchfield for the MS03- a program as it starts up) and invokes one (or more) of
026 vulnerability7 is an excellent example of how them via a function pointer stored in the list entry. Be-
pointer subterfuge can combine with a traditional stack- cause the list entries are stored on the stack, it is possible
smashing approach. to replace the exception-handler function pointer via
Figure 3 presents a simplified version of a vulnerable buffer overflow (a standard example of function-
program’s code. The stack_cookie and global pointer clobbering), thus allowing an attacker to trans-
_magic_number variables are explicit (albeit simplified) fer control to an arbitrary location—typically a tram-
representations of some additional checks introduced by poline to code injected by the attacker. Versions of
the Microsoft Visual C++ 7.0 compiler. For the purposes Windows starting with Windows Server 2003 perform
of this section, it is enough to note that the goal of these some validity checking of the exception handlers that
code fragments is to prevent execution from reaching limit the feasibility of this straightforward attack.
program point P if a buffer overrun has modified the An alternative to clobbering an individual function
saved return address, which on an x86 machine is located pointer is to replace the field of the thread environment
on the stack directly after the stack_cookie variable. block (a per-thread data structure maintained by the
By taking advantage of the buffer overrun at P1, Windows operating system) that points to the list of reg-
Litchfield’s exploit first performs the following primitive istered exception handlers. The attacker simply needs to
operations: “mock up” an apparently valid list entry as part of the
payload and, using an arbitrary pointer write, modify the
• stores a sequence of instructions in the local variable “first exception handler” field. Although recent versions
buff; of Windows do some validity checking for the list entries,
• modifies the pointer variable ptr to point to the global Litchfield has demonstrated successful exploits in many of
variable global_magic_number; these cases.
• sets i to a new value val; As this discussion implies, the SEH mechanism has
• sets stack_cookie to the same value val; and been repeatedly revised in response to these attacks; all
• modifies the saved return address to contain the address currently published vulnerabilities are expected to be
of a trampoline that will indirectly transfer execution to fixed in Windows XP Service Pack 2. However, pub-
buff. lished exploits continue to be feasible on older versions of
the operating system, and it is, of course, possible that
When execution reaches P2, the assignment modi- new exploits will be discovered for SEH’s latest version.
order of heap operations to position the heap block of in- nique has been repeatedly extended, researchers such as
terest at a known location and to disambiguate the fol- Matt Conover and Oded Horovitz are currently investigat-
lowing blocks’ behavior. ing new exploit approaches that build on heap smashing.8
As of early 2004, the clear explanations in The Shellcoder’s
Handbook6 and elsewhere imply that heap buffer overrun
exploitation is almost as cookbook of a process as stack
buffer exploitation. Just as the original stack-smashing tech- G iven the continued existence of large amounts of C
and C++ code in system-critical code (operating
systems, databases, mail and Web servers, and so on), 8. M. Conover and O. Horovitz, “Reliable Windows Heap
buffer overruns are likely to continue to be an important Exploits,” Proc. CanSecWest, 2004; http://cansecwest.
source of potential vulnerabilities. Security researchers com/csw04/csw04-Oded+Connover.ppt.
continue to devise new mitigation approaches to pre- 9. C. Cowan et al., “StackGuard: Automatic Adaptive Detec-
venting exploitation of these vulnerabilities, as well as to tion and Prevention of Buffer overrun attacks,” Proc. Usenix
investigate promising combinations10; however, attackers Security Symp., Usenix Assoc., 1998; www.immunix.
have proven equally adept at inventing new exploit tech- com/pdfs/usenixsc98.pdf.
niques to defeat promising mitigations. 10. J. Pincus and B. Baker, Mitigations for Low-Level Coding
An important point about the new exploitation Vulnerabilities: Incomparability and Mitigations; http://
techniques we described in this article is that they in- research.microsoft.com/users/jpincus/mitigations.pdf.
validate traditional assumptions about buffer overrun
exploits. Jonathan Pincus is a senior researcher at Microsoft Research. His
research interests include security, privacy, and reliability of soft-
ware-based systems. He received his MS from the University of
• Arc injection invalidates the assumption that all exploits California at Berkeley, and his AB from Harvard University. Con-
rely on injecting code. tact him at jpincus@microsoft.com.
• Pointer subterfuge invalidates the assumption that all
Brandon Baker is a security development engineer and red-team
exploits rely on overwriting the saved return address.
lead in the Microsoft Windows Security group. His research inter-
• Heap smashing and pointer subterfuge both invalidate ests include security architecture and penetration testing. He
the assumption that only stack buffers are vulnerable. received his BSc in computer science from Texas A&M University.
Contact him at babaker@microsoft.com.
In addition to taking these specific techniques into ac-
count when analyzing potential solutions, researchers must
also consider what assumptions the solutions make. Simi-
larly, systems designers must consider exploit possibilities as Any products your peers should know
they introduce new functionality in order to avoid intro- about? Write a review for IEEE Pervasive
ducing new avenues of exploitation (for example, C++ vir-
Computing, and tell us why you were
Tried
tual functions, structured exception handling, or atexit).
At least in the short term, the “arms race” appears likely to impressed. Our New Products department
continue: attackers will find ways to invalidate assumptions, features reviews of the latest components,
and thus create new exploit techniques.
devices, tools, and other ubiquitous com-
References
1. CERT Advisory CA-2002-27 Apache/mod_ssl Worm,
any puting gadgets on the market.
new
advisories/CA-2002-27.html. recommendations to
2. Buffer Overrun in RPC Interface Could Allow Code Execution, pvcproducts@computer.org
Microsoft Security Bulletin MS03-0262003; www. today!
microsoft.com/technet/security/bulletin/MS03-026.mspx.
3. C. Cowan et al., “Buffer Overflows: Attacks and Defenses
for the Vulnerability of the Decade,” DARPA Information
Survivability Conf. and Expo (DISCEX ‘00), 2000; www.
gadgets
immunix.com/pdfs/discex00.pdf
4. J. Wilander and M. Kamkar, “A Comparison of Publicly
Available Tools for Dynamic Buffer Overflow Prevention,”
Proc. 10th Network and Distributed System Security Symp.
lately
(NDSS ‘03), 2003; www.ida.liu.se/~johwi/research
?
_publications/paper_ndss2003_john_wilander.pdf.
5. G. Hoglund and G. McGraw, Exploiting Software: How to
Break Code, Addison-Wesley, 2004.
6. J. Koziol et al., The Shellcoder’s Handbook: Discovering and
Exploiting Security Holes, John Wiley & Sons, 2004.
7. D. Litchfield, Defeating the Stack Buffer Overflow Preven-
tion Mechanism of Microsoft Windows 2003 Server, 2003;
www.nextgenss.com/papers/defeating-w2k3-stack
-protection.pdf.