Professional Documents
Culture Documents
Theory:
Attackers generally use buffer overflows to corrupt the execution stack of a web application.
By sending carefully crafted input to a web application, an attacker can cause the web
application to execute arbitrary code, possibly taking over the machine. Attackers have
managed to identify buffer overflows in a staggering array of products and components.
Buffer overflow flaws can be present in both the web server and application server products
that serve the static and dynamic portions of a site, or in the web application itself. Buffer
overflows found in commonly-used server products are likely to become widely known and
can pose a significant risk to users of these products. When web applications use libraries,
such as a graphics library to generate images or a communications library to send e-mail, they
open themselves to potential buffer overflow attacks. Literature detailing buffer overflow
attacks against commonly-used products is readily available, and newly discovered
vulnerabilities are reported almost daily.
Buffer overflows can also be found in custom web application code, and may even be more
likely, given the lack of scrutiny that web applications typically go through. Buffer overflow
attacks against customized web applications can sometimes lead to interesting results. In
some cases, we have discovered that sending large inputs can cause the web application or the
back-end database to malfunction. It is possible to cause a denial of service attack against the
web site, depending on the severity and specific nature of the flaw. Overly large inputs could
cause the application to display a detailed error message, potentially leading to a successful
attack on the system.
Buffer overflow attacks generally rely upon two techniques (and usually the combination):
Compiled or
Interpreted
Language/Environment
Strongly
Typed
Direct Memory
Access
Safe or
Unsafe
Both
Yes
No
Safe
.NET
Both
Yes
No
Safe
Perl
Both
Yes
No
Safe
Python - interpreted
Intepreted
Yes
No
Safe
Ruby
Interpreted
Yes
No
Safe
C/C++
Compiled
No
Yes
Unsafe
Assembly
Compiled
No
Yes
Unsafe
COBOL
Compiled
Yes
No
Safe
Developer training bounds checking, use of unsafe functions, and group standards
Non-executable stacks many operating systems have at least some support for this
Safe functions use strncat instead of strcat, strncpy instead of strcpy, etc
Patches Be sure to keep your web and application servers fully patched, and be
aware of bug reports relating to applications upon which your code is dependent.
Periodically scan your application with one or more of the commonly available
scanners that look for buffer overflow flaws in your server products and your custom web
applications.
Stack Overflow
Stack overflows are the best understood and the most common form of buffer overflows. The
basics of a stack overflow are simple:
There are two buffers, a source buffer containing arbitrary input (presumably from the
attacker), and a destination buffer that is too small for the attack input. The second buffer
resides on the stack and somewhat adjacent to the function return address on the stack.
The faulty code does not check that the source buffer is too large to fit in the
destination buffer. It copies the attack input to the destination buffer, overwriting
additional information on the stack (such as the function return address).
When the function returns, the CPU unwinds the stack frame and pops the (now
modified) return address from the stack.
Control does not return to the function as it should. Instead, arbitrary code (chosen by
the attacker when crafting the initial input) is executed.
is written in a language (or depends upon a program that is written in a language) that
allows buffer overflows to be created (see Table 8.1) AND
copies data from one buffer on the stack to another without checking sizes first AND
does not use techniques such as canary values or non-executable stacks to prevent
buffer overflows THEN
Heap Overflow
Heap overflows are problematic in that they are not necessarily protected by CPUs capable of
using non-executable stacks. A heap is an area of memory allocated by the application at runtime to store data. The following example, written in C, shows a heap overflow exploit.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BSIZE 16
#define OVERSIZE 8 /* overflow buf2 by OVERSIZE bytes */
void main(void) {
u_long b_diff;
char *buf0 = (char*)malloc(BSIZE);
char *buf1 = (char*)malloc(BSIZE);
is written in a language (or depends upon a program that is written in a language) that
allows buffer overflows to be created (see Table 8.1) AND
copies data from one buffer on the stack to another without checking sizes first AND
does not use techniques such as canary values to prevent buffer overflows THEN
void main(void) {
char str[100] = scanf("%s");
printf("%s", str);
}
This simple program takes input from the user and displays it back on the screen. The
string %s means that the other parameter, str, should be displayed as a string. This example
is not vulnerable to a format string attack, but if one changes the last line, it becomes
exploitable:
printf(str);
uses functions such as printf, snprintf directly, or indirectly through system services
(such as syslog) or other AND
the use of such functions allows input from the user to contain control information
interpreted by the function itself
3. Avoid the use of functions like printf that allow user input to contain control
information
4. If relying upon operating system functions or utilities written in a vulnerable language,
ensure that they:
1. use the principle of least privilege
2. use compilers that protect against stack and heap overflows
3. are current in terms of patches
Unicode Overflow
Unicode exploits are a bit more difficult to do than typical buffer overflows as demonstrated
in Anleys 2002 paper, but it is wrong to assume that by using Unicode, you are protected
against buffer overflows. Examples of Unicode overflows include Code Red, a devastating
Trojan with an estimated economic cost in the billions of dollars.
How to determine if you are vulnerable
If your program:
is written in a language (or depends upon a program that is written in a language) that
allows buffer overflows to be created (see Table 8.1) AND
does not use techniques such as canary values to prevent buffer overflows THEN
char buf[50];
if (s > 10) {
return;
}
// large buffer
// check we're not greater than 10
Are there cases where these values are used as array indices after performing an
arithmetic operation (+, -, *, /, or % (modulo))?
How would your program react to a negative or zero value for integer values,
If using .NET, use David LeBlancs SafeInt class or a similar construct. Otherwise, use
a "BigInteger" or "BigDecimal" implementation in cases where it would be hard to
validate input yourself.
If your compiler supports the option, change the default for integers to be unsigned
unless otherwise explicitly stated. Use unsigned integers whenever you don't need
negative values.