diff --git a/AUTHORS.rst b/AUTHORS.rst
index ba09d47b0..95a1f3473 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -13,4 +13,5 @@ The following organizations or individuals have contributed to this repo:
- Navonil Das @NavonilDas
- Tushar Upadhyay @tushar912
- Hritik Vijay @hritik14
-- Tushar Goel @TG1999
\ No newline at end of file
+- Tushar Goel @TG1999
+- Keshav Priyadarshi @keshav-space
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 8ed9f1f26..9510a4e3f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -112,4 +112,4 @@ urllib3==1.26.9
wcwidth==0.2.5
websocket-client==0.59.0
yarl==1.7.2
-zipp==3.8.0
+zipp==3.8.0
\ No newline at end of file
diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py
index 261106685..2334c2d86 100644
--- a/vulnerabilities/importers/__init__.py
+++ b/vulnerabilities/importers/__init__.py
@@ -23,12 +23,15 @@
from vulnerabilities.importers import github
from vulnerabilities.importers import nginx
from vulnerabilities.importers import nvd
+from vulnerabilities.importers import openssl
+
IMPORTERS_REGISTRY = [
nginx.NginxImporter,
alpine_linux.AlpineImporter,
github.GitHubAPIImporter,
nvd.NVDImporter,
+ openssl.OpensslImporter,
]
IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY}
diff --git a/vulnerabilities/importers/openssl.py b/vulnerabilities/importers/openssl.py
index 2ae36168c..53d73b4cf 100644
--- a/vulnerabilities/importers/openssl.py
+++ b/vulnerabilities/importers/openssl.py
@@ -20,101 +20,152 @@
# VulnerableCode is a free software code scanning tool from nexB Inc. and others.
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
-import dataclasses
-import re
-import xml.etree.ElementTree as ET
-from typing import Set
+import logging
+from datetime import timezone
+from typing import Iterable
+from urllib.parse import urljoin
+import defusedxml.ElementTree as DET
import requests
+from dateutil import parser as dateparser
from packageurl import PackageURL
+from univers.version_range import OpensslVersionRange
+from univers.versions import OpensslVersion
-from vulnerabilities.helpers import create_etag
-from vulnerabilities.helpers import nearest_patched_package
-from vulnerabilities.importer import Advisory
+from vulnerabilities.importer import AdvisoryData
+from vulnerabilities.importer import AffectedPackage
from vulnerabilities.importer import Importer
from vulnerabilities.importer import Reference
+from vulnerabilities.importer import VulnerabilitySeverity
+from vulnerabilities.severity_systems import SCORING_SYSTEMS
+logger = logging.getLogger(__name__)
-class OpenSSLImporter(Importer):
+class OpensslImporter(Importer):
+ spdx_license_expression = "Apache-2.0"
+ license_url = "https://github.com/openssl/openssl/blob/master/LICENSE.txt"
url = "https://www.openssl.org/news/vulnerabilities.xml"
- def updated_advisories(self) -> Set[Advisory]:
- # Etags are like hashes of web responses. We maintain
- # (url, etag) mappings in the DB. `create_etag` creates
- # (url, etag) pair. If a (url, etag) already exists then the code
- # skips processing the response further to avoid duplicate work
- if create_etag(data_src=self, url=self.url, etag_key="ETag"):
- raw_data = self.fetch()
- advisories = self.to_advisories(raw_data)
- return self.batch_advisories(advisories)
-
- return []
-
def fetch(self):
- return requests.get(self.url).content
-
- @staticmethod
- def to_advisories(xml_response: str) -> Set[Advisory]:
- advisories = []
- pkg_name = "openssl"
- pkg_type = "generic"
- root = ET.fromstring(xml_response)
- for element in root:
- if element.tag == "issue":
- cve_id = ""
- summary = ""
- safe_pkg_versions = []
- vuln_pkg_versions = []
- ref_urls = []
- for info in element:
-
- if info.tag == "cve":
- if info.attrib.get("name"):
- cve_id = "CVE-" + info.attrib.get("name")
-
- else:
- continue
-
- if cve_id == "CVE-2007-5502":
- # This CVE has weird version "fips-1.1.2".This is
- # probably a submodule. Skip this for now.
- continue
-
- if info.tag == "affects":
- # Vulnerable package versions
- vuln_pkg_versions.append(info.attrib.get("version"))
-
- if info.tag == "fixed":
- # Fixed package versions
- safe_pkg_versions.append(info.attrib.get("version"))
-
- if info:
- commit_hash = info[0].attrib["hash"]
- ref_urls.append(
- Reference(
- url="https://github.com/openssl/openssl/commit/" + commit_hash
- )
- )
- if info.tag == "description":
- # Description
- summary = re.sub(r"\s+", " ", info.text).strip()
-
- safe_purls = [
- PackageURL(name=pkg_name, type=pkg_type, version=version)
- for version in safe_pkg_versions
- ]
- vuln_purls = [
- PackageURL(name=pkg_name, type=pkg_type, version=version)
- for version in vuln_pkg_versions
- ]
-
- advisory = Advisory(
- vulnerability_id=cve_id,
- summary=summary,
- affected_packages=nearest_patched_package(vuln_purls, safe_purls),
- references=ref_urls,
+ response = requests.get(url=self.url)
+ if not response.status_code == 200:
+ logger.error(f"Error while fetching {self.url}: {response.status_code}")
+ return
+ return response.content
+
+ def advisory_data(self) -> Iterable[AdvisoryData]:
+ xml_response = self.fetch()
+ return parse_vulnerabilities(xml_response)
+
+
+def parse_vulnerabilities(xml_response) -> Iterable[AdvisoryData]:
+ root = DET.fromstring(xml_response)
+ for xml_issue in root:
+ if xml_issue.tag == "issue":
+ advisory = to_advisory_data(xml_issue)
+ if advisory:
+ yield advisory
+
+
+def to_advisory_data(xml_issue) -> AdvisoryData:
+ """
+ Return AdvisoryData from given xml_issue
+ """
+
+ purl = PackageURL(type="openssl", name="openssl")
+ cve = advisory_url = severity = summary = None
+ safe_pkg_versions = {}
+ vuln_pkg_versions_by_base_version = {}
+ aliases = []
+ references = []
+ affected_packages = []
+ date_published = xml_issue.attrib["public"].strip()
+
+ for info in xml_issue:
+ if info.tag == "impact":
+ severity = VulnerabilitySeverity(
+ system=SCORING_SYSTEMS["generic_textual"], value=info.attrib["severity"]
+ )
+
+ elif info.tag == "advisory":
+ advisory_url = info.attrib["url"]
+ if not advisory_url.startswith("https://web.archive.org"):
+ advisory_url = urljoin("https://www.openssl.org", advisory_url)
+
+ elif info.tag == "cve":
+ cve = info.attrib.get("name")
+ # use made up alias to compensate for case when advisory doesn't have CVE-ID
+ madeup_alias = f"VC-OPENSSL-{date_published}"
+ if cve:
+ cve = f"CVE-{cve}"
+ madeup_alias = f"{madeup_alias}-{cve}"
+ aliases.append(cve)
+ references.append(Reference(reference_id=cve))
+ aliases.append(madeup_alias)
+
+ elif info.tag == "affects":
+ affected_base = info.attrib["base"]
+ affected_version = info.attrib["version"]
+ if affected_base.startswith("fips"):
+ logger.error(
+ f"{affected_base!r} is a OpenSSL-FIPS Object Module and isn't supported by OpensslImporter. Use a different importer."
+ )
+ return
+ if affected_base in vuln_pkg_versions_by_base_version:
+ vuln_pkg_versions_by_base_version[affected_base].append(affected_version)
+ else:
+ vuln_pkg_versions_by_base_version[affected_base] = [affected_version]
+
+ elif info.tag == "fixed":
+ fixed_base = info.attrib["base"]
+ fixed_version = info.attrib["version"]
+ safe_pkg_versions[fixed_base] = fixed_version
+ for commit in info:
+ commit_hash = commit.attrib["hash"]
+ references.append(
+ Reference(
+ url=urljoin("https://github.com/openssl/openssl/commit/", commit_hash)
+ )
)
- advisories.append(advisory)
- return advisories
+ elif info.tag == "description":
+ summary = " ".join(info.text.split())
+
+ elif info.tag in ("reported", "problemtype", "title"):
+ # as of now, these info isn't useful for AdvisoryData
+ # for more see: https://github.com/nexB/vulnerablecode/issues/688
+ continue
+ else:
+ logger.error(
+ f"{info.tag!r} is a newly introduced tag. Modify the importer to make use of this new info."
+ )
+
+ for base_version, affected_versions in vuln_pkg_versions_by_base_version.items():
+ affected_version_range = OpensslVersionRange.from_versions(affected_versions)
+ fixed_version = None
+ if base_version in safe_pkg_versions:
+ fixed_version = OpensslVersion(safe_pkg_versions[base_version])
+ affected_package = AffectedPackage(
+ package=purl,
+ affected_version_range=affected_version_range,
+ fixed_version=fixed_version,
+ )
+ affected_packages.append(affected_package)
+
+ if severity and advisory_url:
+ references.append(Reference(url=advisory_url, severities=[severity]))
+ elif advisory_url:
+ references.append(Reference(url=advisory_url))
+
+ parsed_date_published = dateparser.parse(date_published, yearfirst=True).replace(
+ tzinfo=timezone.utc
+ )
+
+ return AdvisoryData(
+ aliases=aliases,
+ summary=summary,
+ affected_packages=affected_packages,
+ references=references,
+ date_published=parsed_date_published,
+ )
diff --git a/vulnerabilities/tests/conftest.py b/vulnerabilities/tests/conftest.py
index 0bb246db3..6cd796789 100644
--- a/vulnerabilities/tests/conftest.py
+++ b/vulnerabilities/tests/conftest.py
@@ -48,7 +48,6 @@ def no_rmtree(monkeypatch):
"test_npm.py",
"test_apache_kafka.py",
"test_apache_tomcat.py",
- "test_openssl.py",
"test_api.py",
"test_package_managers.py",
"test_archlinux.py",
diff --git a/vulnerabilities/tests/test_data/openssl/openssl-expected.json b/vulnerabilities/tests/test_data/openssl/openssl-expected.json
new file mode 100644
index 000000000..7107ac6e7
--- /dev/null
+++ b/vulnerabilities/tests/test_data/openssl/openssl-expected.json
@@ -0,0 +1,246 @@
+[
+ {
+ "aliases": [
+ "CVE-2021-3712",
+ "VC-OPENSSL-20210824-CVE-2021-3712"
+ ],
+ "summary": "ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING structure which contains a buffer holding the string data and a field holding the buffer length. This contrasts with normal C strings which are repesented as a buffer for the string data which is terminated with a NUL (0) byte. Although not a strict requirement, ASN.1 strings that are parsed using OpenSSL's own \"d2i\" functions (and other similar parsing functions) as well as any string whose value has been set with the ASN1_STRING_set() function will additionally NUL terminate the byte array in the ASN1_STRING structure. However, it is possible for applications to directly construct valid ASN1_STRING structures which do not NUL terminate the byte array by directly setting the \"data\" and \"length\" fields in the ASN1_STRING array. This can also happen by using the ASN1_STRING_set0() function. Numerous OpenSSL functions that print ASN.1 data have been found to assume that the ASN1_STRING byte array will be NUL terminated, even though this is not guaranteed for strings that have been directly constructed. Where an application requests an ASN.1 structure to be printed, and where that ASN.1 structure contains ASN1_STRINGs that have been directly constructed by the application without NUL terminating the \"data\" field, then a read buffer overrun can occur. The same thing can also occur during name constraints processing of certificates (for example if a certificate has been directly constructed by the application instead of loading it via the OpenSSL parsing functions, and the certificate contains non NUL terminated ASN1_STRING structures). It can also occur in the X509_get1_email(), X509_REQ_get1_email() and X509_get1_ocsp() functions. If a malicious actor can cause an application to directly construct an ASN1_STRING and then process it through one of the affected OpenSSL functions then this issue could be hit. This might result in a crash (causing a Denial of Service attack). It could also result in the disclosure of private memory contents (such as private keys, or sensitive plaintext).",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.1.1|1.1.1a|1.1.1b|1.1.1c|1.1.1d|1.1.1e|1.1.1f|1.1.1g|1.1.1h|1.1.1i|1.1.1j|1.1.1k",
+ "fixed_version": "1.1.1l"
+ },
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.0.2|1.0.2|1.0.2a|1.0.2b|1.0.2c|1.0.2d|1.0.2e|1.0.2f|1.0.2g|1.0.2h|1.0.2i|1.0.2j|1.0.2k|1.0.2l|1.0.2m|1.0.2n|1.0.2o|1.0.2p|1.0.2q|1.0.2r|1.0.2s|1.0.2t|1.0.2u|1.0.2w|1.0.2x|1.0.2y",
+ "fixed_version": "1.0.2za"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "CVE-2021-3712",
+ "url": "",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/94d23fcff9b2a7a8368dfe52214d5c2569882c11",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/ccb0a11145ee72b042d10593a64eaf9e8a55ec12",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://www.openssl.org/news/secadv/20210824.txt",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "Moderate"
+ }
+ ]
+ }
+ ],
+ "date_published": "2021-08-24T00:00:00+00:00"
+ },
+ {
+ "aliases": [
+ "CVE-2019-1551",
+ "VC-OPENSSL-20191206-CVE-2019-1551"
+ ],
+ "summary": "There is an overflow bug in the x64_64 Montgomery squaring procedure used in exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a result of this defect would be very difficult to perform and are not believed likely. Attacks against DH512 are considered just feasible. However, for an attack the target would have to re-use the DH512 private key, which is not recommended anyway. Also applications directly using the low level API BN_mod_exp may be affected if they use BN_FLG_CONSTTIME.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.1.1|1.1.1a|1.1.1b|1.1.1c|1.1.1d",
+ "fixed_version": "1.1.1e"
+ },
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.0.2|1.0.2a|1.0.2b|1.0.2c|1.0.2d|1.0.2e|1.0.2f|1.0.2g|1.0.2h|1.0.2i|1.0.2j|1.0.2k|1.0.2l|1.0.2m|1.0.2n|1.0.2o|1.0.2p|1.0.2q|1.0.2r|1.0.2s|1.0.2t",
+ "fixed_version": "1.0.2u"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "CVE-2019-1551",
+ "url": "",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/419102400a2811582a7a3d4a4e317d72e5ce0a8f",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/f1c5eea8a817075d31e43f5876993c6710238c98",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://www.openssl.org/news/secadv/20191206.txt",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "Low"
+ }
+ ]
+ }
+ ],
+ "date_published": "2019-12-06T00:00:00+00:00"
+ },
+ {
+ "aliases": [
+ "CVE-2009-1379",
+ "VC-OPENSSL-20090512-CVE-2009-1379"
+ ],
+ "summary": "Use-after-free vulnerability in the dtls1_retrieve_buffered_fragment function could cause a client accessing a malicious DTLS server to crash.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/0.9.8|0.9.8a|0.9.8b|0.9.8c|0.9.8d|0.9.8e|0.9.8f|0.9.8g|0.9.8h|0.9.8i|0.9.8j|0.9.8k|0.9.8l",
+ "fixed_version": "0.9.8m"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "CVE-2009-1379",
+ "url": "",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/561cbe567846a376153bea7f1f2d061e78029c2d",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://web.archive.org/web/20100824233642/http://rt.openssl.org/Ticket/Display.html?id=1923&user=guest&pass=guest",
+ "severities": []
+ }
+ ],
+ "date_published": "2009-05-12T00:00:00+00:00"
+ },
+ {
+ "aliases": [
+ "CVE-2019-1552",
+ "VC-OPENSSL-20190730-CVE-2019-1552"
+ ],
+ "summary": "OpenSSL has internal defaults for a directory tree where it can find a configuration file as well as certificates used for verification in TLS. This directory is most commonly referred to as OPENSSLDIR, and is configurable with the --prefix / --openssldir configuration options. For OpenSSL versions 1.1.0 and 1.1.1, the mingw configuration targets assume that resulting programs and libraries are installed in a Unix-like environment and the default prefix for program installation as well as for OPENSSLDIR should be '/usr/local'. However, mingw programs are Windows programs, and as such, find themselves looking at sub-directories of 'C:/usr/local', which may be world writable, which enables untrusted users to modify OpenSSL's default configuration, insert CA certificates, modify (or even replace) existing engine modules, etc. For OpenSSL 1.0.2, '/usr/local/ssl' is used as default for OPENSSLDIR on all Unix and Windows targets, including Visual C builds. However, some build instructions for the diverse Windows targets on 1.0.2 encourage you to specify your own --prefix. OpenSSL versions 1.1.1, 1.1.0 and 1.0.2 are affected by this issue. Due to the limited scope of affected deployments this has been assessed as low severity and therefore we are not creating new releases at this time.",
+ "affected_packages": [
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.1.1|1.1.1a|1.1.1b|1.1.1c",
+ "fixed_version": "1.1.1d"
+ },
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.1.0|1.1.0a|1.1.0b|1.1.0c|1.1.0d|1.1.0e|1.1.0f|1.1.0g|1.1.0h|1.1.0i|1.1.0j|1.1.0k",
+ "fixed_version": "1.1.0l"
+ },
+ {
+ "package": {
+ "type": "openssl",
+ "namespace": null,
+ "name": "openssl",
+ "version": null,
+ "qualifiers": null,
+ "subpath": null
+ },
+ "affected_version_range": "vers:openssl/1.0.2|1.0.2a|1.0.2b|1.0.2c|1.0.2d|1.0.2e|1.0.2f|1.0.2g|1.0.2h|1.0.2i|1.0.2j|1.0.2k|1.0.2l|1.0.2m|1.0.2n|1.0.2o|1.0.2p|1.0.2q|1.0.2r|1.0.2s",
+ "fixed_version": "1.0.2t"
+ }
+ ],
+ "references": [
+ {
+ "reference_id": "CVE-2019-1552",
+ "url": "",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/54aa9d51b09d67e90db443f682cface795f5af9e",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/e32bc855a81a2d48d215c506bdeb4f598045f7e9",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/b15a19c148384e73338aa7c5b12652138e35ed28",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://github.com/openssl/openssl/commit/d333ebaf9c77332754a9d5e111e2f53e1de54fdd",
+ "severities": []
+ },
+ {
+ "reference_id": "",
+ "url": "https://www.openssl.org/news/secadv/20190730.txt",
+ "severities": [
+ {
+ "system": "generic_textual",
+ "value": "Low"
+ }
+ ]
+ }
+ ],
+ "date_published": "2019-07-30T00:00:00+00:00"
+ }
+]
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/openssl/openssl_xml_data.xml b/vulnerabilities/tests/test_data/openssl/openssl_xml_data.xml
new file mode 100644
index 000000000..959fa0f7e
--- /dev/null
+++ b/vulnerabilities/tests/test_data/openssl/openssl_xml_data.xml
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Buffer overflow
+ Read buffer overruns processing ASN.1 strings
+
+ ASN.1 strings are represented internally within OpenSSL as an ASN1_STRING
+ structure which contains a buffer holding the string data and a field holding
+ the buffer length. This contrasts with normal C strings which are repesented as
+ a buffer for the string data which is terminated with a NUL (0) byte.
+
+ Although not a strict requirement, ASN.1 strings that are parsed using OpenSSL's
+ own "d2i" functions (and other similar parsing functions) as well as any string
+ whose value has been set with the ASN1_STRING_set() function will additionally
+ NUL terminate the byte array in the ASN1_STRING structure.
+
+ However, it is possible for applications to directly construct valid ASN1_STRING
+ structures which do not NUL terminate the byte array by directly setting the
+ "data" and "length" fields in the ASN1_STRING array. This can also happen by
+ using the ASN1_STRING_set0() function.
+
+ Numerous OpenSSL functions that print ASN.1 data have been found to assume that
+ the ASN1_STRING byte array will be NUL terminated, even though this is not
+ guaranteed for strings that have been directly constructed. Where an application
+ requests an ASN.1 structure to be printed, and where that ASN.1 structure
+ contains ASN1_STRINGs that have been directly constructed by the application
+ without NUL terminating the "data" field, then a read buffer overrun can occur.
+
+ The same thing can also occur during name constraints processing of certificates
+ (for example if a certificate has been directly constructed by the application
+ instead of loading it via the OpenSSL parsing functions, and the certificate
+ contains non NUL terminated ASN1_STRING structures). It can also occur in the
+ X509_get1_email(), X509_REQ_get1_email() and X509_get1_ocsp() functions.
+
+ If a malicious actor can cause an application to directly construct an
+ ASN1_STRING and then process it through one of the affected OpenSSL functions
+ then this issue could be hit. This might result in a crash (causing a Denial of
+ Service attack). It could also result in the disclosure of private memory
+ contents (such as private keys, or sensitive plaintext).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Integer overflow bug
+ rsaz_512_sqr overflow bug on x86_64
+
+ There is an overflow bug in the x64_64 Montgomery squaring procedure used in
+ exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis
+ suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a
+ result of this defect would be very difficult to perform and are not believed
+ likely. Attacks against DH512 are considered just feasible. However, for an
+ attack the target would have to re-use the DH512 private key, which is not
+ recommended anyway. Also applications directly using the low level API
+ BN_mod_exp may be affected if they use BN_FLG_CONSTTIME.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use-after-free vulnerability in the dtls1_retrieve_buffered_fragment
+ function could cause a client accessing a malicious DTLS server to
+ crash.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Insecure defaults
+ Windows builds with insecure path defaults
+ OpenSSL has internal defaults for a directory tree where it can find a configuration file as well as certificates used for verification in TLS. This directory is most commonly referred to as OPENSSLDIR, and is configurable with the --prefix / --openssldir configuration options. For OpenSSL versions 1.1.0 and 1.1.1, the mingw configuration targets assume that resulting programs and libraries are installed in a Unix-like environment and the default prefix for program installation as well as for OPENSSLDIR should be '/usr/local'. However, mingw programs are Windows programs, and as such, find themselves looking at sub-directories of 'C:/usr/local', which may be world writable, which enables untrusted users to modify OpenSSL's default configuration, insert CA certificates, modify (or even replace) existing engine modules, etc. For OpenSSL 1.0.2, '/usr/local/ssl' is used as default for OPENSSLDIR on all Unix and Windows targets, including Visual C builds. However, some build instructions for the diverse Windows targets on 1.0.2 encourage you to specify your own --prefix. OpenSSL versions 1.1.1, 1.1.0 and 1.0.2 are affected by this issue. Due to the limited scope of affected deployments this has been assessed as low severity and therefore we are not creating new releases at this time.
+
+
+
+
\ No newline at end of file
diff --git a/vulnerabilities/tests/test_data/openssl_xml_data.xml b/vulnerabilities/tests/test_data/openssl_xml_data.xml
deleted file mode 100644
index fcea46e92..000000000
--- a/vulnerabilities/tests/test_data/openssl_xml_data.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- NULL pointer dereference
- Segmentation fault in SSL_check_chain
-
- Server or client applications that call the SSL_check_chain() function during or
- after a TLS 1.3 handshake may crash due to a NULL pointer dereference as a
- result of incorrect handling of the "signature_algorithms_cert" TLS extension.
- The crash occurs if an invalid or unrecognised signature algorithm is received
- from the peer. This could be exploited by a malicious peer in a Denial of
- Service attack. OpenSSL version 1.1.1d, 1.1.1e, and 1.1.1f are affected by this issue. This
- issue did not affect OpenSSL versions prior to 1.1.1d.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Integer overflow bug
- rsaz_512_sqr overflow bug on x86_64
-
- There is an overflow bug in the x64_64 Montgomery squaring procedure used in
- exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis
- suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a
- result of this defect would be very difficult to perform and are not believed
- likely. Attacks against DH512 are considered just feasible. However, for an
- attack the target would have to re-use the DH512 private key, which is not
- recommended anyway. Also applications directly using the low level API
- BN_mod_exp may be affected if they use BN_FLG_CONSTTIME.
-
-
-
-
-
-
-
diff --git a/vulnerabilities/tests/test_openssl.py b/vulnerabilities/tests/test_openssl.py
index 2f1de46c1..ee191bded 100644
--- a/vulnerabilities/tests/test_openssl.py
+++ b/vulnerabilities/tests/test_openssl.py
@@ -20,466 +20,108 @@
# VulnerableCode is a free software code scanning tool from nexB Inc. and others.
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
+
+import datetime
+import json
import os
import unittest
-from collections import OrderedDict
+from typing import Iterable
+import defusedxml.ElementTree as DET
from packageurl import PackageURL
+from univers.version_constraint import VersionConstraint
+from univers.version_range import OpensslVersionRange
+from univers.versions import OpensslVersion
-from vulnerabilities.helpers import AffectedPackage
-from vulnerabilities.importer import Advisory
+from vulnerabilities.importer import AdvisoryData
+from vulnerabilities.importer import AffectedPackage
from vulnerabilities.importer import Reference
-from vulnerabilities.importers.openssl import OpenSSLImporter
+from vulnerabilities.importer import VulnerabilitySeverity
+from vulnerabilities.importers.openssl import parse_vulnerabilities
+from vulnerabilities.importers.openssl import to_advisory_data
+from vulnerabilities.severity_systems import SCORING_SYSTEMS
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
-TEST_DATA = os.path.join(BASE_DIR, "test_data/", "openssl_xml_data.xml")
-
+TEST_DATA = os.path.join(BASE_DIR, "test_data", "openssl")
-def load_test_data():
- with open(TEST_DATA) as f:
- return f.read()
+class TestOpenssl(unittest.TestCase):
+ # use regen flag to generates the expected_file
+ def test_parse_vulnerabilities(self, regen=True):
+ xml_page = os.path.join(TEST_DATA, "openssl_xml_data.xml")
+ with open(xml_page) as f:
+ xml_response = f.read()
+ result = [data.to_dict() for data in parse_vulnerabilities(xml_response)]
-class TestOpenSSL(unittest.TestCase):
- def test_to_advisory(self):
- data = load_test_data()
- expected_advisories = [
- Advisory(
- summary='Server or client applications that call the SSL_check_chain() function during or after a TLS 1.3 handshake may crash due to a NULL pointer dereference as a result of incorrect handling of the "signature_algorithms_cert" TLS extension. The crash occurs if an invalid or unrecognised signature algorithm is received from the peer. This could be exploited by a malicious peer in a Denial of Service attack. OpenSSL version 1.1.1d, 1.1.1e, and 1.1.1f are affected by this issue. This issue did not affect OpenSSL versions prior to 1.1.1d.',
- vulnerability_id="CVE-2020-1967",
- affected_packages=[
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1d",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1g",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1g",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1f",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1g",
- ),
- ),
- ],
- references=[
- Reference(
- reference_id="",
- url="https://github.com/openssl/openssl/commit/eb563247aef3e83dda7679c43f9649270462e5b1",
- severities=[],
- )
- ],
- ),
- Advisory(
- summary="There is an overflow bug in the x64_64 Montgomery squaring procedure used in exponentiation with 512-bit moduli. No EC algorithms are affected. Analysis suggests that attacks against 2-prime RSA1024, 3-prime RSA1536, and DSA1024 as a result of this defect would be very difficult to perform and are not believed likely. Attacks against DH512 are considered just feasible. However, for an attack the target would have to re-use the DH512 private key, which is not recommended anyway. Also applications directly using the low level API BN_mod_exp may be affected if they use BN_FLG_CONSTTIME.",
- vulnerability_id="CVE-2019-1551",
- affected_packages=[
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2a",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2b",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2c",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2d",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2e",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2f",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2g",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2h",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2i",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2j",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2k",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2l",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2m",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2n",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2o",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2p",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2q",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2r",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2s",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2t",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.0.2u",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1",
- ),
- patched_package=None,
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1a",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1b",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1c",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- ),
- AffectedPackage(
- vulnerable_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1d",
- ),
- patched_package=PackageURL(
- type="generic",
- namespace=None,
- name="openssl",
- version="1.1.1e",
- ),
- ),
- ],
- references=[
- Reference(
- reference_id="",
- url="https://github.com/openssl/openssl/commit/419102400a2811582a7a3d4a4e317d72e5ce0a8f",
- severities=[],
- ),
- Reference(
- reference_id="",
- url="https://github.com/openssl/openssl/commit/f1c5eea8a817075d31e43f5876993c6710238c98",
- severities=[],
- ),
- ],
- ),
- ]
+ expected_file = os.path.join(TEST_DATA, "openssl-expected.json")
+ if regen:
+ with open(expected_file, "w") as f:
+ json.dump(result, f, indent=2)
+ expected = result
+ else:
+ with open(expected_file) as f:
+ expected = json.load(f)
+ assert result == expected
- found_advisories = OpenSSLImporter.to_advisories(data)
+ def test_to_advisory_data(self):
+ issue_string = """
+
+
+
+
+
+
+ Unauthenticated read/unencrypted write
+ Read/write after SSL object in error state
+ OpenSSL 1.0.2 (starting from version 1.0.2b) introduced an "error state"
+
+
+ """
- found_advisories = list(map(Advisory.normalized, found_advisories))
- expected_advisories = list(map(Advisory.normalized, expected_advisories))
- assert sorted(found_advisories) == sorted(expected_advisories)
+ expected = AdvisoryData(
+ aliases=["CVE-2017-3737", "VC-OPENSSL-20171207-CVE-2017-3737"],
+ summary='OpenSSL 1.0.2 (starting from version 1.0.2b) introduced an "error state"',
+ affected_packages=[
+ AffectedPackage(
+ package=PackageURL(
+ type="openssl",
+ namespace=None,
+ name="openssl",
+ version=None,
+ qualifiers={},
+ subpath=None,
+ ),
+ affected_version_range=OpensslVersionRange(
+ constraints=(
+ VersionConstraint(
+ comparator="=", version=OpensslVersion(string="1.0.2b")
+ ),
+ VersionConstraint(
+ comparator="=", version=OpensslVersion(string="1.0.2c")
+ ),
+ )
+ ),
+ fixed_version=OpensslVersion(string="1.0.2n"),
+ )
+ ],
+ references=[
+ Reference(
+ reference_id="CVE-2017-3737",
+ url="",
+ severities=[],
+ ),
+ Reference(
+ reference_id="",
+ url="https://github.com/openssl/openssl/commit/898fb884b706aaeb283de4812340bb0bde8476dc",
+ severities=[],
+ ),
+ Reference(
+ reference_id="",
+ url="https://www.openssl.org/news/secadv/20171207.txt",
+ severities=[],
+ ),
+ ],
+ date_published=datetime.datetime(2017, 12, 7, 0, 0, tzinfo=datetime.timezone.utc),
+ )
+ issue_parsed = DET.fromstring(issue_string)
+ assert expected == to_advisory_data(issue_parsed)