« Return to Thread: A Proposal to Precisely Define Weaknesses
A Proposal to Precisely Define Weaknesses
by Paul E. Black
1 May 2009
Although much work has been done, which has greatly
improved the definitions of source code weaknesses, there are still
inconsistencies, ambiguities, and errors. Better definitions are needed
as one element to speed the work of detecting and preventing weaknesses.
We propose, first, that one element of a CWE be
designated the prime definition. If there is inconsistency between the
prime definition and a description, example, or definition in another element,
the prime definition is considered to be correct. If there is an error,
the prime definition is the first to be fixed. Other descriptions and
definitions can later be brought into alignment. Second we propose a
specific set of reviews and other steps as necessary and sufficient to consider
a prime definition to be thoroughly reviewed.
This document has three sections: motivation for
precisely and accurately defining weaknesses, comments on the current state of
definitions, and the proposal itself.
If you disagree (or agree!) with the proposal or
have suggestions, please respond. Feel free to share this.
SECTION 1. WHY CAREFULLY DEFINE WEAKNESSES?
An important prelude to preventing, mitigating, or
detecting weaknesses in software and systems is to have clear, unambiguous,
widely-accepted definitions of such weaknesses. Consider the following
questions that might occur to someone learning about software weaknesses.
What precisely is a buffer overflow? Is it the same as a heap overflow or
an unbounded transfer? Is one just a refinement of another? If an
integer overflow leads to memory violation, which weakness is it? Is it
both or is there some other relation between them? Precise definitions
could answer these questions and others.
Many people have done excellent work toward clearly defining
types of weakness. (Hereafter we usually use the term
"weakness" to mean a weakness class or type, not a particular
instance of a weakness type.) Some papers and work are "Seven Pernicious
Kingdoms: A Taxonomy of Software Security Errors" (Tsipenyuk, Chess, and
McGraw), "The CLASP Application Security Process", (Viega), "The
Preliminary List of Vulnerability Examples for Researchers (PLOVER)"
(Christey), "The Ten Most Critical Web Application Security
Vulnerabilities" (OWASP), "19 Deadly Sins of Software Security
Programming Flaws and How to Fix Them" (Howard, LeBlanc, and Viega),
"A Taxonomy of Computer Program Security Flaws, with Examples"
(Landwehr, Bull, McDermott, and Choi), (see http://cwe.mitre.org/about/sources.html
for more) "Structured CWE Descriptions" (Christey, Harris,
Heinbockel) available at http://cwe.mitre.org/documents/structured_descriptions/,
ISO/IEC Project 22.24772: Programming Language Vulnerabilities available at http://aitc.aitcnet.org/isai/ and many
others. KDM Analytics has produced formal definitions of some 30
weaknesses.
Since 2006 MITRE has led the Common Weakness Enumeration
(CWE) effort to collect, reconcile, organize, and define weaknesses. Not
only has this work improved and unified definitions, it has also led to discovery
of fundamental clarifying concepts, such as chains and composites of weaknesses
("Chains and Composites", Steve Christey, http://cwe.mitre.org/data/reports/chains_and_composites.html).
Precise definitions can lead to further better
understanding of weaknesses, their causes, cures, and preventions.
There are still inconsistencies and ambiguities within
CWEs. Consider that a CWE may have many descriptive elements. Some
in CWE Version 1.0 are
Black_Box_Definition (possibly more
than one)
White_Box_Definition (possibly more
than one)
Description
Description_Summary
Extended_Description
Compound_Element
Name (Weakness)
Demonstrative_Example
Observed_Example
Note
Theoretical_Note
Could inconsistencies be eliminated by deleting all but
one such element in each CWE? That is not practical. One definition
cannot serve all people in all instances. Training and reference needs
succinct prose definitions and examples. Automated tools need a
definition written in machine-readable languages. When discussion gets
specific, people need the nuances and details of what constitutes that
weakness. Proving that a weakness is absent or is prevented by some
approach needs a rigorous, mathematically formal definition.
Improving the state-of-practice of software development
to reduce instances of weaknesses and the vulnerabilities they cause takes work
from language designers, compiler writers, educators, assurance tool
developers, auditors and developers of guidance, people who specify and
contract software development, researchers, vulnerability trackers, software
engineers, and many more. If people in these roles disagree about what
constitutes a particular weakness, or even whether it is a weakness at all,
communication is difficult at best. At worst they may work at cross
purposes. Broadly accepted definitions should allow different groups to
work together more effectively.
Unambiguous, complete definitions allows those in the
field to understand precisely what different software assurance tools,
services, technologies, or methods can detect, mitigate, or prevent.
Formal definitions may allow tools to automatically check
for weaknesses, create wrappers to filter out attacks to exploit them, or even
rewrite the code to eliminate them.
SECTION 2. DOES THE CURRENT METHOD NEED IMPROVEMENT?
Currently there isn't a documented process to validate
weakness definitions. Descriptions, definitions, and examples in the CWE
have been reviewed and improved by different entities and the quality and
consistency have improved dramatically over the years. Yet, even casual
examination shows that most, if not all, CWEs need further work.
Given the number of CWEs and their range of complexity,
frequency, and severity, it is probably not worthwhile to precisely define
every single weakness. But for those which need precise definitions, it
is not clear exactly what should be. As with code, an essentially
unlimited amount of checking and review could be done for each weakness.
The community should agree on the types and amounts of validation that are
necessary and sufficient.
To be specific, currently every CWE has a summary
description. A CWE may also have alternate term descriptions,
demonstrative examples, or a white box definition. Thousands of these
descriptions have been reviewed and improved greatly. But which ones are
merely informative and which ones are intended to be the carefully reviewed,
precise and accurate? Consider CWE-121, Stack-based Buffer
Overflow. (Text taken from CWE version 1.3). Here is the
description summary:
"A stack-based buffer overflow
condition is a condition where the
buffer being overwritten is allocated on the
stack (i.e., is a
local variable or, rarely, a parameter to a
function)."
Here is the White Box Definition:
"A buffer overflow where the
buffer from the Buffer Write
Operation is statically
allocated"
Is the following an instance of CWE-121? Note that
alloca() gets memory from the stack, not the heap.
#define BUFSIZE 256
char *buf;
int main(int argc, char **argv) {
buf = (char *)alloca(BUFSIZE);
strcpy(buf, argv[1]);
}
The description summary uses "i.e." meaning
"that is" or a restatement. A strict reading excludes this
example because the buffer is only referenced by a global variable.
The white box definition says the buffer is statically
allocated, that is, allocated automatically by the compiler or language support
routine, not by functions invoked at run-time, such as alloca().
Again a strict reading excludes this example because the
buffer is dynamically allocated.
Yet most people would agree that the example code has an
instance of Stack-based Buffer Overflow and that the descriptions have minor
inaccuracies. Even ignoring this particular example, we see there is
inconsistency between the descriptions.
The following code snippets highlight not merely quibbles
about wording, but raise the fundamental question of what CWE-121 means.
typedef struct
{
char buf1[10];
char buf2[10];
} my_struct;
my_struct s;
s.buf1[17] = 'A';
(from SRD test case 188)
The C99 standard [1] Sect. 6.7.2.1 Structure and union specifiers,
page 102, para 5 says fields are "allocated in order". So buf2
makes the structure at least big enough that the access doesn't go outside the
structure. Any particular compiler probably allocates the structure
consistently, so the above code likely have a specific behavior in each
environment, although it might differ from environment to environment. Is
this an instance as CWE-121?
It is common in network programming to have structures
and code like the following:
struct {
int header;
char payload[ 0 ];
} *p;
p = malloc(sizeof *p + 2);
p->payload[0] = 'A';
p->payload[1] = '\0';
(adapted from Aurelien Delaitre)
Nothing in the C standard justifies this code, but most
compilers will treat it reasonably. Since the code does not strictly
follow the C standard, is its behavior undefined so that this should not be
considered an instance of CWE-121?
Compilers usually allocate structures in multiples of
four bytes, so the following code should be fine. That is, there is memory
for 12 characters in the structure. Should this example be considered to
write outside of the buffer or not? On what grounds?
typedef struct
{
int int_field;
char buf[10];
} my_struct;
my_struct s;
s.buf[10] = 'A';
(from SRD test case 201)
We see that precise definitions are important to make
consistent judgments. We also see that it is very difficult to write a
definition which is precise and accurate.
Given all the work which the CWE embodies, how can the
effect of inconsistencies be minimized? Where should work be concentrated
to achieve good definitions? All CWEs have a status of draft or
incomplete. How much and what kind of work should be done before a
definition is considered to be "thoroughly reviewed", that is, good
enough for the community to move on to another one? What language, either
formal (mathematically precise) or prose, should be used to state definitions
clearly and so the style is similar across CWEs?
What should be done to minimize assumptions or artifacts
arising from the use of a particular formal language or style?
SECTION 3. THE PROPOSAL
This proposal is part of a vision to improve software
assurance by having widely-used clear definitions of software weakness classes.
The goals of this proposal are to
* increase precision (minimize ambiguity and
inconsistency) in CWE
entries and
* increase accuracy (minimize mistakes indicated
by broad agreement).
The proposal has two points: (1) the need for an prime
definition and
(2) a review process. Each point has several parts
or supporting clauses which are somewhat independent.
POINT ONE: The community should have one prime definition
of each weakness.
PROPOSAL CLAUSE 1: the Common Weakness Enumeration (CWE)
is the repository of the prime definition.
PROPOSAL CLAUSE 2: each weakness has exactly one prime
definition.
All other notes, summaries, descriptions, categories,
components, examples, definitions, etc. are subordinate to it. For
instance, if a summary seems to contradict the prime definition, the prime
definition is assumed to be correct and the summary should be reinterpreted or
changed.
There may be times when the prime definition is
just wrong and needs to be corrected (see review process below), but short of
that, the prime definition is authoritative.
The prime definition is a complete description of the
weakness. All details and nuances are in that element. One need not
read any other element to understand what is or is not an instance, although
other elements may be helpful as examples or restatements.
It is important for the community to choose a prime
definition so work can be focused on it. Having prime definitions lets us
decide that a CWE is precisely and accurately described. Other summaries,
descriptions, views, names, etc. can be brought into agreement as time,
resources, and need arise.
The prime description will likely be legalistic and dry,
like most formal descriptions. One would read something else to initially
get a sense of what it is or to be reminded of it. Summaries,
relationships, and notes serve such purposes. Rather the prime definition
answers questions when differences of opinion or interpretation arise.
A clearly defined vocabulary is needed. Likely
there will be stock phrases, too. This vocabulary and the definitions
themselves should be based on the work already done by many contributors to the
CWE.
One example is "Structured CWE Descriptions"
(Christey, Harris, Heinbockel), available at http://cwe.mitre.org/documents/structured_descriptions/
Another is the work by KDM Analytics. Starting from scratch would be
wasteful.
DISCUSSION POINT: if elements refer to completely
orthogonal ideas, there could be more than one prime element and still has no
chance of (internal) contradiction.
We don't think this occurs in CWE.
DISCUSSION POINT: "prime definition" is only
one possible name. Other possibilities are master, attested, decisive,
prevailing, key, normative, authoritative, official, sanctioned, or commonly
accepted element or definition.
PROPOSAL CLAUSE 3: different kinds of weaknesses are best
expressed with different prime elements.
Most weaknesses are manifest in code, like hard-coded
password
(CWE-259) or leftover debug code (CWE-489). (Note
that these two are not 100% discernible from code alone.) However some
weaknesses are "black box", behavioral, functional, or external
weaknesses, like denial of service (CWE-730), configuration (CWE-16), or
violation of secure design principles (CWE-657).
PROPOSAL CLAUSE 4: each kind of weakness (see CLAUSE 3)
has a prime element.
For instance, the prime definition for all weaknesses
manifest in code might be White_Box_Definition.
DISCUSSION POINT: what is the right element for each kind
of weakness? For weaknesses manifest in code White_Box_Definition seem
most appropriate. Application behavior could be described in
Black_Box_Definition.
POINT TWO: How should the Community Decide a Definition
is Right?
An implementation may be checked for correctness against
its specification. But how can a specification be checked? The
short answer is that it can't be fully checked. However, we can take
steps to validate a definition and minimize mistakes.
PROPOSAL CLAUSE 5: a CWE prime definition is acceptable
when the following are done:
(A) the definition is published on the CWE
discussion list, and
there is no (or only limited)
disagreement that it is precise
(unambiguous) and accurate
(correct).
(B) the definition agrees with SC22/WG23
Programming Language
Vulnerabilities if there is a
correspondence.
(C) the definition is carefully reviewed by two
experts, who find it
to be precise and accurate.
(D) the definition is written in two different
"executable" forms
which are tested and deemed to
find/generate/mitigate the
weakness (and nothing else).
We think these steps are the minimum needed to come up
with good definitions. We need the general consensus of the community to
make sure it is broadly agreeable. We want definitions which are
consistent with other standards rather than creating yet another
(inconsistent) "standard". We need
experts to make sure the definition says the right thing. Finally, we
need executable forms to make sure the definition is precise.
Since CWEs are still being developed and the community is
self-selected, We don't think unanimous agreement is needed.
Nevertheless, any objections should be taken very
seriously. The desired goal is unanimity.
The community of concern is large and there are other
efforts. As much as possible the definitions should be in harmony.
One particular effort is PDTR 24772 a draft of which is document N0138 at http://aitc.aitcnet.org/isai/
Here are some correspondences between CWEs and entries in PDTR 24772:
6.15 Numeric Conversion Errors [FLC]
CWE 192
6.17 Boundary Beginning Violation [XYX]
CWE 123
CWE 129
6.18 Unchecked Array Indexing [XYZ]
CWE 129
6.19 Buffer Overflow in Stack [XYW]
CWE 121
We need reviews from at least two very different experts
to minimize the chance that the definition only reflects the view of one person
or one group. Why not three or more? The only objective reason we
offer is that economy suggests the fewest possible, and two is the least number
greater than one.
Who are the experts? We don't have specific people
in mind. It seems it should be people who have a lot of experience in the
field. It also seems like it should be people who have thought about such
definitions, so its likely to be authors, security researchers, and tool
makers. Maybe we should designate a pool of experts and any two of them
are acceptable. (And no objections from "experts"?)
Expert availability will probably be a factor.
The definition should be "formalized" in at
least two completely different ways to minimize the chance of unstated
assumptions or severe bias to one form of expression. Some ways may be a
language for generating test cases, rules for a source code scanner to find the
weakness, or a purely formal description in a highly mathematical notation for
proving program properties.
The executable forms and the expert reviews should be
completely independent. That is, a expert writing an
"executable" form only counts as an expert review (C above) or an
executable (D above), but not both. Also the two experts should not be
from the same organization.
It was suggested that one more step be added: that the
definition be validated to accurately describe some subset of reported
instances of the weakness, like the CVE. The aim is to make sure the
definition corresponds to real examples.
This proposal does not address how the process would be
executed, in particular where the resources would come from.
Nevertheless, We think it is important to begin by getting community agreement
on these two points.
-paul-
« Return to Thread: A Proposal to Precisely Define Weaknesses
| Free embeddable forum powered by Nabble | Forum Help |