Baseline for Ed 2 of tr 24772


Dangling References to Stack Frames [DCM]



Yüklə 0,54 Mb.
səhifə21/54
tarix16.08.2018
ölçüsü0,54 Mb.
#63136
1   ...   17   18   19   20   21   22   23   24   ...   54

6.33 Dangling References to Stack Frames [DCM]

6.33.1 Description of application vulnerability


Many languages allow treating the address of a local variable as a value stored in other variables. Examples are the application of the address operator in C or C++, or of the ‘Access or ‘Address attributes in Ada. In some languages, this facility is also used to model the call-by-reference mechanism by passing the address of the actual parameter by-value. An obvious safety requirement is that the stored address shall not be used after the lifetime of the local variable has expired. This situation can be described as a “dangling reference to the stack”.

6.33.2 Cross reference


CWE:

562. Return of Stack Variable Address

JSF AV Rule: 173

MISRA C 2012: 4.1 and 18.6

MISRA C++ 2008: 0-3-1, 7-5-1, 7-5-2, and 7-5-3

CERT C guidelines: EXP35-C and DCL30-C

Ada Quality and Style Guide: 7.6.7, 7.6.8, and 10.7.6

6.33.3 Mechanism of failure


The consequences of dangling references to the stack come in two variants: a deterministically predictable variant, which therefore can be exploited, and an intermittent, non-deterministic variant, which is next to impossible to elicit during testing. The following code sample illustrates the two variants; the behaviour is not language-specific:

struct s {  … };


typedef struct s array_type[1000];
array_type* ptr;
array_type* F()
{
  struct s Arr[1000];
  ptr = &Arr;     // Risk of variant 1;
  return &Arr;    // Risk of variant 2;
}

  struct s secret;


  array_type* ptr2;
  ptr2 = F();
  secret = (*ptr2)[10];   // Fault of variant 2

  secret = (*ptr)[10];    // Fault of variant 1



The risk of variant 1 is the assignment of the address of Arr to a pointer variable that survives the lifetime of Arr. The fault is the subsequent use of the dangling reference to the stack, which references memory since altered by other calls and possibly validly owned by other routines. As part of a call-back, the fault allows systematic examination of portions of the stack contents without triggering an array-bounds-checking violation. Thus, this vulnerability is easily exploitable. As a fault, the effects can be most astounding, as memory gets corrupted by completely unrelated code portions. (A life-time check as part of pointer assignment can prevent the risk. In many cases, such as the situations above, the check is statically decidable by a compiler. However, for the general case, a dynamic check is needed to ensure that the copied pointer value lives no longer than the designated object.)

The risk of variant 2 is an idiom “seen in the wild” to return the address of a local variable to avoid an expensive copy of a function result, as long as it is consumed before the next routine call occurs. The idiom is based on the ill-founded assumption that the stack will not be affected by anything until this next call is issued. The assumption is false, however, if an interrupt occurs and interrupt handling employs a strategy called “stack stealing”, which is, using the current stack to satisfy its memory requirements. Thus, the value of Arr can be overwritten before it can be retrieved after the call on F. As this fault will only occur if the interrupt arrives after the call has returned but before the returned result is consumed, the fault is highly intermittent and next to impossible to re-create during testing. Thus, it is unlikely to be exploitable, but also exceedingly hard to find by testing. It can begin to occur after a completely unrelated interrupt handler has been coded or altered. Only static analysis can relatively easily detect the danger (unless the code combines it with risks of variant 1). Some compilers issue warnings for this situation; such warnings need to be heeded, and some forms of static analysis are effective in identifying such problems.


6.33.4 Applicable language characteristics


This vulnerability description is intended to be applicable to languages with the following characteristics:

  • The address of a local entity (or formal parameter) of a routine can be obtained and stored in a variable or can be returned by this routine as a result.

  • No check is made that the lifetime of the variable receiving the address is no larger than the lifetime of the designated entity.

6.33.5 Avoiding the vulnerability or mitigating its effects


