Not all CVEs are Created Equal. Or even valid…

[I wrote this early 2019 and it was scheduled for January 7 but it apparently did not actually publish and then got lost in my excessive drafts list. I touched it up this week to publish because the example that triggered this blog is old but the response is evergreen. Apologies for the long delay!]

I recently caught a Tweet from @NullCon offering 10 free conferences passes to NullconDasham, awarded to “InfoSec heroes who shared their hard work with the community & contributed to the @CVEnew database“.

I re-Tweeted with comment pointing out “There were at least 311 CVE assignments in 2018 alone, that were for issues that were *not* a vulnerability. I hope you are going to scrutinize the submissions.” Anant Shrivastava replied asking for some examples, and the next morning Mitja Kolsek suggested a blog would be beneficial. Here it is, as short and sweet as I can, which is never short in the world of Vulnerability Databases (VDBs) due to caveats.

The Caveats

Everything in the world of VDBs comes with caveats. Beware of entering a conversation on the topic where neither side of the discussion or debate disclaims themselves, frequently. First, I work on Risk Based Security’s (RBS) VulnDB, a commercial VDB offering that “competes” with CVE. Regardless of quality, some companies will go with ‘free’. I am an outspoken critic of CVE, despite spending 10 years on the CVE Editorial Board trying to guide them and influence them to change for the better.

Second, every VDB will have entries that are deemed “not a vulnerability” (NAV), for two primary reasons. One instance that cannot be avoided is when a researcher disclosed a vulnerability in some fashion, an ID is assigned for tracking purposes, and later deemed not to be a vulnerability. We see this regardless of where a vulnerability is disclosed (e.g. Full Disclosure Mail list or a vendor’s bug tracker). It is the nature of researching vulnerabilities where more testing and scrutiny may reveal it was a one-off, configuration-specific, or simply did not cross privilege boundaries. That last bit is an important point, and more on that later. When these incidents happen, it isn’t a black mark on the VDB who tracked it necessarily. It becomes a black mark if the VDB doesn’t update their entry at a later point to reflect the new information. VDBs simply cannot be a static resource where a vulnerability is added once and never revisited. It has to be a living database that is constantly updated to include new information including additional technical information, re-casting CVSS scores, adding or removing products affected, and/or adding new references to support those changes.

The other common instance of an entry being added to a VDB that is “not a vulnerability” is when an issue is disclosed, and there is no sanity check performed before assigning the ID. While there is merit in “assign for everything for tracking purposes”, that just doesn’t scale any more. The number of bogus reports have been growing considerably the last few years. In some cases, the issue reported will clearly show that it isn’t a vulnerability by e.g. saying “this requires administrative access” and then “exploits” functionality that is there by design. Take for example if I report a cross-site scripting (XSS) issue in blogging software, but it requires administrative access. By design, the administrator is expected to be able to add any JavaScript to support features and make the blog work as intended. As such, my reported issue is not a vulnerability, and should not be given an VDB ID unless there is some equivocation or confusion.

The way MITRE currently operates CVE lends heavily to this problem, as they will hand out assignments and perform little to no scrutiny for most of them. Researchers can just request an ID without providing enough details for them to determine the validity, or the researcher can provide all the details needed and MITRE just doesn’t read the details to notice it may be invalid. Add in their ‘federated’ model, where CVE Numbering Authorities (CNA) can make assignments without MITRE in the loop and it can add to the problem as many CNAs do not follow the rules for assignments in various ways. The other problem with the CVE model, as mentioned in an example above, is that they simply don’t go back to update published entries that often.

Examples of Invalid CVEs

Rather than a laundry list of random CVE IDs, I think it is more beneficial to give some general examples of the types of issues that typically fall in this category with supporting examples. But first, RBS’ VulnDB currently has 1,604 entries that are flagged ‘not a vulnerability’ and have a CVE assignment. There are 209 this year alone, down from the 311 in 2018. But… there are 2,882 NAV in total tracked by VulnDB, so CVE isn’t even properly tracking many of them to then include disclaimers which provides clarity if someone searches for a particular NAV disclosure.

As mentioned above, it is important to understand the fundamental definition or spirit of what constitutes a vulnerability. At the most basic level, it is a flaw that allows an attacker to cross privilege boundaries. In many cases this is straight-forward and we’re all probably familiar with thousands of disclosures that include valid issues that do just that, such as sending a request to a remote server and executing commands as a user we should not have the privileges of. We’re all likely familiar with the plague of context-dependent a.k.a. user-assisted attacks that send malicious content which exploits a flaw in a web browser or PDF reader that leads to information disclosure or arbitrary code execution, often associated with so-called Advanced Persistent Threats (APT) and aggressive malware distribution campaigns. There is no arguing that these issues allow an attacker to perform an action with the privileges of another user, so they constitute vulnerabilities.

On the other hand, there are several types of issues we frequently see disclosed that tend not to be a valid vulnerability, or may be in some circumstances and not others. In no particular order, here are the four most common we see:

1) If you “paste this long exploit string into a field of client software you can make it crash”. For software like a music player, image editor, or PDF viewer, making it crash through malformed input isn’t necessarily a vulnerability. When the exploit requires “tricking” an unsuspecting user to take extraordinary action, such as pasting a 4,000 character string into the song name field, only to have the software crash? No privilege boundaries have been crossed. Tricking them into clicking the ‘X’ at the upper right achieves the same result and the software can be trivially restarted. If an attacker can cause the program to not only terminate, but keep terminating upon re-launch, you can then argue that is a valid denial of service attack.

