Difference between revisions of "Buffer Overflows"

From OWASP
Jump to: navigation, search
(How to protect yourself)
(fixed links)
 
(37 intermediate revisions by 7 users not shown)
Line 1: Line 1:
[[Guide Table of Contents]]__TOC__'''
+
[[Guide Table of Contents|Development Guide Table of Contents]]__TOC__'''
  
 
==Objective ==
 
==Objective ==
Line 5: Line 5:
 
To ensure that:
 
To ensure that:
  
* Applications do not expose themselves to faulty components
+
* Applications do not expose themselves to faulty components.
  
* Applications create as few buffer overflows as possible
+
* Applications create as few buffer overflows as possible.
  
* Developers are encouraged to use languages and frameworks that are relatively immune to buffer overflows.  
+
* Developers are encouraged to use languages and frameworks that are relatively immune to buffer overflows.
  
 
==Platforms Affected ==
 
==Platforms Affected ==
Line 15: Line 15:
 
Almost every platform, with the following notable exceptions:
 
Almost every platform, with the following notable exceptions:
  
* Java/J2EE – as long as native methods or system calls are not invoked
+
* Java/J2EE – as long as native methods or system calls are not invoked.
  
* .NET – as long as unsafe or unmanaged code is not invoked (such as the use of P/Invoke or COM Interop)
+
* .NET – as long as unsafe or unmanaged code is not invoked (such as the use of P/Invoke or COM Interop).
  
 
* PHP, Python, Perl – as long as external programs or vulnerable extensions are not used.
 
* PHP, Python, Perl – as long as external programs or vulnerable extensions are not used.
Line 27: Line 27:
 
==Description ==
 