Software developers can avoid the vulnerability or mitigate its ill effects in the following ways:

  • Do not use the address of locally declared entities as storable, assignable or returnable value (except where idioms of the language make it unavoidable).

  • Where unavoidable, ensure that the lifetime of the variable containing the address is completely enclosed by the lifetime of the designated object.

  • Never return the address of a local variable as the result of a function call.

6.33.6 Implications for standardization


In future standardization activities, the following items should be considered:

  • Do not provide means to obtain the address of a locally declared entity as a storable value; or

  • Define implicit checks to implement the assurance of enclosed lifetime expressed in sub-clause 5 of this vulnerability. Note that, in many cases, the check is statically decidable, for example, when the address of a local entity is taken as part of a return statement or expression.

6.34 Subprogram Signature Mismatch [OTR]

6.34.1 Description of application vulnerability


If a subprogram is called with a different number of parameters than it expects, or with parameters of different types than it expects, then the results will be incorrect. Depending on the language, the operating environment, and the implementation, the error might be as benign as a diagnostic message or as extreme as a program continuing to execute with a corrupted stack. The possibility of a corrupted stack provides opportunities for penetration.

6.34.2 Cross reference


CWE:

628. Function Call with Incorrectly Specified Arguments

686. Function Call with Incorrect Argument Type

683. Function Call with Incorrect Order of Arguments

JSF AV Rule: 108

MISRA C 2012: 8.2-8.4, 17.1, and 17.3

MISRA C++ 2008: 0-3-2, 3-2-1, 3-2-2, 3-2-3, 3-2-4, 3-3-1, 3-9-1, 8-3-1, 8-4-1, and 8-4-2

CERT C guidelines: DCL31-C, and DCL35-C


6.34.3 Mechanism of failure


When a subprogram is called, the actual arguments of the call are pushed on to the execution stack. When the subprogram terminates, the formal parameters are popped off the stack. If the number and type of the actual arguments do not match the number and type of the formal parameters, then depending upon the calling mechanism used by the language translator, the push and the pop will not be consistent and, if so, the stack will be corrupted. Stack corruption can lead to unpredictable execution of the program and can provide opportunities for execution of unintended or malicious code.

The compilation systems for many languages and implementations can check to ensure that the list of actual parameters and any expected return match the declared set of formal parameters and return value (the subprogram signature) in both number and type. (In some cases, programmers should observe a set of conventions to ensure that this is true.) However, when the call is being made to an externally compiled subprogram, an object-code library, or a module compiled in a different language, the programmer must take additional steps to ensure a match between the expectations of the caller and the called subprogram.


6.34.4 Applicable language characteristics


This vulnerability description is intended to be applicable to languages with the following characteristics:

  • Languages that do not require their implementations to ensure that the number and types of actual arguments are equal to the number and types of the formal parameters.

  • Implementations that permit programs to call subprograms that have been externally compiled (without a means to check for a matching subprogram signature), subprograms in object code libraries, and any subprograms compiled in other languages.

6.34.5 Avoiding the vulnerability or mitigating its effects


Software developers can avoid the vulnerability or mitigate its ill effects in the following ways:

  • Use language or compiler support or static analysis tools to detect mismatches in calling signatures and the actual subprogram, particularly in multilingual environments.

  • Take advantage of any mechanism provided by the language to ensure that subprogram signatures match.

  • Avoid any language features that permit variable numbers of actual arguments without a method of enforcing a match for any instance of a subprogram call.

  • Take advantage of any language or implementation feature that would guarantee matching the subprogram signature in linking to other languages or to separately compiled modules.

  • Intensively review subprogram calls where the match is not guaranteed by tooling.

  • Ensure that only a trusted source is used when using non-standard imported modules.

6.34.6 Implications for standardization


In future standardization activities, the following items should be considered:

  • Language specifiers could ensure that the signatures of subprograms match within a single compilation unit and could provide features for asserting and checking the match with externally compiled subprograms.

Yüklə 0,54 Mb.

Dostları ilə paylaş:
1   ...   17   18   19   20   21   22   23   24   ...   54




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə