A Proposal to Precisely Define Weaknesses

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

A Proposal to Precisely Define Weaknesses

Michael Koo

            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-

 

Reply | Threaded
Open this post in threaded view
|

Re: A Proposal to Precisely Define Weaknesses

Steven M. Christey-2
Paul and Michael, thank you for raising these important issues along
with your extensive commentary :-)

All - feel free to send any thoughts to this list or privately to
[hidden email].

I will respond to a small piece of Paul's proposal to help get the
ball rolling.  This post will concentrate on where the MITRE team is
with respect to the maturity of existing CWE definitions.  Later posts
will cover Paul's suggestions from a process standpoint.

> We propose, first, that one element of a CWE be designated the prime
> definition.

Our approach for the past year has been to treat the CWE
Description_Summary element as an emerging "prime" definition.  We use
the Extended_Summary to provide some additional details, informal
examples, etc.

For Description_Summary, our goal has been to create a focused
description that is as clear as possible, avoids vague terms, and
omits as much extraneous information as possible.  We do this by
trying to identify the core error, and to avoid conflating these with
closely-related errors (e.g. chains) and attacks.  Recently, we have
been avoiding identifying the typical consequence of the weakness,
which is informally covered in the Extended_Summary element (and often
detailed in the Common_Consequences element).

We also try to write Description_Summary as a single sentence, which
forces us to concentrate on the core issue as much as possible.  One
emerging style that has worked for us is to describe the software's
erroneous behavior with respect to any associated resources that are
affected by that behavior.  The reason *why* the behavior is erroneous
is moved to the Extended_Summary.

We also believe that there needs to be very close alignment between
the Name attribute and the Description_Summary.

Many of our description summaries have been inherited from previous
efforts in which the names or definitions were not so precise; we did
not help our own cause in earlier years when we wrote our own
descriptions, either.

Starting with Draft 9, we have made significant improvements to many
descriptions.  Since Draft 9 was released, we have modified the
descriptions for 311 different entries, and we've modified the names
for 98 entries.  If you read the difference reports
(http://cwe.mitre.org/data/reports.html) you can see that Name and
Description are often one of the most frequently updated elements for
each new version.

There has been some tension in how to capture the Description_Summary
effectively and clearly, without being too verbose or too difficult to
understand.  As Paul has mentioned, CWE has multiple audiences.  In
some cases, we can write a terse Description_Summary using
vulnerability theory terms, but the casual reader might not understand
most of the words in that description.

There are also significant challenges when trying to be more precise,
in that we often realize that we're not sure what the actual CWE entry
is really about!  Consider CWE-377 (currently named "Insecure
Temporary File").  Its description is: "Creating and using insecure
temporary files can leave application and system data vulnerable to
attack."  The immediate question that comes to mind is - what is
"insecure" about the temporary file?  It has bad permissions?  It's
created in a directory with bad permissions?  Its name contains
sensitive information?  It's subject to symlink following?  It's not
deleted after use?  It's accidentally packaged up with other files
before it's sent somewhere else?  This vague name and description are
actually hiding several lower-level weaknesses - yet for certain
audiences, these distinctions are not important, and to adopt a more
precise definition would not help certain audiences.

The labor to come up with an acceptable Description_Summary for all
CWE entries, estimating 30 minutes each, would be approximately 8
staff weeks for weakness-focused entries.  Some of this labor has been
spread over time, but there is still room for improvement.  And note
that in many cases, it will take more than 30 minutes to get clarity -
for example, the buffer overflow examples given by Paul.

To take Paul's example of the current CWE-121 description:

  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).

Under current MITRE practices, ideally we would change this
Description_Summary, perhaps in the following fashion (note: this is
an informal example only):

  - the phrase regarding local variables and function parameters would
    be relocated elsewhere in CWE - probably to the
    Extended_Description

  - the "overwrite" phrase would be avoided or otherwise clarified

  - a next-generation description might be:

      The software allocates a buffer using memory that is stored on
      the stack, but it writes to an address that is outside of the
      implied boundaries of that buffer.

While such a description may still have some subtle problems, it is
closer to our current guidelines for CWE descriptions: it focuses
largely on behavior ("allocate"/"write") and resources
("buffer"/"stack"), while avoiding specific examples or variants
("local variable"), while also attempting to more clearly identify
concepts such as "overflow" and "overwrite" whose terms have many
audience-specific interpretations.

Note that CWE-121 has another larger problem that we frequently
wrestle with.  This CWE's abstraction has a particular perspective
focused on the type of resource (i.e. "buffer on stack") that leads to
conceptual overlap with other resource-independent CWEs (like CWE-125
"out-of-bounds read").  This part of the tree, like many other parts
of CWE, still needs additional research that more clearly identifies
the various perspectives and "layers" that come from various CWE
audiences.  The CWE content team is getting better at identifying when
perspective/layering problems are preventing a clear identification of
a weakness or set of related weaknesses, but fixing these problems is
sometimes difficult.

As Paul has noted, there are many other fields that are related to
other descriptive aspects of a weakness, such as relationship notes,
background details, terminology notes, and white box definitions.  All
of these have specific roles.  They have not been the highest priority
to us, but we clean them up or fill them out when we run across them
(especially when they are in Other_Notes, which historically was a
general-purpose field before we extended the schema for Draft 9 and
version 1.0).

> 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.

This is roughly the approach that we have taken.  However, in some
cases, we may believe that the prime definition is excessively vague
or inconsistent with the rest of the CWE entry.  We will sometimes
deprecate an entry outright if, as a whole, the entry can be
interpreted to cover multiple distinct weaknesses (assuming the entry
is not a category or higher-level asbtraction).  As a result of the
deprecation, we may split it into newer entries that are more clearly
written.

Also, when there is a mismatch between the Name and the Description,
we will strongly consider deprecating the entry, since it is clear to
me that many people map to CWE identifiers based only on the name
without reading the description.

A current example of this problem is CWE-217, which has a very general
name of "Failure to Protect Stored Data from Modification," which was
inherited from CLASP.  But the rest of the original CLASP item - and
much of CWE-217 itself - is focused on a very low-level Java problem
(actually, if you look at the demonstrative examples, it's about a
couple distinct problems).  CWE-217 will be deprecated in the next
version, with a couple replacements that are much more clear.

Another example of definitional confusion/vagueness is CWE-391.  As
its maintenance notes currently say: "This entry needs significant
modification. It currently combines information from three different
taxonomies, but each taxonomy is talking about a slightly different
issue."  However, for us to fully deal with CWE-391, we have been
forced into defining a general model for error handling, which is
incomplete because of perspective/layering problems (see CWE-754 and
CWE-755 for a start).

>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.

We expect to be updating the vulnerability theory document
(http://cwe.mitre.org/documents/vulnerability_theory/intro.html) in
the coming months, which handles some of the gaps.

In addition, we have begun maintaining a glossary of terms here:

  http://cwe.mitre.org/documents/glossary/index.html

While these are not perfect, and they are often still evolving, these
reflect some of the ongoing vocabulary that we are trying to develop.

As Paul has noted, there is other work being done by other
contributors to CWE that can be leveraged or consulted.  Since CWE
operates within multiple audiences, this will sometimes be a difficult
task.  For example, the current ISO/IEC Project 22.24772 document
appears to use the term "encapsulation" in a different way than
McGraw/Chess/Tsipenyuk did, which was also different than how others
may define it.  (Look for my "what is encapsulation?" post coming
sometime in 2009).  When terms like this become overloaded, the
solution for one audience will not necessarily work for another
audience.

The main point of this post was to provide some context: what our
current approach to CWE descriptions has been, and some of the
challenges that will be faced if the community decides that it is
important to adopt a "prime definition."

Any and all feedback is welcome.  Thanks again to Paul and Mike for
raising this question.  I look forward to everyone's thoughts.

- Steve
Reply | Threaded
Open this post in threaded view
|

Re: A Proposal to Precisely Define Weaknesses

Pascal Meunier
In reply to this post by Michael Koo
Michael and Paul,
        Yours is an interesting proposal, and the goals are laudable.  I have
        organized my comments by corresponding section in your proposal.

Section 1.
I accept the premise that careful definitions are better, within the limits of
what is possible or practical.  

Section 2.
I find your examples of difficult cases interesting and well-chosen.  They
illustrate things that IMO are wrong with not just the practices of many
programmers, but also with the "C" language and its compilers. Inasmuch as the
examples have several issues, asking which single weakness that code represents
is itself an ill-posed question.  I would think that language and
compiler/hardware bugs are out-of-scope for the CWE.  Yet, I believe that
you are correct in that the CWE should be robust vs these difficulties.

The code in the SRD test case 201 is wrong at the semantics level, and at that
level it is obviously a buffer overflow.  That is because the semantics of the
type declaration are violated. I believe that the point of the example is that
the compiler happens to allocate extra memory for efficiency reasons, so the
"actual" buffer is not overflowed.  However, what is wrong here is that the
combination of C language, compiler and architecture introduced an ambiguity
about what constitutes the buffer.  The conceptual, "semantic buffer" is
different from the actual one.  It's a fallacy to think that a program that
doesn't trample other memory structures or doesn't crash, due to a happenstance
combination of compiler and architecture, is correct.  IMO it is unfair to ask
that the CWE definitions resolve ambiguities within languages and compilers
themselves.  I think that the CWE should operate and apply at the semantic level
of the code because this is where programmers do their work.  Ambiguities and
bugs within specific languages and compilers should be the problem of the
relevant standards bodies or compiler vendors.  I am tempted to say that the
fact that the program doesn't crash or produce an error is a weakness in the
specification of the "C" language ;).  

The example with alloca() makes it clear that rare cases can be overlooked
when writing definitions for CWE. It's rare because its use is
discouraged and it is not in POSIX.1-2001, according to various man pages.
Consequently I find this oversight not upsetting, even though your point is
well made.  I agree that it would be better if things like this didn't happen.

The SRD test case 188 is similar to 201 and rather obvious to me;  it is wrong
at the semantics level, as there does not exist an element at index 17 for buf1,
and at that level it is obviously a buffer overflow.  As an example possible
consequence, with most compilers and in most environments the contents of buf2
get overwritten, and if those contents had a security meaning then all kinds of
bad things could happen. That the access doesn't go outside the struct and
the program happens not to crash is irrelevant.  

So, how do we make the CWE robust vs these issues?  As a general comment on
those examples, it seems that several were discussed because the consequences
of the violations were possibly or likely benign.  I'd argue that the possible
consequences don't matter, and it many cases they are hard to fathom anyway.
What matters (but see below) is that at a semantic level, a close similarity is
established between those violations and weaknesses known to produce
vulnerable, exploitable code, for the purpose of being classified as instances
of those weaknesses.

I love the example of a network programming structure with a payload, and how
you describe it. It is obviously a hack, albeit a popular hack that works
well and is convenient.  It is also the perfect counterexample to what I've
said above.  The literal semantics of the code are violated, yet few people
would consider this an example of CWE-121.  This is because at a higher level,
we can figure out the intent of the programmer and that the code is safe.
However, if we need to guess at programmer intent on a regular basis in order
to figure out that something is or isn't a weakness, the task is much harder
and difficult to automate. I believe, though, that a scanner could be programmed
to treat an array with a declared size of zero as possibly being a declaration
that the size is probably variable and will be determined later. If it is so
popular, then perhaps the standard needs to be changed and allow a special
notation for an array of a size TBD (to be determined), so programmers can
write what they mean? I think that this is really a problem with standards and
compilers, out of scope for the CWE to resolve. Nevertheless, to achieve the
goal of robustness, the CWE folks are stuck with defining an augmented or
variant "C" instead of the one defined in the standard.  If this example is
only one of a few exceptions, though, it is manageable.  

Section 3.
a) I have reservations on the practicality of requiring the CWE definitions to
be reviewed by experts external to MITRE.  The CVE had a review and vote model
that was overwhelmed by the creation rate of new vulnerabilities. I don't
expect that the number of CWE entries will be anywhere as high as the number of
CVE entries, but in theory the number of ways in which people can get things
wrong is very high and the known ones could keep increasing every year. The
number of replies to your proposal might be indicative of the number of
volunteers MITRE would get for reviewing CWE entries.  Still, the fact that the
SC22/WG23 effort is making progress is encouraging.  I guess we'll really know
only if the CWE folks actually make a request.

b) I'm slightly worried that focusing on a "prime definition" will set the stage
for excessive rules- or wording- lawyering, instead of using "reasoned common
sense".  This phenomenon is common wherever a single prime definition exists.
For example, in some games lacking examples of what the rules mean, the exact
grammar and definitions of words get analysed to a ridiculous extent.  Let's
mention also "legalese", the distortion of human languages attempting to
close loopholes and reach precise meanings.  Its existence is almost proof
that if we want precise and correct prime definitions, we shouldn't use a
natural language.

c) Another aspect is that whereas designating a single, prime definition removes
ambiguity and inconsistencies from consideration, assuming that they are not
contained within the prime definition itself, it also removes redundancy, which
is very useful for catching errors. In a way, I see this proposal as having
disturbing similarities to removing checksums from network messages, or
considering them as wrong if a calculated checksum doesn't match, which defeats
the purpose. The human mind uses many points of references to form a concept;
I'm not sure that a single definition would be able to capture all the
viewpoints and nuances of a problem. I see this as a different issue from your
discussion point as to whether elements refer to completely orthogonal ideas.
In Steve's answer, I note that indeed differences between fields can result in
deprecating an entry.  This confirms the usefulness of redundancy in spotting
"definitional confusion/vagueness".  Granted, if things were done really well
to start with, like you suggest, then perhaps the redundancy wouldn't be
needed (and in a perfect world we wouldn't need backups ;-)).  I like the way
it's been handled by the CWE team.  

d) A minor concern is that focusing on a single definition also devalues the
other fields, so perhaps they will get less attention than they deserve.  I
think all are useful for humans attempting to learn or understand what a
particular weakness is. Could this, as a side effect, make the CWE slightly
more difficult to use, e.g., because there would be fewer examples?

Regards,
Pascal Meunier


On Fri, 1 May 2009 14:51:02 -0400
"Michael Koo" <[hidden email]> wrote:

>             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-
>
>  
>