==Description ==
  
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.  
+
Attackers generally use [[Buffer Overflow|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 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 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.
Line 40: Line 40:
  
 
* This means that strongly-typed programming languages (and environments) that disallow direct memory access usually prevent buffer overflows from happening.
 
* This means that strongly-typed programming languages (and environments) that disallow direct memory access usually prevent buffer overflows from happening.
 
* Language/Environment * Compiled or Interpreted * Strongly Typed * Direct Memory Access * Safe or Unsafe
 
 
* Java, Java Virtual Machine (JVM) * 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
 
  
 
{| border=1
 
{| border=1
 
+
|-
  || * Language/Environment || * Compiled or Interpreted || * Strongly Typed || * Direct Memory Access || * Safe or Unsafe
+
  ! Language/Environment !! Compiled or Interpreted !! Strongly Typed !! Direct Memory Access !! Safe or Unsafe
  
 
|-
 
|-
  
  || * Java, Java Virtual Machine (JVM) || * Both || * Yes || * No || * Safe
+
  || Java, Java Virtual Machine (JVM) || Both || Yes || No || Safe
  
 
|-
 
|-
  
  || * .NET || * Both || * Yes || * No || * Safe
+
  || .NET || Both || Yes || No || Safe
  
 
|-
 
|-
  
  || * Perl  || * Both || * Yes || * No || * Safe
+
  || Perl  || Both || Yes || No || Safe
  
 
|-
 
|-
  
  || * Python - interpreted || * Intepreted || * Yes || * No || * Safe
+
  || Python - interpreted || Intepreted || Yes || No || Safe
  
 
|-
 
|-
  
  || * Ruby || * Interpreted || * Yes || * No || * Safe
+
  || Ruby || Interpreted || Yes || No || Safe
  
 
|-
 
|-
  
  || * C/C++ || * Compiled || * No || * Yes || * Unsafe
+
  || C/C++ || Compiled || No || Yes || Unsafe
  
 
|-
 
|-
  
  || * Assembly || * Compiled || * No || * Yes || * Unsafe
+
  || Assembly || Compiled || No || Yes || Unsafe
  
 
|-
 
|-
  
  || * COBOL || * Compiled || * Yes || * No || * Safe
+
  || COBOL || Compiled || Yes || No || Safe
  
 
|-
 
|-
  
 
|}
 
|}
 
 
 
 
Table 8.1: Language descriptions
 
Table 8.1: Language descriptions
  
Line 135: Line 114:
 
The following example, written in C, demonstrates a stack overflow exploit.
 
The following example, written in C, demonstrates a stack overflow exploit.
  
 +
<pre>
 +
#include <string.h>
  
 
+
void f(char* s) {
#include <string.h>
+
 
+
 
+
 
+
void f(char* s) {
+
 
+
 
     char buffer[10];
 
     char buffer[10];
 
 
     strcpy(buffer, s);
 
     strcpy(buffer, s);
 +
}
  
}
+
void main(void) {
 
+
 
+
 
+
void main(void) {
+
 
+
 
     f("01234567890123456789");
 
     f("01234567890123456789");
 
+
}
}
+
 
+
 
+
  
 
[root /tmp]# ./stacktest
 
[root /tmp]# ./stacktest
  
 
Segmentation fault
 
Segmentation fault
 +
</pre>
  
 
===How to determine if you are vulnerable ===
 
===How to determine if you are vulnerable ===
Line 176: Line 144:
  
 
===How to protect yourself ===
 
===How to protect yourself ===
 
+
# Deploy on systems capable of using non-executable stacks, such as:
* Deploy on systems capable of using non-executable stacks, such as:
+
 
## AMD and Intel x86-64 chips with associated 64-bit operating systems
 
## AMD and Intel x86-64 chips with associated 64-bit operating systems
 
## Windows XP SP2 (both 32- and 64-bit)
 
## Windows XP SP2 (both 32- and 64-bit)
Line 184: Line 151:
 
## OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
 
## OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
 
## Solaris 2.6 and later with the “noexec_user_stack” flag enabled
 
## Solaris 2.6 and later with the “noexec_user_stack” flag enabled
 
+
# Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
* Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
+
# Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
 
+
# If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
* Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
+
 
+
* If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
+
 
+
 
## use the principle of least privilege
 
## use the principle of least privilege
 
## use compilers that protect against stack and heap overflows
 
## use compilers that protect against stack and heap overflows
Line 197: Line 160:
 
==Heap Overflow ==
 
==Heap Overflow ==
  
Heap overflows are problematic in that they are not necessarily protected by CPUs capable of using non-execuable stacks. A heap is an area of memory allocated by the application at run-time to store data. The following example, written in C, shows a heap overflow exploit.
+
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 run-time to store data. The following example, written in C, shows a heap overflow exploit.
 
+
 
+
  
 +
<pre>
 
  #include <stdio.h>
 
  #include <stdio.h>
 
 
  #include <stdlib.h>
 
  #include <stdlib.h>
 
 
  #include <unistd.h>
 
  #include <unistd.h>
 
 
  #include <string.h>
 
  #include <string.h>
 
 
  
 
  #define BSIZE 16
 
  #define BSIZE 16
 
 
  #define OVERSIZE 8 /* overflow buf2 by OVERSIZE bytes */
 
  #define OVERSIZE 8 /* overflow buf2 by OVERSIZE bytes */
 
 
  
 
  void main(void) {
 
  void main(void) {
 
 
     u_long b_diff;
 
     u_long b_diff;
 
 
     char *buf0 = (char*)malloc(BSIZE); // create two buffers
 
     char *buf0 = (char*)malloc(BSIZE); // create two buffers
 
 
     char *buf1 = (char*)malloc(BSIZE);
 
     char *buf1 = (char*)malloc(BSIZE);
 
 
  
 
     b_diff = (u_long)buf1 - (u_long)buf0; // difference between locations
 
     b_diff = (u_long)buf1 - (u_long)buf0; // difference between locations
 
 
     printf("Initial values:  ");
 
     printf("Initial values:  ");
 
 
     printf("buf0=%p, buf1=%p, b_diff=0x%x bytes\n", buf0, buf1, b_diff);
 
     printf("buf0=%p, buf1=%p, b_diff=0x%x bytes\n", buf0, buf1, b_diff);
 
 
  
 
     memset(buf1, 'A', BUFSIZE-1), buf1[BUFSIZE-1] = '\0';
 
     memset(buf1, 'A', BUFSIZE-1), buf1[BUFSIZE-1] = '\0';
 
 
 
 
     printf("Before overflow: buf1=%s\n", buf1);
 
     printf("Before overflow: buf1=%s\n", buf1);
  
 
     memset(buf0, 'B', (u_int)(diff + OVERSIZE));
 
     memset(buf0, 'B', (u_int)(diff + OVERSIZE));
 
 
     printf("After overflow:  buf1=%s\n", buf1);
 
     printf("After overflow:  buf1=%s\n", buf1);
 
 
}
 
}
 
 
  
 
[root /tmp]# ./heaptest
 
[root /tmp]# ./heaptest
  
 
Initial values:  buf0=0x9322008, buf1=0x9322020, diff=0xff0 bytes
 
Initial values:  buf0=0x9322008, buf1=0x9322020, diff=0xff0 bytes
 
 
Before overflow: buf1=AAAAAAAAAAAAAAA
 
Before overflow: buf1=AAAAAAAAAAAAAAA
 
 
After overflow:  buf1=BBBBBBBBAAAAAAA
 
After overflow:  buf1=BBBBBBBBAAAAAAA
 
+
</pre>
 
+
  
 
The simple program above shows two buffers being allocated on the heap, with the first buffer being overflowed to overwrite the contents of the second buffer.  
 
The simple program above shows two buffers being allocated on the heap, with the first buffer being overflowed to overwrite the contents of the second buffer.  
Line 275: Line 210:
 
===How to protect yourself ===
 
===How to protect yourself ===
  
* Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
+
# Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
 
+
# Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
* Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
+
# If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
 
+
* If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
+
 
+
 
## use the principle of least privilege
 
## use the principle of least privilege
 
 
## use compilers that protect against stack and heap overflows
 
## use compilers that protect against stack and heap overflows
 
 
## are current in terms of patches
 
## are current in terms of patches
  
Line 291: Line 221:
 
Format string buffer overflows (usually called "format string vulnerabilities") are highly specialized buffer overflows that can have the same effects as other buffer overflow attacks. Basically, format string vulnerabilities take advantage of the mixture of data and control information in certain functions, such as C/C++'s printf. The easiest way to understand this class of vulnerability is with an example:
 
Format string buffer overflows (usually called "format string vulnerabilities") are highly specialized buffer overflows that can have the same effects as other buffer overflow attacks. Basically, format string vulnerabilities take advantage of the mixture of data and control information in certain functions, such as C/C++'s printf. The easiest way to understand this class of vulnerability is with an example:
  
#include <stdio.h>
+
<pre>
 
+
#include <stdio.h>
#include <stdlib.h>
+
#include <stdlib.h>
 
+
#include <unistd.h>
#include <unistd.h>
+
#include <string.h>
 
+
#include <string.h>
+
 
+
 
+
 
+
void main(void) {
+
  
 +
void main(void) {
 
     char str[100] = scanf("%s");
 
     char str[100] = scanf("%s");
 
 
     printf("%s", str);
 
     printf("%s", str);
 +
}
 +
</pre>
  
}
+
This simple program takes input from the user and displays it back on the screen. The string <code>%s</code> 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:
 
+
 
+
 
+
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);
 
     printf(str);
Line 335: Line 257:
 
===How to protect yourself ===
 
===How to protect yourself ===
  
* Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
+
# Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
 
+
# Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc. Specifically check for control information (meta-characters like '%')
* Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc. Specifically check for control information (meta-characters like '%')
+
# Avoid the use of functions like printf that allow user input to contain control information
 
+
# If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
* Avoid the use of functions like printf that allow user input to contain control information
+
 
+
* If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
+
 
+
 
## use the principle of least privilege
 
## use the principle of least privilege
 
 
## use compilers that protect against stack and heap overflows
 
## use compilers that protect against stack and heap overflows
 
 
## are current in terms of patches
 
## are current in terms of patches
  
Line 364: Line 280:
  
 
* does not use techniques such as canary values to prevent buffer overflows THEN
 
* does not use techniques such as canary values to prevent buffer overflows THEN
 +
 +
it is highly likely that the application is vulnerable to attack.
  
 
===How to protect yourself  ===
 
===How to protect yourself  ===
  
* Deploy on systems capable of using non-executable stacks, such as:
+
# Deploy on systems capable of using non-executable stacks, such as:
 
+
 
## AMD and Intel x86-64 chips with associated 64-bit operating systems
 
## AMD and Intel x86-64 chips with associated 64-bit operating systems
 
 
## Windows XP SP2 (both 32- and 64-bit)
 
## Windows XP SP2 (both 32- and 64-bit)
 
 
## Windows 2003 SP1 (both 32- and 64-bit)
 
## Windows 2003 SP1 (both 32- and 64-bit)
 
 
## Linux after 2.6.8 on AMD and x86-64 processors in 32- and 64-bit mode
 
## Linux after 2.6.8 on AMD and x86-64 processors in 32- and 64-bit mode
 
 
## OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
 
## OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
 
 
## Solaris 2.6 and later with the “noexec_user_stack” flag enabled
 
## Solaris 2.6 and later with the “noexec_user_stack” flag enabled
 
+
# Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
* Use higher-level programming languages that are strongly typed and that disallow direct memory access.  
+
# Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
 
+
# If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
* Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.  
+
 
+
* If relying upon operating system functions or utilities written in a vulnerable language, ensure that they:
+
 
+
 
## use the principle of least privilege
 
## use the principle of least privilege
 
 
## use compilers that protect against stack and heap overflows
 
## use compilers that protect against stack and heap overflows
 
 
## are current in terms of patches
 
## are current in terms of patches
  
Line 405: Line 311:
 
Although such an operation will usually cause some type of exception, your application must be coded to check for such an exception and take proper action. Otherwise, your application would report that 192 + 208 equals 144.
 
Although such an operation will usually cause some type of exception, your application must be coded to check for such an exception and take proper action. Otherwise, your application would report that 192 + 208 equals 144.
  
The following code demonstrates a buffer overflow, and was adapted from Blexim's ''Phrack ''article:
+
The following code demonstrates a buffer overflow, and was adapted from [http://www.phrack.org/issues.html?issue=60&id=10#article Blexim's Phrack article]:
  
 +
<pre>
 +
#include <stdio.h>
 +
#include <string.h>
  
 +
void main(int argc, char *argv[]) {
 +
    int i = atoi(argv[1]);        // input from user
 +
    unsigned short s = i;          // truncate to a short
 +
    char buf[50];                  // large buffer
  
'' #include <stdio.h>''
+
    if (s > 10) {                  // check we're not greater than 10
 +
        return;
 +
    }
  
'' #include <string.h>''
+
     memcpy(buf, argv[2], i);       // copy i bytes to the buffer
 
+
    buf[i] = '\0';                 // add a null byte to the buffer
 
+
    printf("%s\n", buf);           // output the buffer contents
 
+
'' void main(int argc, char *argv[]){''
+
 
+
''  int i = atoi(argv[1]); // input from user''
+
 
+
''  unsigned short s = i; // truncate to a short''
+
 
+
''  char buf[50]; // large buffer''
+
 
+
 
+
 
+
''  if (s > 10) { // check we're not greater than 10''
+
 
+
''     return;''
+
 
+
''  }''
+
 
+
''  memcpy(buf, argv[2], i); // copy i bytes to the buffer''
+
 
+
''  buf[i] = '\0'; // add a null byte to the buffer''
+
 
+
''  printf("%s\n", buf); // output the buffer contents''
+
 
+
 
+
 
+
''  return;''
+
 
+
'' } ''
+
 
+
 
+
 
+
''[root /tmp]# ./inttest 65580 foobar''
+
 
+
''Segmentation fault''
+
  
 +
    return;
 +
}
  
 +
[root /tmp]# ./inttest 65580 foobar
 +
Segmentation fault
 +
</pre>
  
 
The above code is exploitable because the validation does not occur on the input value (65580), but rather the value after it has been converted to an unsigned short (45).  
 
The above code is exploitable because the validation does not occur on the input value (65580), but rather the value after it has been converted to an unsigned short (45).  
Line 471: Line 357:
 
* Use range checking if your language or framework supports it, or be sure to implement range checking yourself after all arithmetic operations.
 
* Use range checking if your language or framework supports it, or be sure to implement range checking yourself after all arithmetic operations.
  
* Be sure to check for exceptions if your language supports it.  
+
* Be sure to check for exceptions if your language supports it.
  
 
==Further reading ==
 
==Further reading ==
Line 477: Line 363:
 
* Team Teso, ''Exploiting Format String Vulnerabilities''
 
* Team Teso, ''Exploiting Format String Vulnerabilities''
  
<u>http://www.cs.ucsb.edu/~jzhou/security/formats-teso.html</u>  
+
<u>http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf</u>
  
 
* Newsham, Tim, ''Format String Attacks
 
* Newsham, Tim, ''Format String Attacks
  
''<u>http://www.lava.net/~newsham/format-string-attacks.pdf</u>
+
''<u>http://hackerproof.org/technotes/format/FormatString.pdf</u>
  
 
* w00 w00 and Matt Conover, ''Preliminary Heap Overflow Tutorial''
 
* w00 w00 and Matt Conover, ''Preliminary Heap Overflow Tutorial''
Line 491: Line 377:
 
<u>http://www.ngssoftware.com/papers/unicodebo.pdf</u>  
 
<u>http://www.ngssoftware.com/papers/unicodebo.pdf</u>  
  
* David Leblanc, ''Integer Handling with the C++ SafeInt Class ''<u>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncode/html/secure01142004.asp</u>     
+
* David Leblanc, ''Integer Handling with the C++ SafeInt Class ''
 +
 
 +
<u>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncode/html/secure01142004.asp</u>     
  
 
* Aleph One, ''Smashing the Stack for fun and profit''
 
* Aleph One, ''Smashing the Stack for fun and profit''
  
<u>http://www.phrack.org/phrack/49/P49-14</u>  
+
<u>http://www.phrack.org/issues.html?issue=49&id=14#article</u>
  
 
* Mark Donaldson, ''Inside the buffer Overflow Attack: Mechanism, method, & prevention''
 
* Mark Donaldson, ''Inside the buffer Overflow Attack: Mechanism, method, & prevention''
  
<u>http://rr.sans.org/code/inside_buffer.php</u>  
+
<u>http://www.sans.org/reading_room/whitepapers/securecode/buffer-overflow-attack-mechanism-method-prevention_386</u>
  
 
* ''NX Bit'', Wikipedia article
 
* ''NX Bit'', Wikipedia article
Line 511: Line 399:
 
* Alexander Anisimov'', Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass'', Positive Technologies
 
* Alexander Anisimov'', Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass'', Positive Technologies
  
<u>http://www.maxpatrol.com/defeating-xpsp2-heap-protection.htm</u>  
+
<u>http://www.ptsecurity.com/download/defeating-xpsp2-heap-protection.pdf</u>
  
 
* Matt Conover, w00w00 on Heap Overflows, w00w00 Security Team
 
* Matt Conover, w00w00 on Heap Overflows, w00w00 Security Team
Line 519: Line 407:
 
* Blexim, ''Basic Integer Overflows
 
* Blexim, ''Basic Integer Overflows
  
''<u>http://www.phrack.org/phrack/60/p60-0x0a.txt</u>
+
''<u>http://www.phrack.org/issues.html?issue=60&id=10#article</u>
  
 
* StackShield
 
* StackShield
  
<u>http://www.angelfire.com/sk/stackshield/index.html</u>
+
<u>http://www.angelfire.com/sk/stackshield/index.html</u>  
  
 
* StackGuard
 
* StackGuard
  
<u>http://www.immunix.org</u>
+
<u>https://en.wikibooks.org/wiki/GNU_C_Compiler_Internals/Stackguard_4_1</u><br>
 +
<u>http://static.usenix.org/publications/library/proceedings/sec98/full_papers/cowan/cowan_html/cowan.html</u>
  
 
* Libsafe
 
* Libsafe
  
<u>http://www.research.avayalabs.com/project/libsafe</u>
+
<u>http://directory.fsf.org/wiki/Libsafe</u>
 
+
  
[[Guide Table of Contents]]
+
<br>
 +
[[Guide Table of Contents|Development Guide Table of Contents]]
 
[[Category:OWASP_Guide_Project]]
 
[[Category:OWASP_Guide_Project]]

Latest revision as of 08:27, 12 May 2013

Development Guide Table of Contents

Contents

Objective

To ensure that:

  • Applications do not expose themselves to faulty components.
  • Applications create as few buffer overflows as possible.
  • Developers are encouraged to use languages and frameworks that are relatively immune to buffer overflows.

Platforms Affected

Almost every platform, with the following notable exceptions:

  • Java/J2EE – as long as native methods or system calls are not invoked.
  • .NET – as long as unsafe or unmanaged code is not invoked (such as the use of P/Invoke or COM Interop).
  • PHP, Python, Perl – as long as external programs or vulnerable extensions are not used.

Relevant COBIT Topics

DS11.9 – Data processing integrity.

Description

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):

  • Writing data to particular memory addresses
  • Having the operating system mishandle data types
  • This means that strongly-typed programming languages (and environments) that disallow direct memory access usually prevent buffer overflows from happening.
Language/Environment Compiled or Interpreted Strongly Typed Direct Memory Access Safe or Unsafe
Java, Java Virtual Machine (JVM) 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

Table 8.1: Language descriptions

General Prevention Techniques

A number of general techniques to prevent buffer overflows include:

  • Code auditing (automated or manual)
  • Developer training – bounds checking, use of unsafe functions, and group standards
  • Non-executable stacks – many operating systems have at least some support for this
  • Compiler tools – StackShield, StackGuard, and Libsafe, among others
  • 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 is 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.

The following example, written in C, demonstrates a stack overflow exploit.

#include <string.h>

void f(char* s) {
    char buffer[10];
    strcpy(buffer, s);
}

void main(void) {
    f("01234567890123456789");
}

[root /tmp]# ./stacktest

Segmentation fault

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
  • 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

it is likely that the application is vulnerable to attack.

How to protect yourself

  1. Deploy on systems capable of using non-executable stacks, such as:
    1. AMD and Intel x86-64 chips with associated 64-bit operating systems
    2. Windows XP SP2 (both 32- and 64-bit)
    3. Windows 2003 SP1 (both 32- and 64-bit)
    4. Linux after 2.6.8 on AMD and x86-64 processors in 32- and 64-bit mode
    5. OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
    6. Solaris 2.6 and later with the “noexec_user_stack” flag enabled
  2. Use higher-level programming languages that are strongly typed and that disallow direct memory access.
  3. Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.
  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

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 run-time 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);		// create two buffers
    char *buf1 = (char*)malloc(BSIZE);

    b_diff = (u_long)buf1 - (u_long)buf0;	// difference between locations
    printf("Initial values:  ");
    printf("buf0=%p, buf1=%p, b_diff=0x%x bytes\n", buf0, buf1, b_diff);

    memset(buf1, 'A', BUFSIZE-1), buf1[BUFSIZE-1] = '\0';
    printf("Before overflow: buf1=%s\n", buf1);

    memset(buf0, 'B', (u_int)(diff + OVERSIZE));
    printf("After overflow:  buf1=%s\n", buf1);
}

[root /tmp]# ./heaptest

Initial values:  buf0=0x9322008, buf1=0x9322020, diff=0xff0 bytes
Before overflow: buf1=AAAAAAAAAAAAAAA
After overflow:  buf1=BBBBBBBBAAAAAAA

The simple program above shows two buffers being allocated on the heap, with the first buffer being overflowed to overwrite the contents of the second buffer.

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
  • 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

it is likely that the application is vulnerable to attack.

How to protect yourself

  1. Use higher-level programming languages that are strongly typed and that disallow direct memory access.
  2. Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.
  3. 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

Format String

Format string buffer overflows (usually called "format string vulnerabilities") are highly specialized buffer overflows that can have the same effects as other buffer overflow attacks. Basically, format string vulnerabilities take advantage of the mixture of data and control information in certain functions, such as C/C++'s printf. The easiest way to understand this class of vulnerability is with an example:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

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);


To see how, consider the user entering the special input:

%08x.%08x.%08x.%08x.%08x

By constructing input as such, the program can be exploited to print the first five entries from the stack.

How to determine if you are vulnerable

If your program:

  • 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

it is highly likely that the application is vulnerable to attack.

How to protect yourself

  1. Use higher-level programming languages that are strongly typed and that disallow direct memory access.
  2. Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc. Specifically check for control information (meta-characters like '%')
  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 Anley’s 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
  • takes Unicode input from a user AND
  • fails to sanitize the input AND
  • does not use techniques such as canary values to prevent buffer overflows THEN

it is highly likely that the application is vulnerable to attack.

How to protect yourself

  1. Deploy on systems capable of using non-executable stacks, such as:
    1. AMD and Intel x86-64 chips with associated 64-bit operating systems
    2. Windows XP SP2 (both 32- and 64-bit)
    3. Windows 2003 SP1 (both 32- and 64-bit)
    4. Linux after 2.6.8 on AMD and x86-64 processors in 32- and 64-bit mode
    5. OpenBSD (w^x on Intel, AMD, SPARC, Alpha and PowerPC)
    6. Solaris 2.6 and later with the “noexec_user_stack” flag enabled
  2. Use higher-level programming languages that are strongly typed and that disallow direct memory access.
  3. Validate input to prevent unexpected data from being processed, such as being too long, of the wrong data type, containing "junk" characters, etc.
  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

Integer Overflow

When an application takes two numbers of fixed word size and perform an operation with them, the result may not fit within the same word size. For example, if the two 8-bit numbers 192 and 208 are added together and stored into another 8-bit byte, the result will not fit into an 8-bit result:

1100 0000

+ 1101 0000

= 0001 1001 0000

Although such an operation will usually cause some type of exception, your application must be coded to check for such an exception and take proper action. Otherwise, your application would report that 192 + 208 equals 144.

The following code demonstrates a buffer overflow, and was adapted from Blexim's Phrack article:

#include <stdio.h>
#include <string.h>

void main(int argc, char *argv[]) {
    int i = atoi(argv[1]);         // input from user
    unsigned short s = i;          // truncate to a short
    char buf[50];                  // large buffer

    if (s > 10) {                  // check we're not greater than 10
        return;
    }

    memcpy(buf, argv[2], i);       // copy i bytes to the buffer
    buf[i] = '\0';                 // add a null byte to the buffer
    printf("%s\n", buf);           // output the buffer contents

    return;
} 

[root /tmp]# ./inttest 65580 foobar
Segmentation fault

The above code is exploitable because the validation does not occur on the input value (65580), but rather the value after it has been converted to an unsigned short (45).

Integer overflows can be a problem in any language and can be exploited when integers are used in array indices and implicit short math operations.

How to determine if you are vulnerable

  • Examine use of signed integers, bytes, and shorts.
  • 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, particular during array lookups?

How to protect yourself

  • If using .NET, use David LeBlanc’s 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.
  • Use range checking if your language or framework supports it, or be sure to implement range checking yourself after all arithmetic operations.
  • Be sure to check for exceptions if your language supports it.

Further reading

  • Team Teso, Exploiting Format String Vulnerabilities

