The Missing Manual: CVRF 1.1 Part 1 of 2
In this post you will learn about some of the design decisions behind the 1.1 release of the Common Vulnerability Reporting Framework (CVRF). Particular attention is paid to explaining some of the required elements and the Product Tree. After those tasty tidbits, we will convert a recent Cisco security advisory into a well-formed and valid CVRF document. To close, you are treated to some of the items on the docket for future versions of CVRF. It bears mentioning that this paper is not meant to be an exhaustive explanation of the CVRF schemata. It is a rather capricious, if somewhat disorganized look at some outliers that aren’t fully explained elsewhere. It is assumed the reader has a working knowledge of the Common Vulnerability Reporting Framework and of XML.
CVRF: Helping industry get their ducks in a row since 2011
After the release of CVRF 1.0 in May of 2011, I found myself at a dinner with some technical folks. Security automation came up, followed by a brief discussion of CVRF. I somehow managed to coin a phrase that quite succinctly captured what CVRF did, does, and will do. So happy was I that I scribbled it down on a napkin: “…the goal of CVRF is to homogenize and automate the creation and consumption of vulnerability documentation.” Wow, that’s just a profoundly simple yet perfectly encompassing statement. Simple, profound and complete enough to be a mission statement! It’s so important; I think we should restate it and perhaps extol some of the keywords as shown in Figure 1 (click to expand):
Like so much in life, it is simple in concept yet complex in execution. It has taken a group of intrepid ICASI-based adventurers over three years to stitch together your CVRF. To be sure, it has evolved a great deal since we first embarked, but always with the same goal in mind. Currently CVRF is positioned to be the de facto standard in vulnerability documentation automation. CVRF 1.0 was the initial foray into this space. Now, almost one year later, the follow-up, CVRF 1.1 is a major leap forward and represents the current best-of-breed solution. So let’s get on with the show and explore a few core CVRF concepts.
A primary tool of development for CVRF is the mind map. Mind maps are wonderful tools for representing ideas and brainstorming in real-time. As we turn the corner on three years of CVRF development, the principal way CVRF is shown to the World is through a mind map diagram. The legend is shown in Table 1.
CVRF is shown in full in Figure 2 (click to expand).
Let’s Be Objective
One of the major design tenets of CVRF was objectivity over subjectivity. We understand that computer security can be an emotional topic at times, but the framework used to convey information pertaining to that subject should be free from opinion and bias; it should just report facts. With this in mind, CVRF was grown in a lab. Each element was named and defined as objectively as possible. We wanted people, regardless of their background, to be able to understand CVRF the same way.
Data-Driven vs. Presentation-Driven
Another design decision made mid-way through the engineering process was for CVRF to adhere to a data-driven model. This is to say that CVRF is only concerned with packaging up and structuring the data, without regard for how that data will be presented to the end-user. There are no presentation markup elements (for example, HTML’s <b>…</b> or <i>…</i>) included in CVRF.
CVRF Doesn’t Do Anything
CVRF is a language. It is a structured way for one machine to communicate with another machine about a topic their human operators find very interesting: information system vulnerabilities. CVRF was built using XML: XML is a meta-language – it doesn’t actually do anything. CVRF doesn’t actually do anything, either. It is a static framework used to structure, store, and transport information. CVRF is merely a structured container for information about information system vulnerabilities. How that information is ultimately transported, parsed, or used is completely up to its users.
Another design decision of CVRF revolved around the consensus that the document must contain a modicum of mandatory, root-level elements. This is done to ensure a solid and consistent foundation upon which to construct documents. The required elements are shown in Figure 3 (click to expand).
Throughout CVRF, you will find optional container elements that use a plural term as the identifier (e.g. “Threats”), followed by a child container that uses the singular version of the same identifier (e.g. “Threat”). The parent container is usually optional (MinOccurs=0) and cannot occur more than once (MaxOccurs=1), while the child container is required (MinOccurs=1) and can have unlimited instances (MaxOccurs=unbounded).
For example: the Threats container can contain multiple Threat containers. If no threats are to be documented, the Threats container should be omitted altogether. However, if a Threats container is defined, you need to specify at least one (more are allowed) child Threat container as per the following:
<Threats> <Threat Type="Impact"> <Description> Successful exploit this vulnerability results in every byte on the target network being replaced by the ones’ compliment of itself. </Description> </Threat> <Threat Type="Exploit Status"> <Description> The exploit is being carried as part of the OKBDGLOBAL.A1 worm and is in widespread use. </Description> </Threat> <Threat Type="Target Set"> <Description> Every network known to man. </Description> </Threat> </Threats>
CVRF has several unrestricted “string” typed fields that assumed to be human consumable. These fields allow you (as a document producer) to input arbitrary character data without constraint around length or content. The best common practice here is quite simply to ensure this character data is free from markup language tags (XML, HTML, XHTML, etc.). However, in some cases, you will find yourself faced with a situation where you are forced to copy data into a CVRF document that contains markup. Often in a Notes or Entitlement element, it is sometimes unavoidable. The general guidance here is the following:
- Avoid including markup data in string fields. If it is unavoidable see #2.
- Escape the special markup characters (for example & becomes &).
- If large blocks of markup are to be used, employ CDATA tags.
The XML construct CDATA instructs the parser to ignore whatever text is enclosed inside of it. To be clear, when you want to migrate an existing document as-is without needing to worry about encoding XML entities, either escape each special character or use CDATA. Please note that if you want the parser to be able to interpret the text within string sections CDATA can make it difficult for document consumers to parse and transform CVRF documents.
An exception to this rule is when you want to include un-rendered markup elements inside a string element for illustrative purposes. An example:
<Notes> <Note Type="Details" Ordinal="120" Title="Quick Fix" Audience="Technical"> If you change the Tomcat web.xml to the following, the problem will go away: <![CDATA[<parameter timeout="0" />]]> </Note> </Notes>
A CDATA example is below in the Praxis section.
Many elements within a CVRF document allow (or require) you to specify one or more Product ID or Group ID references, indicating that the current element applies to one or more products. In most cases, specifying a Product ID or Group ID is optional, and as such omitting the ID indicates that the current entry is general or non-specific. If an element applies to more than one product, you can choose whether to list all corresponding Product ID values separately, or whether to define a group first and then reference the corresponding Group ID – it’s up to you.
In the Vulnerability section, the following containers allow product referencing: Products/Product, Threats/Threat, CVSS Score Sets/Score Set, and Remediations/Remediation. Additionally, all of these containers follow the previously mentioned conventions for plural/singular container notation.
The Product Tree
The Product Tree is a new construct for CVRF 1.1 and is a total redesign in how CVRF enumerates products in a vulnerability. In earlier versions, after multiple rounds of peer review, we noticed that people were having several issues with the way products were specified:
- It was inefficient: It violated “Don’t Repeat Yourself” model of software development. Since each product was encapsulated inside the Vulnerability container, if you had multiple vulnerabilities in the same product, you would have to repeat the same XML code in each Vulnerability container.
- It was confusing: You could have an Affected Platform and/or an Affected Release that were actually fixed or recommended versions.
- It didn’t enforce machine-parseable names: Affected Platform and Affected Release each had Name attributes that were strings with recommendations, but not restrictions, as to how to best populate them.
To solve these problems, we scrapped Product Family and the Affected elements and created a hierarchical Product Tree as shown in Figure 4 (click to expand).
On a high-level, it contains all of the fully qualified product names that can be referenced elsewhere in a CVRF document. It solved all of the problems above.
- It is efficient: Because the Product Tree is an external to the Vulnerability container(s), it can be specified once within the document and referred to many times. Each Vulnerability container can now contain a reference to the same product rather than having to redundantly list each product over again.
- Product status is clear: Products aren’t assigned a status inside the Product Tree. A product’s susceptibility or inoculation status will be different across vulnerabilities. It is now left up to Vulnerability/Products/Product to assign a status (“Known Affected”, “First Fixed”, and so on).
- Machine consumable naming is permitted: Using the branched method a document producer can create a product name using machine-readable tags combined with human-readable names (see below).
Additionally, it affords the user a way to specify complex relationships between products or components (as a precondition for being vulnerable) using the Relationship container.
To Be Continued…
In the next installment of this blog, you will be taken through the creation of the CVRF 1.1 document from scratch. Stay tuned!