[CVEDetailsBridge] Add bridge (#2332)

CVE Details is a collection of CVEs, taken from the National Vulnerability
Database (NVD) and other sources like the Exploit DB and Metasploit. The
website categorizes it by vendor and product and attach the CWE category.
There is an Atom feed available, but only logged in users can use it,
it is not reliable and contain no useful information. This bridge create a
sane feed with additional information like tags and a link to the CWE
a description of the vulnerability.
This commit is contained in:
Aaron F 2021-12-18 05:44:05 +01:00 committed by GitHub
parent 814711e3af
commit e1290aa42c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -0,0 +1,141 @@
<?php
// CVE Details is a collection of CVEs, taken from the National Vulnerability
// Database (NVD) and other sources like the Exploit DB and Metasploit. The
// website categorizes it by vendor and product and attach the CWE category.
// There is a Atom feed available, but only logged in users can use it,
// it is not reliable and contain no useful information. This bridge create a
// sane feed with additional information like tags and a link to the CWE
// a description of the vulnerability.
class CVEDetailsBridge extends BridgeAbstract {
const MAINTAINER = 'Aaron Fischer';
const NAME = 'CVE Details';
const CACHE_TIMEOUT = 60 * 60 * 6; // 6 hours
const DESCRIPTION = 'Report new CVE vulnerabilities for a given vendor (and product)';
const URI = 'https://www.cvedetails.com';
const PARAMETERS = array(array(
// The Vendor ID can be taken from the URL
'vendor_id' => array(
'name' => 'Vendor ID',
'type' => 'number',
'required' => true,
'exampleValue' => 74, // PHP
),
// The optional Product ID can be taken from the URL as well
'product_id' => array(
'name' => 'Product ID',
'type' => 'number',
'required' => false,
'exampleValue' => 128, // PHP
),
));
private $html = null;
private $vendor = '';
private $product = '';
// Return the URL to query.
// Because of the optional product ID, we need to attach it if it is
// set. The search result page has the exact same structure (with and
// without the product ID).
private function _buildURL() {
$url = self::URI . '/vulnerability-list/vendor_id-' . $this->getInput('vendor_id');
if ($this->getInput('product_id') !== '') {
$url .= '/product_id-' . $this->getInput('product_id');
}
// Sadly, there is no way (prove me wrong please) to sort the search
// result by publish date. So the nearest alternative is the CVE
// number, which should be mostly accurate.
$url .= '?order=1'; // Order by CVE number DESC
return $url;
}
// Make the actual request to cvedetails.com and stores the response
// (HTML) for later use and extract vendor and product from it.
private function _fetchContent() {
$html = getSimpleHTMLDOM($this->_buildURL())
or returnServerError('Request failed: ' . $this->_buildURL());
$this->html = defaultLinkTo($html, self::URI);
$vendor = $html->find('#contentdiv > h1 > a', 0);
if ($vendor == null) {
returnServerError('Invalid Vendor ID ' .
$this->getInput('vendor_id') .
' or Product ID ' .
$this->getInput('product_id'));
}
$this->vendor = $vendor->innertext;
$product = $html->find('#contentdiv > h1 > a', 1);
if ($product != null) {
$this->product = $product->innertext;
}
}
// Build the name of the feed.
public function getName() {
if ($this->getInput('vendor_id') == '') {
return self::NAME;
}
if ($this->html == null) {
$this->_fetchContent();
}
$name = 'CVE Vulnerabilities for ' . $this->vendor;
if ($this->product != '') {
$name .= '/' . $this->product;
}
return $name;
}
// Pull the data from the HTML response and fill the items..
public function collectData() {
if ($this->html == null) {
$this->_fetchContent();
}
foreach ($this->html->find('#vulnslisttable .srrowns') as $i => $tr) {
// There are some optional vulnerability types, which will be
// added to the categories as well as the CWE number -- which is
// always given.
$categories = array($this->vendor);
$enclosures = array();
$cwe = $tr->find('td', 2)->find('a', 0);
if ($cwe != null) {
$cwe = $cwe->innertext;
$categories[] = 'CWE-' . $cwe;
$enclosures[] = 'https://cwe.mitre.org/data/definitions/' . $cwe . '.html';
}
$c = $tr->find('td', 4)->innertext;
if (trim($c) != '') {
$categories[] = $c;
}
if ($this->product != '') {
$categories[] = $this->product;
}
// The CVE number itself
$title = $tr->find('td', 1)->find('a', 0)->innertext;
$this->items[] = array(
'uri' => $tr->find('td', 1)->find('a', 0)->href,
'title' => $title,
'timestamp' => $tr->find('td', 5)->innertext,
'content' => $tr->next_sibling()->innertext,
'categories' => $categories,
'enclosures' => $enclosures,
'uid' => $tr->find('td', 1)->find('a', 0)->innertext,
);
// We only want to fetch the latest 10 CVEs
if (count($this->items) >= 10) {
break;
}
}
}
}