http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf

  • Newsham, Tim, Format String Attacks

http://hackerproof.org/technotes/format/FormatString.pdf

  • w00 w00 and Matt Conover, Preliminary Heap Overflow Tutorial

http://www.w00w00.org/files/articles/heaptut.txt

  • Chris Anley, Creating Arbitrary Shellcode In Unicode Expanded Strings

http://www.ngssoftware.com/papers/unicodebo.pdf

  • David Leblanc, Integer Handling with the C++ SafeInt Class

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncode/html/secure01142004.asp

  • Aleph One, Smashing the Stack for fun and profit

http://www.phrack.org/issues.html?issue=49&id=14#article

  • Mark Donaldson, Inside the buffer Overflow Attack: Mechanism, method, & prevention

http://www.sans.org/reading_room/whitepapers/securecode/buffer-overflow-attack-mechanism-method-prevention_386

  • NX Bit, Wikipedia article

http://en.wikipedia.org/wiki/NX_bit

  • Horizon, How to bypass Solaris no execute stack protection

http://www.secinf.net/unix_security/How_to_bypass_Solaris_nonexecutable_stack_protection_.html

  • Alexander Anisimov, Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass, Positive Technologies

http://www.ptsecurity.com/download/defeating-xpsp2-heap-protection.pdf

  • Matt Conover, w00w00 on Heap Overflows, w00w00 Security Team

http://www.w00w00.org/files/articles/heaptut.txt

  • Blexim, Basic Integer Overflows

http://www.phrack.org/issues.html?issue=60&id=10#article

  • StackShield

http://www.angelfire.com/sk/stackshield/index.html

  • StackGuard

https://en.wikibooks.org/wiki/GNU_C_Compiler_Internals/Stackguard_4_1
http://static.usenix.org/publications/library/proceedings/sec98/full_papers/cowan/cowan_html/cowan.html

  • Libsafe

http://directory.fsf.org/wiki/Libsafe


Development Guide Table of Contents