.NET Framework 2.0 Security Inspection Questions - Unsafe Code

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Jason Taylor, Rudolph Araujo


Contents

Unsafe Code Vulnerabilities and Implications

Vulnerability

Implications

Buffer overflow in unmanaged code or code marked /unsafe

Allows arbitrary code execution by using the privileges of the running application.

Integer overflow in unmanaged code or code marked /unsafe

Unexpected calculation results in system instability or allows an attacker to read arbitrary memory.

Format string problem in unmanaged code or code marked /unsafe

An attacker can read or modify arbitrary memory.

Array out of bounds in unmanaged code or code marked /unsafe

Failure to check array bounds before access can allow an attacker to read arbitrary memory.

Data truncation in unmanaged code or code marked /unsafe

Unexpected data truncation can result in system instability or allow an attacker to read arbitrary memory.


Pay particularly close attention to any code compiled with the /unsafe switch. This code does not have all of the protection normal managed code is given. Look for potential buffer overflows, array out of bound errors, integer underflow, and overflow, as well as data truncation errors.


Review unsafe code by using the following questions:

  • Is the code susceptible to buffer overruns?
  • Is the code susceptible to integer overflows?
  • Is the code susceptible to format string problems?
  • Is the code susceptible to array out of bound errors?


Is the code susceptible to buffer overruns?

Buffer overruns are a vulnerability that may lead to execution of arbitrary code. While tracing through unmanaged or unsafe code, make sure that the following rules are followed:

  • Make sure any functions that copy variable-length data into a buffer and use a maximum length parameter properly.
  • Make sure that the code does not rely on another layer or tier for data truncation.
  • If you see a problem, make sure the code truncates the data instead of expanding the buffer to fit it. Buffer expansion may just move the problem downstream.
  • Make sure any unmanaged code was compiled with the /GS option.

The application should not contain code similar to the following example.

public void ProcessInput()
{
 char[] data = new char[255];  
 GetData(data);
}
public unsafe void GetData(char[] buffer)
{
int ch = 0;
fixed (char* pBuf = buffer)
{
  do
  {
    ch = System.Console.Read();
    *(pBuf++) = (char)ch;
  } while(ch != '\n');
}
}
 

In this code example, an overflow occurs whenever a single line is more than 255 characters long. There are two problems in this code:

  • The ProcessInput function allocates only enough space for 255 characters.
  • The GetData function does not check the size of the array as it fills it.


Is the code susceptible to integer overflows?

This problem occurs if a calculation causes a data value to be larger or smaller than its data type allows. This will cause the value to wrap and become much larger or smaller than expected. As you review the data through unmanaged or unsafe code, make sure that any location where a user can give input that results in a calculation does not cause an underflow or overflow condition.

The application should not contain code similar to the following example.

int[] filter(uint len, int[] numbers)
{
 uint newLen =  len * 3/4;
 int[] buf = new int[newLen];
 int j = 0;
 for(int i = 0; i < len; i++)
 {
   if (i % 4 != 0)
   buf[j++] = numbers[i];
 }
 return buf;
}
 

The problem in this example is that, in calculating the value for len, the code first computes len * 3 and then divides by 4. When len is large enough (about 1.4 billion), len * 3 overflows and newLen is assigned a value that is too small. The result is out of range array access in the buf array.


Is the code susceptible to format string problems?

Format string problems are caused by the way that the printf functions handle variables and by the %n format directive. While you review unmanaged or unsafe code, make sure that format string data never contains user input.

The application should not contain code similar to the following example.

void main (int argc,
          char **argv)
{
 /* Whatever the user said, spit back! */
 printf (argv[1]);
}
 

In this example, untrusted input in the form of a command line parameter is passed directly to a printf statement. This means that an attacker could include format string % directives in the string, and force the application to return or modify arbitrary memory in the stack.


Is the code susceptible to array out of bound errors?

Array indexing errors, such as buffer overruns can lead to memory being overwritten at arbitrary locations. This can lead to application instability or, with a carefully constructed attack, can lead to code injection. While tracing through unmanaged or unsafe code, make sure that the following rules are followed:

  • With C/C++ code, make sure that indexes run from zero to n-1, where n is the number of array elements.
  • Where possible, make sure that code does not use input parameters as array indices.
  • Make sure that any input parameters used as array indices are validated and constrained to ensure that the maximum and minimum array bounds cannot be exceeded.
Personal tools