Overview
Assumptions about protocol data or data stored in memory
can be invalid, resulting in using data in ways that were
unintended.
Consequences
Access control (including confidentiality and integrity):
Can result in unintended modifications or information leaks
of data.
Exposure
period
Design: This problem can arise when a protocol leaves
room for interpretation and is implemented by multiple
parties that need to interoperate.
Implementation: This problem can arise by not
understanding the subtleties either of writing portable code
or of changes between protocol versions.
Platform
Protocol errors of this nature can happen on any
platform. Invalid memory layout assumptions are possible in
languages and environments with a single, flat memory space,
such as C/C++ and Assembly.
Required
resources
Any
Severity
Medium to High
Likelihood
of
exploit
Low
Avoidance
and
mitigation
- Design and Implementation: In flat address space
situations, never allow computing memory addresses as
offsets from another memory address.
- Design: Fully specify protocol layout unambiguously,
providing a structured grammar (e.g., a compilable yacc
grammar).
- Testing: Test that the implementation properly
handles each case in the protocol grammar.
Discussion
When changing platforms or protocol versions, data may
move in unintended ways. For example, some architectures may
place local variables a and b right next to
each other with a on top; some may place them next to
each other with b on top; and others may add some
padding to each. This ensured that each variable is aligned
to a proper word size.
In protocol implementations, it is common to offset
relative to another field to pick out a specific piece of
data. Exceptional conditions - often involving new protocol
versions - may add corner cases that lead to the data layout
changing in an unusual way. The result can be that an
implementation accesses a particular part of a packet,
treating data of one type as data of another type.
Examples
In C:
void example() {
char a;
char b;
*(&a + 1) = 0;
}
Here, b may not be one byte past a. It may
be one byte in front of a. Or, they may have three bytes
between them because they get aligned to 32-bit boundaries.