Two examples of this type of NAV can be found in CVE-2018-18759 for Modbus Slave and CVE-2018-12897 for SolarWinds DameWare Mini remote Control. For Modbus, it requires pasting in a 603 character string to a specific field that will crash the software. Based on the disclosure, under no circumstances does this cross privilege boundaries; if there is a valid issue here, it is not demonstrated at all. As is, this is just a stability bug for all intents and purposes.

For SolarWinds it is a bit murky as it requires tricking someone into pasting in a string of over 2000 characters resulting in a buffer overflow. While this can potentially lead to arbitrary code execution, the exploit vector is what OSVDB called “Yes, pigs DO fly!“. Meaning, it is technically possible, but highly unlikely. It is just as easy to argue that if you can trick someone into that action, you can more easily convince them to open a command shell and type out shorter commands to be executed with their privileges. There are additional occurrences of this in the CVE database, as well as MITRE catching some and flagging them as DISPUTED, such as CVE-2018-17231.

2) Perhaps the most prevalent the last few years are DLL loading attacks. Known as “DLL path subversion” or “DLL hijacking” among other terms, the fundamental premise is if you can convince a privileged program, or one under higher/different privileges than your own, to execute your own code you can cross privilege boundaries. While a large majority of these reported in the previous years are on Windows, such attacks go back a couple decades to *nix platforms. Regardless of the platform, the attack vector and if it is a valid issue rests on two simple questions. What privileges are required to conduct the attack, and what privileges is the foreign code executed under when exploited? Answering these two will quickly determine if the issue is valid. Unfortunately, too many researchers and vendors tend to answer one or the other. Just one answer, either one, doesn’t prove there is a vulnerability. In conjunction with each other, you either prove or disprove the issue.

While this type of issue can manifest technically in a number of ways, we typically see disclosures centered around the same scenario. A user on a Windows box can create or overwrite a DLL file in a specific place, which will be loaded by the program and the code executed when the program is next launched. This can be due to weak permissions that allows a regular user to write to a location that should be privileged (e.g. C:\Program Files\Microsoft Office\Office12) or due to a pathing issue, where the program checks an insecure directory for a DLL before looking in the appropriate privileged location. Disclosures related to DLL subversion should make it crystal clear if the flaw is due to permissions, and if so include the permissions of the insecure resource, or if the flaw is due to the program and/or system path, and include the actual search path if so. With most disclosures failing to answer the two basic questions, or provide adequate proof of the vulnerability, we often find out that the first question boils down to “a user with administrator privileges” which instantly makes it not a vulnerability. Doesn’t matter that the second question is answered with “code is executed as administrator!” Privilege boundaries are not being crossed. Microsoft has written an excellent blog on this topic, titled “Triaging a DLL planting vulnerability

For a few specific examples:

  1. We see this frequently from JVN advisories that talk about DLL search path issues that include the installer path. Since the attacker would have to plant the file where the installer runs, and the typical default directories such as ‘Downloads’ does not allow this behavior, it boils down to a known insecure behavior on the part of the user. If you can get them to download, save, and install the program from a specific directory where you have permissions, you can trick them into doing bad things in more simple ways. Since JVN is a CNA, they assign CVE IDs to these, which often sit in RESERVED status for weeks.
  2. Another common example can be seen in CVE-2018-20211 which covers a reported issue in Exiftool based on a Full Disclosure post. In this case, the reported issue does not demonstrate an attack vector that crosses privilege boundaries, as planting a DLL in the system’s %TEMP% directory requires a privileged account. This is a case where it may be an actual issue, but based on the public information it is not.
  3. The last type we frequently see comes from vendors, who you may assume would be the end-all source of a vulnerability. Unfortunately, history shows that is not always the case, and that some of their developers and researchers don’t necessarily consider all of the factors. As such, when we see a vendor advisory that highly suggests it is the same as the first bullet, but doesn’t give enough details, we’re left in limbo with an issue that may or may not be valid. Based strictly on their wording that “this particular type of exploit only manifests at install time” strongly suggests this is not a valid issue, and falls under bullet one. Since Symantec is a CNA, one of their issues got assigned CVE-2018-12245. In this case the CVE ID is open, but Microsoft does not dispute it or caveat it. Instead, they trust the vendor fully despite their collective history of vulnerability aggregation suggesting this may not be an issue.

3) Akin to the example number one, we see a large number of Out-of-bounds Read issues reported against command-line utilities. First, let’s make it clear we’re talking about an OOB read, not an OOB write (both of which enjoy the name “overflow” in ASAN output). Not all ‘overflows’ are created equal! When it comes to third-party libraries that may process user-supplied input, exploit scenarios and impacts can vary. When it comes to command-line tools or example programs in those libraries, the exploitation scenarios begin to dwindle. When it is purely a command-line utility and an OOB read leading to a crash, we often see that reported as a denial of service. In reality, it is just the command-line version of the first example above. The program will crash and provide no benefit to the attacker. The user can just re-execute the command as if nothing had happened. Just because the input made the program read a portion of privileged memory doesn’t mean it gets disclosed to anyone, let alone the attacker. These issues, along with their CVE assignments, have become more prevalent due to the high adoption rate of using fuzzers to find potential issues. So we’re seeing them in software such as Netwide Assembler (NASM), Xpdf, and Ming (libming) which in at least one case received two separate CVE IDs despite neither being valid.

Yes, every researcher seems to want to collect CVEs, and I get it. But know this; just having a laundry list of CVE IDs only gets you past people who don’t know vulnerabilities or how the CVE ecosystem works. The first time your resume is put in front of a vulnerability analyst who takes the time to look at your disclosure? The gig may be up before you ever get it.

Leave a Reply

%d bloggers like this: