diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 98148bf8e..19707af2c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,10 +2,16 @@ Release notes ============= +Version v31.1.1 +--------------- + +- We re-enabled support for the Apache HTTPD security advisories importer. + + Version v31.1.0 ---------------- -- We re-enabled support for the NPM vulnerabilities advisories importer. +- We re-enabled support for the NPM vulnerabilities advisories importer. - We re-enabled support for the Retiredotnet vulnerabilities advisories importer. - We are now handling purl fragments in package search. For example: you can now serch using queries in the UI like this : ``cherrypy@2.1.1``, @@ -30,7 +36,7 @@ Version v31.0.0 - We made bulk search faster by pre-computing `package_url` and `plain_package_url` in Package model. And provided two options in package bulk search ``purl_only`` option to get only vulnerable purls without any - extra details, ``plain_purl`` option to filter purls without qualifiers and + extra details, ``plain_purl`` option to filter purls without qualifiers and subpath and also return them without qualifiers and subpath. The names used are provisional and may be updated in a future release. diff --git a/requirements.txt b/requirements.txt index add89c95a..2abee0b65 100644 --- a/requirements.txt +++ b/requirements.txt @@ -107,7 +107,7 @@ toml==0.10.2 tomli==2.0.1 traitlets==5.1.1 typing_extensions==4.1.1 -univers==30.9.0 +univers==30.9.1 urllib3==1.26.9 wcwidth==0.2.5 websocket-client==0.59.0 @@ -120,4 +120,4 @@ drf-spectacular-sidecar==2022.10.1 drf-spectacular==0.24.2 coreapi==2.3.3 coreschema==0.0.4 -itypes==1.2.0 \ No newline at end of file +itypes==1.2.0 diff --git a/setup.cfg b/setup.cfg index 73fb4ebbd..bd8626710 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,7 +70,7 @@ install_requires = #essentials packageurl-python>=0.10.5rc1 - univers>=30.9.0 + univers>=30.9.1 license-expression>=21.6.14 # file and data formats diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py index 3594cbd4d..2831c1060 100644 --- a/vulnerabilities/importers/__init__.py +++ b/vulnerabilities/importers/__init__.py @@ -8,6 +8,7 @@ # from vulnerabilities.importers import alpine_linux +from vulnerabilities.importers import apache_httpd from vulnerabilities.importers import archlinux from vulnerabilities.importers import debian from vulnerabilities.importers import debian_oval @@ -41,6 +42,7 @@ debian_oval.DebianOvalImporter, npm.NpmImporter, retiredotnet.RetireDotnetImporter, + apache_httpd.ApacheHTTPDImporter, ] IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY} diff --git a/vulnerabilities/importers/apache_httpd.py b/vulnerabilities/importers/apache_httpd.py index 56a142e30..cadcd6800 100644 --- a/vulnerabilities/importers/apache_httpd.py +++ b/vulnerabilities/importers/apache_httpd.py @@ -13,43 +13,32 @@ import requests from bs4 import BeautifulSoup from packageurl import PackageURL -from univers.version_range import VersionRange +from univers.version_constraint import VersionConstraint +from univers.version_range import ApacheVersionRange from univers.versions import SemverVersion 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.package_managers import GitHubTagsAPI from vulnerabilities.severity_systems import APACHE_HTTPD -from vulnerabilities.utils import nearest_patched_package class ApacheHTTPDImporter(Importer): base_url = "https://httpd.apache.org/security/json/" + spdx_license_expression = "Apache-2.0" + license_url = "https://www.apache.org/licenses/LICENSE-2.0" - def set_api(self): - self.version_api = GitHubTagsAPI() - asyncio.run(self.version_api.load_api(["apache/httpd"])) - self.version_api.cache["apache/httpd"] = set( - filter( - lambda version: version.value not in ignore_tags, - self.version_api.cache["apache/httpd"], - ) - ) - - def updated_advisories(self): + def advisory_data(self): links = fetch_links(self.base_url) - self.set_api() - advisories = [] for link in links: data = requests.get(link).json() - advisories.append(self.to_advisory(data)) - return self.batch_advisories(advisories) + yield self.to_advisory(data) def to_advisory(self, data): - cve = data["CVE_data_meta"]["ID"] + alias = data["CVE_data_meta"]["ID"] descriptions = data["description"]["description_data"] description = None for desc in descriptions: @@ -66,12 +55,13 @@ def to_advisory(self, data): VulnerabilitySeverity( system=APACHE_HTTPD, value=value, + scoring_elements="", ) ) break reference = Reference( - reference_id=cve, - url=urllib.parse.urljoin(self.base_url, f"{cve}.json"), + reference_id=alias, + url=urllib.parse.urljoin(self.base_url, f"{alias}.json"), severities=severities, ) @@ -81,56 +71,68 @@ def to_advisory(self, data): for version_data in products["version"]["version_data"]: versions_data.append(version_data) - fixed_version_ranges, affected_version_ranges = self.to_version_ranges(versions_data) + fixed_versions = [] + for timeline_object in data.get("timeline") or []: + timeline_value = timeline_object["value"] + if "release" in timeline_value: + split_timeline_value = timeline_value.split(" ") + if "never" in timeline_value: + continue + if "release" in split_timeline_value[-1]: + fixed_versions.append(split_timeline_value[0]) + if "release" in split_timeline_value[0]: + fixed_versions.append(split_timeline_value[-1]) affected_packages = [] - fixed_packages = [] - - for version_range in fixed_version_ranges: - fixed_packages.extend( - [ - PackageURL(type="apache", name="httpd", version=version) - for version in self.version_api.get("apache/httpd").valid_versions - if SemverVersion(version) in version_range - ] - ) - - for version_range in affected_version_ranges: - affected_packages.extend( - [ - PackageURL(type="apache", name="httpd", version=version) - for version in self.version_api.get("apache/httpd").valid_versions - if SemverVersion(version) in version_range - ] + affected_version_range = self.to_version_ranges(versions_data, fixed_versions) + if affected_version_range: + affected_packages.append( + AffectedPackage( + package=PackageURL( + type="apache", + name="httpd", + ), + affected_version_range=affected_version_range, + ) ) return AdvisoryData( - vulnerability_id=cve, + aliases=[alias], summary=description, - affected_packages=nearest_patched_package(affected_packages, fixed_packages), + affected_packages=affected_packages, references=[reference], ) - def to_version_ranges(self, versions_data): - fixed_version_ranges = [] - affected_version_ranges = [] + def to_version_ranges(self, versions_data, fixed_versions): + constraints = [] for version_data in versions_data: version_value = version_data["version_value"] range_expression = version_data["version_affected"] - if range_expression == "<": - fixed_version_ranges.append( - VersionRange.from_scheme_version_spec_string( - "semver", ">={}".format(version_value) - ) - ) - elif range_expression == "=" or range_expression == "?=": - affected_version_ranges.append( - VersionRange.from_scheme_version_spec_string( - "semver", "{}".format(version_value) - ) + if range_expression not in {"<=", ">=", "?=", "!<", "="}: + raise ValueError(f"unknown comparator found! {range_expression}") + comparator_by_range_expression = { + ">=": ">=", + "!<": ">=", + "<=": "<=", + "=": "=", + } + comparator = comparator_by_range_expression.get(range_expression) + if comparator: + constraints.append( + VersionConstraint(comparator=comparator, version=SemverVersion(version_value)) ) - return (fixed_version_ranges, affected_version_ranges) + for fixed_version in fixed_versions: + # The VersionConstraint method `invert()` inverts the fixed_version's comparator, + # enabling inclusion of multiple fixed versions with the `affected_version_range` values. + constraints.append( + VersionConstraint( + comparator="=", + version=SemverVersion(fixed_version), + ).invert() + ) + + return ApacheVersionRange(constraints=constraints) def fetch_links(url): diff --git a/vulnerabilities/improvers/default.py b/vulnerabilities/improvers/default.py index 42522f40b..23dea75aa 100644 --- a/vulnerabilities/improvers/default.py +++ b/vulnerabilities/improvers/default.py @@ -39,21 +39,22 @@ def interesting_advisories(self) -> QuerySet: return Advisory.objects.all() def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]: - if not advisory_data: return [] if advisory_data.affected_packages: for affected_package in advisory_data.affected_packages: - affected_purls, fixed_purl = get_exact_purls(affected_package) - yield Inference( - aliases=advisory_data.aliases, - confidence=MAX_CONFIDENCE, - summary=advisory_data.summary, - affected_purls=affected_purls, - fixed_purl=fixed_purl, - references=advisory_data.references, - ) + # To deal with multiple fixed versions in a single affected package + affected_purls, fixed_purls = get_exact_purls(affected_package) + for fixed_purl in fixed_purls: + yield Inference( + aliases=advisory_data.aliases, + confidence=MAX_CONFIDENCE, + summary=advisory_data.summary, + affected_purls=affected_purls, + fixed_purl=fixed_purl, + references=advisory_data.references, + ) else: yield Inference.from_advisory_data( @@ -78,7 +79,7 @@ def get_exact_purls(affected_package: AffectedPackage) -> Tuple[List[PackageURL] >>> got = get_exact_purls(affected_package) >>> expected = ( ... [PackageURL(type='turtle', namespace=None, name='green', version='2.0.0', qualifiers={}, subpath=None)], - ... PackageURL(type='turtle', namespace=None, name='green', version='5.0.0', qualifiers={}, subpath=None) + ... [PackageURL(type='turtle', namespace=None, name='green', version='5.0.0', qualifiers={}, subpath=None)] ... ) >>> assert expected == got """ @@ -89,16 +90,25 @@ def get_exact_purls(affected_package: AffectedPackage) -> Tuple[List[PackageURL] # TODO: Revisit after https://github.com/nexB/univers/issues/33 try: affected_purls = [] + fixed_versions = [] if vr: range_versions = [c.version for c in vr.constraints if c] + # Any version that's not affected by a vulnerability is considered + # fixed. + fixed_versions = [c.version for c in vr.constraints if c and c.comparator == "!="] resolved_versions = [v for v in range_versions if v and v in vr] for version in resolved_versions: affected_purl = evolve_purl(purl=affected_package.package, version=str(version)) affected_purls.append(affected_purl) - fixed_purl = affected_package.get_fixed_purl() if affected_package.fixed_version else None + if affected_package.fixed_version: + fixed_versions.append(affected_package.fixed_version) - return affected_purls, fixed_purl + fixed_purls = [ + evolve_purl(purl=affected_package.package, version=str(version)) + for version in fixed_versions + ] + return affected_purls, fixed_purls except Exception as e: logger.error(f"Failed to get exact purls for {affected_package} {e}") - return [], None + return [], [] diff --git a/vulnerabilities/tests/conftest.py b/vulnerabilities/tests/conftest.py index 472693f7a..945af0ea6 100644 --- a/vulnerabilities/tests/conftest.py +++ b/vulnerabilities/tests/conftest.py @@ -25,7 +25,6 @@ def no_rmtree(monkeypatch): # Step 2: Run test for importer only if it is activated (pytestmark = pytest.mark.skipif(...)) # Step 3: Migrate all the tests collect_ignore = [ - "test_apache_httpd.py", "test_apache_kafka.py", "test_apache_tomcat.py", "test_api.py", diff --git a/vulnerabilities/tests/test_apache_httpd.py b/vulnerabilities/tests/test_apache_httpd.py index e206a88a2..9ff6bd5b6 100644 --- a/vulnerabilities/tests/test_apache_httpd.py +++ b/vulnerabilities/tests/test_apache_httpd.py @@ -9,104 +9,110 @@ import json import os -from unittest import TestCase -from packageurl import PackageURL -from univers.version_range import VersionRange +import pytest +from univers.version_constraint import VersionConstraint +from univers.version_range import ApacheVersionRange +from univers.versions import SemverVersion -from vulnerabilities import severity_systems -from vulnerabilities.importer import AdvisoryData -from vulnerabilities.importer import Reference -from vulnerabilities.importer import VulnerabilitySeverity from vulnerabilities.importers.apache_httpd import ApacheHTTPDImporter -from vulnerabilities.package_managers import GitHubTagsAPI -from vulnerabilities.package_managers import PackageVersion -from vulnerabilities.utils import AffectedPackage +from vulnerabilities.tests import util_tests BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -TEST_DATA = os.path.join(BASE_DIR, "test_data", "apache_httpd", "CVE-1999-1199.json") - - -class TestApacheHTTPDImporter(TestCase): - @classmethod - def setUpClass(cls): - data_source_cfg = {"etags": {}} - cls.data_src = ApacheHTTPDImporter(1, config=data_source_cfg) - known_versions = [PackageVersion("1.3.2"), PackageVersion("1.3.1"), PackageVersion("1.3.0")] - cls.data_src.version_api = GitHubTagsAPI(cache={"apache/httpd": known_versions}) - with open(TEST_DATA) as f: - cls.data = json.load(f) - - def test_to_version_ranges(self): - data = [ - { - "version_affected": "?=", - "version_value": "1.3.0", - }, - { - "version_affected": "=", - "version_value": "1.3.1", - }, - { - "version_affected": "<", - "version_value": "1.3.2", - }, - ] - fixed_version_ranges, affected_version_ranges = self.data_src.to_version_ranges(data) - - # Check fixed packages - assert [ - VersionRange.from_scheme_version_spec_string("semver", ">=1.3.2") - ] == fixed_version_ranges - - # Check vulnerable packages - assert [ - VersionRange.from_scheme_version_spec_string("semver", "==1.3.0"), - VersionRange.from_scheme_version_spec_string("semver", "==1.3.1"), - ] == affected_version_ranges - - def test_to_advisory(self): - expected_advisories = [ - AdvisoryData( - summary="A serious problem exists when a client sends a large number of " - "headers with the same header name. Apache uses up memory faster than the " - "amount of memory required to simply store the received data itself. That " - "is, memory use increases faster and faster as more headers are received, " - "rather than increasing at a constant rate. This makes a denial of service " - "attack based on this method more effective than methods which cause Apache" - " to use memory at a constant rate, since the attacker has to send less data.", - affected_packages=[ - AffectedPackage( - vulnerable_package=PackageURL( - type="apache", - name="httpd", - version="1.3.0", - ), - ), - AffectedPackage( - vulnerable_package=PackageURL( - type="apache", - name="httpd", - version="1.3.1", - ), - ), - ], - references=[ - Reference( - url="https://httpd.apache.org/security/json/CVE-1999-1199.json", - severities=[ - VulnerabilitySeverity( - system=severity_systems.APACHE_HTTPD, - value="important", - ), - ], - reference_id="CVE-1999-1199", - ), - ], - vulnerability_id="CVE-1999-1199", +TEST_DATA = os.path.join(BASE_DIR, "test_data/apache_httpd") + + +def test_to_version_ranges(): + data = [ + { + "version_affected": "?=", + "version_value": "1.3.0", + }, + { + "version_affected": "=", + "version_value": "1.3.1", + }, + { + "version_affected": "<=", + "version_value": "2.3.4", + }, + ] + fixed_versions = ["1.3.2"] + affected_version_range = ApacheHTTPDImporter().to_version_ranges(data, fixed_versions) + + assert ( + ApacheVersionRange( + constraints=( + VersionConstraint(comparator="=", version=SemverVersion(string="1.3.1")), + VersionConstraint(comparator="<=", version=SemverVersion(string="2.3.4")), + VersionConstraint(comparator="!=", version=SemverVersion(string="1.3.2")), ) - ] - found_advisories = [self.data_src.to_advisory(self.data)] - found_advisories = list(map(AdvisoryData.normalized, found_advisories)) - expected_advisories = list(map(AdvisoryData.normalized, expected_advisories)) - assert sorted(found_advisories) == sorted(expected_advisories) + ) + == affected_version_range + ) + + +def unknown_comparator(): + data = [ + { + "version_affected": "?=", + "version_value": "1.3.0", + }, + { + "version_affected": "=", + "version_value": "1.3.1", + }, + { + "version_affected": "#=", + "version_value": "2.3.4", + }, + ] + fixed_versions = ["1.3.2"] + affected_version_range = ApacheHTTPDImporter().to_version_ranges(data, fixed_versions) + + +def test_unknown_comparator_exception(): + with pytest.raises(ValueError) as excinfo: + unknown_comparator() + + assert "unknown comparator found! #=" in str(excinfo.value) + + +def test_to_advisory_CVE_1999_1199(): + with open(os.path.join(TEST_DATA, "CVE-1999-1199.json")) as f: + data = json.load(f) + + advisories = ApacheHTTPDImporter().to_advisory(data) + result = advisories.to_dict() + expected_file = os.path.join(TEST_DATA, f"CVE-1999-1199-apache-httpd-expected.json") + util_tests.check_results_against_json(result, expected_file) + + +def test_to_advisory_CVE_2021_44224(): + with open(os.path.join(TEST_DATA, "CVE-2021-44224.json")) as f: + data = json.load(f) + + advisories = ApacheHTTPDImporter().to_advisory(data) + result = advisories.to_dict() + expected_file = os.path.join(TEST_DATA, f"CVE-2021-44224-apache-httpd-expected.json") + util_tests.check_results_against_json(result, expected_file) + + +def test_to_advisory_CVE_2017_9798(): + with open(os.path.join(TEST_DATA, "CVE-2017-9798.json")) as f: + data = json.load(f) + + advisories = ApacheHTTPDImporter().to_advisory(data) + result = advisories.to_dict() + expected_file = os.path.join(TEST_DATA, f"CVE-2017-9798-apache-httpd-expected.json") + util_tests.check_results_against_json(result, expected_file) + + +def test_to_advisory_CVE_2022_28614(): + with open(os.path.join(TEST_DATA, "CVE-2022-28614.json")) as f: + data = json.load(f) + + advisories = ApacheHTTPDImporter().to_advisory(data) + result = advisories.to_dict() + expected_file = os.path.join(TEST_DATA, f"CVE-2022-28614-apache-httpd-expected.json") + util_tests.check_results_against_json(result, expected_file) diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-1999-1199-apache-httpd-expected.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-1999-1199-apache-httpd-expected.json new file mode 100644 index 000000000..5e24e496c --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-1999-1199-apache-httpd-expected.json @@ -0,0 +1,34 @@ +{ + "aliases": [ + "CVE-1999-1199" + ], + "summary": "A serious problem exists when a client sends a large number of headers with the same header name. Apache uses up memory faster than the amount of memory required to simply store the received data itself. That is, memory use increases faster and faster as more headers are received, rather than increasing at a constant rate. This makes a denial of service attack based on this method more effective than methods which cause Apache to use memory at a constant rate, since the attacker has to send less data.", + "affected_packages": [ + { + "package": { + "type": "apache", + "namespace": null, + "name": "httpd", + "version": null, + "qualifiers": null, + "subpath": null + }, + "affected_version_range": "vers:apache/1.3.0|1.3.1|!=1.3.2", + "fixed_version": null + } + ], + "references": [ + { + "reference_id": "CVE-1999-1199", + "url": "https://httpd.apache.org/security/json/CVE-1999-1199.json", + "severities": [ + { + "system": "apache_httpd", + "value": "important", + "scoring_elements": "" + } + ] + } + ], + "date_published": null +} \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798-apache-httpd-expected.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798-apache-httpd-expected.json new file mode 100644 index 000000000..53bf3e31d --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798-apache-httpd-expected.json @@ -0,0 +1,34 @@ +{ + "aliases": [ + "CVE-2017-9798" + ], + "summary": "When an unrecognized HTTP Method is given in an directive in an .htaccess file, and that .htaccess file is processed by the corresponding request, the global methods table is corrupted in the current worker process, resulting in erratic behaviour. This behavior may be avoided by listing all unusual HTTP Methods in a global httpd.conf RegisterHttpMethod directive in httpd release 2.4.25 and later. To permit other .htaccess directives while denying the directive, see the AllowOverrideList directive. Source code patch (2.4) is at; CVE-2017-9798-patch-2.4.patch Source code patch (2.2) is at; CVE-2017-9798-patch-2.2.patch Note 2.2 is end-of-life, no further release with this fix is planned. Users are encouraged to migrate to 2.4.28 or later for this and other fixes.", + "affected_packages": [ + { + "package": { + "type": "apache", + "namespace": null, + "name": "httpd", + "version": null, + "qualifiers": null, + "subpath": null + }, + "affected_version_range": "vers:apache/2.2.0|2.2.2|2.2.3|2.2.4|2.2.5|2.2.6|2.2.8|2.2.9|2.2.10|2.2.11|2.2.12|2.2.13|2.2.14|2.2.15|2.2.16|2.2.17|2.2.18|2.2.19|2.2.20|2.2.21|2.2.22|2.2.23|2.2.24|2.2.25|2.2.26|2.2.27|2.2.29|2.2.31|2.2.32|2.2.34|2.4.1|2.4.2|2.4.3|2.4.4|2.4.6|2.4.7|2.4.9|2.4.10|2.4.12|2.4.16|2.4.17|2.4.18|2.4.20|2.4.23|2.4.25|2.4.26|2.4.27|!=2.4.28", + "fixed_version": null + } + ], + "references": [ + { + "reference_id": "CVE-2017-9798", + "url": "https://httpd.apache.org/security/json/CVE-2017-9798.json", + "severities": [ + { + "system": "apache_httpd", + "value": "low", + "scoring_elements": "" + } + ] + } + ], + "date_published": null +} \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798.json new file mode 100644 index 000000000..1191d8c4b --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2017-9798.json @@ -0,0 +1,333 @@ +{ + "data_type": "CVE", + "data_format": "MITRE", + "data_version": "4.0", + "generator": { + "engine": "xmltojsonmjc 1.0" + }, + "references": {}, + "timeline": [ + { + "time": "2017-07-12", + "lang": "eng", + "value": "reported" + }, + { + "time": "2017-09-18", + "lang": "eng", + "value": "public" + }, + { + "time": "2017-10-05", + "lang": "eng", + "value": "2.4.28 released" + }, + { + "time": "--", + "lang": "eng", + "value": "2.2.35-never released" + } + ], + "CNA_private": { + "owner": "httpd" + }, + "CVE_data_meta": { + "ASSIGNER": "security@apache.org", + "AKA": "", + "STATE": "PUBLIC", + "DATE_PUBLIC": "2017-09-18", + "ID": "CVE-2017-9798", + "TITLE": "Use-after-free when using with an unrecognized method in .htaccess (\"OptionsBleed\")" + }, + "source": { + "defect": [], + "advisory": "", + "discovery": "UNKNOWN" + }, + "problemtype": { + "problemtype_data": [ + { + "description": [ + { + "lang": "eng", + "value": "Use-after-free when using with an unrecognized method in .htaccess (\"OptionsBleed\")" + } + ] + } + ] + }, + "credit": [ + { + "lang": "eng", + "value": "We would like to thank Hanno Böck for reporting this issue." + } + ], + "description": { + "description_data": [ + { + "lang": "eng", + "value": "When an unrecognized HTTP Method is given in an directive in an .htaccess file, and that .htaccess file is processed by the corresponding request, the global methods table is corrupted in the current worker process, resulting in erratic behaviour. This behavior may be avoided by listing all unusual HTTP Methods in a global httpd.conf RegisterHttpMethod directive in httpd release 2.4.25 and later. To permit other .htaccess directives while denying the directive, see the AllowOverrideList directive. Source code patch (2.4) is at; CVE-2017-9798-patch-2.4.patch Source code patch (2.2) is at; CVE-2017-9798-patch-2.2.patch Note 2.2 is end-of-life, no further release with this fix is planned. Users are encouraged to migrate to 2.4.28 or later for this and other fixes." + } + ] + }, + "impact": [ + { + "other": "low" + } + ], + "affects": { + "vendor": { + "vendor_data": [ + { + "vendor_name": "Apache Software Foundation", + "product": { + "product_data": [ + { + "product_name": "Apache HTTP Server", + "version": { + "version_data": [ + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.27" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.26" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.25" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.23" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.20" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.18" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.17" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.16" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.12" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.10" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.9" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.7" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.6" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.4" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.3" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.2" + }, + { + "version_name": "2.4", + "version_affected": "=", + "version_value": "2.4.1" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.34" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.32" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.31" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.29" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.27" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.26" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.25" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.24" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.23" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.22" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.21" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.20" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.19" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.18" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.17" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.16" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.15" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.14" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.13" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.12" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.11" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.10" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.9" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.8" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.6" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.5" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.4" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.3" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.2" + }, + { + "version_name": "2.2", + "version_affected": "=", + "version_value": "2.2.0" + } + ] + } + } + ] + } + } + ] + } + } +} diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224-apache-httpd-expected.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224-apache-httpd-expected.json new file mode 100644 index 000000000..411e4dee3 --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224-apache-httpd-expected.json @@ -0,0 +1,34 @@ +{ + "aliases": [ + "CVE-2021-44224" + ], + "summary": "A crafted URI sent to httpd configured as a forward proxy (ProxyRequests on) can cause a crash (NULL pointer dereference) or, for configurations mixing forward and reverse proxy declarations, can allow for requests to be directed to a declared Unix Domain Socket endpoint (Server Side Request Forgery).\n\nThis issue affects Apache HTTP Server 2.4.7 up to 2.4.51 (included).", + "affected_packages": [ + { + "package": { + "type": "apache", + "namespace": null, + "name": "httpd", + "version": null, + "qualifiers": null, + "subpath": null + }, + "affected_version_range": "vers:apache/>=2.4.7|<=2.4.51|!=2.4.52", + "fixed_version": null + } + ], + "references": [ + { + "reference_id": "CVE-2021-44224", + "url": "https://httpd.apache.org/security/json/CVE-2021-44224.json", + "severities": [ + { + "system": "apache_httpd", + "value": "moderate", + "scoring_elements": "" + } + ] + } + ], + "date_published": null +} \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224.json new file mode 100644 index 000000000..456732fa7 --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2021-44224.json @@ -0,0 +1,106 @@ +{ + "CVE_data_meta": { + "ASSIGNER": "security@apache.org", + "ID": "CVE-2021-44224", + "STATE": "REVIEW", + "TITLE": "Possible NULL dereference or SSRF in forward proxy configurations in Apache HTTP Server 2.4.51 and earlier" + }, + "affects": { + "vendor": { + "vendor_data": [ + { + "product": { + "product_data": [ + { + "product_name": "Apache HTTP Server", + "version": { + "version_data": [ + { + "version_affected": ">=", + "version_name": "Apache HTTP Server 2.4", + "version_value": "2.4.7" + }, + { + "version_affected": "<=", + "version_name": "Apache HTTP Server 2.4", + "version_value": "2.4.51" + } + ] + } + } + ] + }, + "vendor_name": "Apache Software Foundation" + } + ] + } + }, + "credit": [ + { + "lang": "eng", + "value": "漂亮鼠" + }, + { + "lang": "eng", + "value": "TengMA(@Te3t123)" + } + ], + "data_format": "MITRE", + "data_type": "CVE", + "data_version": "4.0", + "description": { + "description_data": [ + { + "lang": "eng", + "value": "A crafted URI sent to httpd configured as a forward proxy (ProxyRequests on) can cause a crash (NULL pointer dereference) or, for configurations mixing forward and reverse proxy declarations, can allow for requests to be directed to a declared Unix Domain Socket endpoint (Server Side Request Forgery).\n\nThis issue affects Apache HTTP Server 2.4.7 up to 2.4.51 (included)." + } + ] + }, + "generator": { + "engine": "Vulnogram 0.0.9" + }, + "impact": [ + { + "other": "moderate" + } + ], + "problemtype": { + "problemtype_data": [ + { + "description": [ + { + "lang": "eng", + "value": "CWE-476 NULL Pointer Dereference" + } + ] + } + ] + }, + "references": { + "reference_data": [ + { + "refsource": "CONFIRM" + } + ] + }, + "source": { + "discovery": "UNKNOWN" + }, + "timeline": [ + { + "lang": "eng", + "time": "2021-11-18", + "value": "Reported to security team" + }, + { + "lang": "eng", + "time": "2021-12-14", + "value": "fixed by r1895955, r1896044 in 2.4.x" + }, + { + "lang": "eng", + "time": "2021-12-20", + "value": "2.4.52 released" + } + ] +} diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614-apache-httpd-expected.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614-apache-httpd-expected.json new file mode 100644 index 000000000..68e72b691 --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614-apache-httpd-expected.json @@ -0,0 +1,34 @@ +{ + "aliases": [ + "CVE-2022-28614" + ], + "summary": "The ap_rwrite() function in Apache HTTP Server 2.4.53 and earlier may read unintended memory if an attacker can cause the server to reflect very large input using ap_rwrite() or ap_rputs(), such as with mod_luas r:puts() function.\n\nModules compiled and distributed separately from Apache HTTP Server that use the \"ap_rputs\" function and may pass it a very large (INT_MAX or larger) string must be compiled against current headers to resolve the issue.", + "affected_packages": [ + { + "package": { + "type": "apache", + "namespace": null, + "name": "httpd", + "version": null, + "qualifiers": null, + "subpath": null + }, + "affected_version_range": "vers:apache/<=2.4.53|!=2.4.54", + "fixed_version": null + } + ], + "references": [ + { + "reference_id": "CVE-2022-28614", + "url": "https://httpd.apache.org/security/json/CVE-2022-28614.json", + "severities": [ + { + "system": "apache_httpd", + "value": "low", + "scoring_elements": "" + } + ] + } + ], + "date_published": null +} \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614.json b/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614.json new file mode 100644 index 000000000..8bb37379c --- /dev/null +++ b/vulnerabilities/tests/test_data/apache_httpd/CVE-2022-28614.json @@ -0,0 +1,122 @@ +{ + "data_type": "CVE", + "data_format": "MITRE", + "data_version": "4.0", + "generator": { + "engine": "Vulnogram 0.0.9" + }, + "CVE_data_meta": { + "ID": "CVE-2022-28614", + "ASSIGNER": "security@apache.org", + "DATE_PUBLIC": "", + "TITLE": "read beyond bounds via ap_rwrite() ", + "AKA": "", + "STATE": "PUBLIC" + }, + "source": { + "defect": [], + "advisory": "", + "discovery": "UNKNOWN" + }, + "affects": { + "vendor": { + "vendor_data": [ + { + "vendor_name": "Apache Software Foundation", + "product": { + "product_data": [ + { + "product_name": "Apache HTTP Server", + "version": { + "version_data": [ + { + "version_name": "", + "version_affected": "<=", + "version_value": "2.4.53", + "platform": "" + } + ] + } + } + ] + } + } + ] + } + }, + "problemtype": { + "problemtype_data": [ + { + "description": [ + { + "lang": "eng", + "value": "CWE-190 Integer Overflow or Wraparound" + } + ] + }, + { + "description": [ + { + "lang": "eng", + "value": "CWE-200 Exposure of Sensitive Information to an Unauthorized Actor" + } + ] + } + ] + }, + "description": { + "description_data": [ + { + "value": "The ap_rwrite() function in Apache HTTP Server 2.4.53 and earlier may read unintended memory if an attacker can cause the server to reflect very large input using ap_rwrite() or ap_rputs(), such as with mod_luas r:puts() function.\n\nModules compiled and distributed separately from Apache HTTP Server that use the \"ap_rputs\" function and may pass it a very large (INT_MAX or larger) string must be compiled against current headers to resolve the issue.", + "lang": "eng" + } + ] + }, + "references": { + "reference_data": [ + { + "refsource": "CONFIRM", + "url": "https://httpd.apache.org/security/vulnerabilities_24.html", + "name": "" + } + ] + }, + "configuration": [], + "impact": [ + { + "other": "low" + } + ], + "exploit": [], + "work_around": [], + "solution": [], + "credit": [ + { + "lang": "eng", + "value": "The Apache HTTP Server project would like to thank Ronald Crane (Zippenhop LLC) for reporting this issue" + } + ], + "CNA_private": { + "owner": "httpd", + "publish": { + "ym": "", + "year": "", + "month": "" + }, + "share_with_CVE": true, + "CVE_table_description": [], + "CVE_list": [], + "internal_comments": "", + "todo": [], + "emailed": "yes", + "userslist": "dev@httpd.apache.org", + "email": "" + }, + "timeline": [ + { + "time": "2022-06-08", + "lang": "eng", + "value": "released in 2.4.54" + } + ] +}