Buffer Overflow –”Data Gone Wild” – CS1


Background

Summary:

Buffer overflow occurs when data is input or written beyond the allocated bounds of an buffer, array, or other object causing a program crash or a vulnerability that hackers might exploit.

Description:

A buffer overflow occurs when data is written beyond the boundaries of a fixed length buffer overwriting adjacent memory locations which may include other buffers, variables and program flow data. Considered the “nuclear bomb” of the software industry, the buffer overflow is one of the most persistent security vulnerabilities and frequently used attacks.

Risk – How Can It Happen?

Writing outside the bounds of a block of allocated memory can corrupt data, crash the program, or allow the execution of malicious code.

Example of Occurrence:

A buffer overflow in a 2004 version of AOL’s AIM instant-messaging software exposed users to buffer overflow vulnerabilities. If a user posted a URL in their “I’m away” message, any of his or her friends who clicked on that link might be vulnerable to attack. AOL’s response was to suggest that users update to a new version that would fix the bug.

Paul Roberts “AOL IM ‘Away’ message flaw deemed critical”, Infoworld, August 9, 2004 http://www.infoworld.com/article/04/08/09/HNaolimflaw_1.html

Example in Code:

 #include <iostream>
 using namespace std;
 int main(void)
 {
   int vals[10];
   for (size_t i=0; i < 20; i++) {
       vals[i]=i;
   }
   return 0;
 }

When this program is run, the loop counter will exceed the value of a suitable index for the array. When the assignment statement tries to store a value in vals[10], buffer overflow occurs. The result is unpredictable. Depending on the operating system and the specific nature of the overflow, it may not cause any apparent problems, may cause the program to crash, or allow the execution of arbitrary code by an attacker.

Because buffer overflow is a common problem in C/C++, it is recommended to declare any variable that is used to represent the size of an object, including integer values used as sizes, indices, loop counters, and lengths, as size_t. The size_t type is an unsigned integer type.

Code Responsibly-- How Can I Avoid Buffer Overflow?

Make sure you have enough space: Before copying data to a fixed size block, make sure it is large enough to hold the data that you are going to copy. If it is not large enough, do not copy more data than your available space can hold. If your program is not able to continue properly after filling the available space, you may have to find some way to recover from the error.

Validate indices: If you have an integer variable, verify that it is within the proper bounds before you use it as an index to an array. This validation is particularly important for any values that might have been provided as user input or other untrusted input, such as information that might be read from a file or from a network connection.

When possible, use buffer-size accessors: Loops that iterate over arrays need to know the size of the array. Using a variable with the wrong value – or the incorrect constant value – can lead to buffer overflows. Some languages, such as Java, provide operators that can be used to retrieve the size of an array. Using these operators can help you avoid some of these problems.

Use alternative data structures that reduce the risk of overflows: Many buffer overflow vulnerabilities can be avoided by using vectors or other structures instead of traditional arrays. When possible, use vectors and iterators instead of arrays and integer-indexed loops. Note that these tools will not prevent you from running into trouble: you will still have to write your code carefully and correctly. However, they can reduce your risk of buffer overflow vulnerabilities.

Lab Assignment

Program 1

#include <iostream>
using namespace std;
int main(void)
{
  int vals[10];
  size_t count;
  size_t which;

  cout << "How many values should be store in the array? ";
  cin >> count;

  for (size_t i = 0; i < count; i++) {
    vals[i] = count-i;
  }

  cout << "Which value do you wish to retrieve? ";
  cin >> which;

  cout << "Your value is " << vals[which] << endl;

  return 0;
}

Lab Questions:

  1. Type*, compile, and run the above program. Describe the results. What happens if you type “3” for the first prompt? 7? 12? 20? What happens if you type 10 for the first prompt and then 3, 7, 12, and 20 for the second prompt?
  2. Complete the security checklist for this program (print the checklist).
  3. List potential buffer overflow errors.
  4. Provide example inputs that might cause buffer overflow problems.
  5. What strategies might you use to remove potential buffer overflow vulnerabilities from this program?

*Copying and pasting programs may result in syntax errors and other inconsistencies. It is recommended you type each program.

Program 2 (optional - check with your instructor if you need to complete this program)

Write a program that reads at most 10 temperatures (stored as floating point values) from a file. You can assume that the temperatures are stored in a file called “temps.txt”. Your program should include the following elements:

  1. A method to read the temperatures into an array
  2. A method that prints the temperatures
  3. A method that computes the average temperature
  4. A main that uses each of these methods.

If there are more than 10 values, your program should ignore any values after the first 10. If there are no values in the file, an appropriate error message should be printed.

Test this program with files containing the following sets of values. Indicate the average that you get in each case. Your program should handle each of these cases appropriately.

  1. Empty file
  2. 40.3 35.8 29.6 45 17.8 19.2 38.6 31.5 27.8 39.9
  3. 19.2 38.6 31.5 27.8 39.9
  4. 40.3 35.8 29.6 45 17.8 19.2 38.6 31.5 27.8 39.9 19.7 22.6 18.8

Security Checklist

Security Checklist

Vulnerability:Buffer Overflow Course: CS1
Task - Check each line of code Completed
1. Finding Arrays:
1.1 Underline each array declaration
1.2 For each array, underline all subsequent references
2. Index Variables – legal range for an array of size n is 0 <= i < n
2.1 For each underlined access that uses a variable as an index, write the legal range next to it.
2.2 For each index marked in 2.1, underline all occurrences of that variable.
2.3. Circle any assignments, inputs or operations that may modify these index variables.
2.4. Mark with a V any array that is indexed by a circled index variable.
3. Loops that modify index variables
3.1 Find loops that modify variables used to index arrays. For any index that occurs as part of a loop conditional, underline the loop limit. For example, if i < max is the conditional in a for loop, underline max
3.2. Write the legal range of the array index next to the loop limit as you did in step 2.1. Mark with a V if the loop limit could exceed the legal range of the array index. Watch out for loops that iterate beyond the bounds of the array (for example, i <=max when the largest valid index is max-1).
3.3 If the upper or lower loop limit is a variable, it must be checked just as indices are checked in Step 2
Highlighted areas indicate vulnerabilities!

Discussion Questions

  1. Describe the buffer overflow problem.
  2. List three ways you could potentially overflow a buffer in your program.
  3. How could you prevent a buffer overflow from occurring in your program?
Further Work (optional - check with your instructor if you need to answer the following questions)
  1. Give three real life examples of buffer overflow attacks (research on the web).
  2. What can result from a buffer overflow?
  3. Buffer overflows can be troublesome if they are used by attackers to run their own code. What sort of things might an attacker try to do if he or she were able to run any code they wanted on a computer?


 
Copyright © Towson University