From 7bf7bc5570673f21878651ba0886d7348a3d28e6 Mon Sep 17 00:00:00 2001 From: Rishi Garg Date: Sat, 8 Mar 2025 17:17:15 +0530 Subject: [PATCH 1/3] Adds Samba Advisory Signed-off-by: Rishi Garg --- vulnerabilities/pipelines/samba_importer.py | 335 ++++++++++++++++++ .../pipelines/test_samba_importer_pipeline.py | 206 +++++++++++ .../tests/test_data/samba/CVE-2023-4154.html | 122 +++++++ .../test_data/samba/CVE-2023-4154.html.txt | 103 ++++++ .../test_data/samba/security_advisories.html | 53 +++ 5 files changed, 819 insertions(+) create mode 100644 vulnerabilities/pipelines/samba_importer.py create mode 100644 vulnerabilities/tests/pipelines/test_samba_importer_pipeline.py create mode 100644 vulnerabilities/tests/test_data/samba/CVE-2023-4154.html create mode 100644 vulnerabilities/tests/test_data/samba/CVE-2023-4154.html.txt create mode 100644 vulnerabilities/tests/test_data/samba/security_advisories.html diff --git a/vulnerabilities/pipelines/samba_importer.py b/vulnerabilities/pipelines/samba_importer.py new file mode 100644 index 000000000..bd2dd4443 --- /dev/null +++ b/vulnerabilities/pipelines/samba_importer.py @@ -0,0 +1,335 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +import html +import logging +import re +from datetime import datetime +from traceback import format_exc as traceback_format_exc +from typing import Dict +from typing import Iterable +from typing import List +from typing import Optional + +import pytz +import requests +from bs4 import BeautifulSoup +from dateutil import parser as dateparser +from packageurl import PackageURL + +from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import AffectedPackage +from vulnerabilities.importer import Reference +from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipeline +from vulnerabilities.utils import build_description +from vulnerabilities.utils import get_cwe_id + + +class SambaImporterPipeline(VulnerableCodeBaseImporterPipeline): + pipeline_id = "samba_importer" + spdx_license_expression = "GPL-3.0-only" + license_url = "https://www.samba.org/samba/docs/GPL.txt" + url = "https://www.samba.org/samba/history/security.html" + importer_name = "Samba Importer" + + @classmethod + def steps(cls): + return (cls.fetch, cls.collect_and_store_advisories, cls.import_new_advisories) + + def fetch(self): + self.log(f"Fetching `{self.url}`") + try: + response = requests.get(self.url) + response.raise_for_status() + self.advisory_data = response.text + self.advisory_details_cache = {} + except requests.exceptions.HTTPError as http_err: + self.log( + f"Failed to fetch Samba security data: {self.url} with error {http_err!r}:\n{traceback_format_exc()}", + level=logging.ERROR, + ) + raise + + def advisories_count(self): + if not hasattr(self, "advisory_data"): + return 0 + + soup = BeautifulSoup(self.advisory_data, "html.parser") + security_table = soup.find("table", {"class": "security_table"}) + return 0 if not security_table else len(security_table.find_all("tr")) - 1 + + def collect_advisories(self): + soup = BeautifulSoup(self.advisory_data, "html.parser") + security_table = soup.find("table", {"class": "security_table"}) + + if not security_table: + self.log("Security table not found in HTML content", level=logging.ERROR) + return + + rows = security_table.find_all("tr")[1:] + for row in rows: + try: + advisory = self.parse_advisory_row(row) + if advisory: + yield advisory + except Exception as e: + self.log( + f"Error parsing advisory row: {e!r}:\n{traceback_format_exc()}", + level=logging.ERROR, + ) + + def get_advisory_details(self, cve_id): + if cve_id in self.advisory_details_cache: + return self.advisory_details_cache[cve_id] + + detail_url = f"https://www.samba.org/samba/security/{cve_id}.html" + + try: + response = requests.get(detail_url) + response.raise_for_status() + + soup = BeautifulSoup(response.text, "html.parser") + pre_tag = soup.find("pre") + if not pre_tag: + self.log(f"No detailed information found for {cve_id}", level=logging.WARNING) + return {} + + announcement_text = html.unescape(pre_tag.get_text()) + details = parse_announcement_text(announcement_text) + details["url"] = detail_url + + self.advisory_details_cache[cve_id] = details + return details + except requests.exceptions.RequestException as e: + self.log(f"Error fetching advisory details for {cve_id}: {e}", level=logging.WARNING) + return {} + except Exception as e: + self.log(f"Error processing advisory details for {cve_id}: {e!r}", level=logging.ERROR) + return {} + + def parse_advisory_row(self, row): + cells = row.find_all("td") + if len(cells) != 6: + self.log( + f"Expected 6 cells in security table row, got {len(cells)}", level=logging.WARNING + ) + return None + + date_issued = cells[0].get_text().strip() + patch_links = [] + + for link in cells[1].find_all("a"): + href = link.get("href", "") + if href: + if not href.startswith(("http://", "https://")): + href = f"https://www.samba.org{href}" + patch_links.append(href) + + issue_desc = cells[2].get_text().strip() + affected_releases = cells[3].get_text().strip() + + cve_ids = [] + for link in cells[4].find_all("a"): + cve_id = link.get_text().strip() + if re.match(r"CVE-\d{4}-\d{4,}", cve_id): + cve_ids.append(cve_id) + + date_published = None + try: + if date_issued: + date_obj = dateparser.parse(date_issued) + if date_obj: + date_published = date_obj.replace(tzinfo=pytz.UTC) + except Exception as e: + self.log(f"Error parsing date {date_issued}: {e!r}", level=logging.WARNING) + + fixed_versions = self.extract_versions_from_patch_links(patch_links) + affected_packages = [] + + if fixed_versions: + base_purl = PackageURL(type="generic", name="samba") + for version in fixed_versions: + affected_packages.append(AffectedPackage(package=base_purl, fixed_version=version)) + elif affected_releases and affected_releases != "Please refer to the advisories.": + base_purl = PackageURL(type="generic", name="samba") + version_match = re.search(r"(?:Samba|samba)\s+(\d+\.\d+\.\d+)", affected_releases) + + if version_match: + affected_packages.append( + AffectedPackage( + package=base_purl, fixed_version=f"{version_match.group(1)}-fixed" + ) + ) + else: + affected_packages.append( + AffectedPackage(package=base_purl, fixed_version="unknown") + ) + + if not cve_ids and issue_desc: + synthetic_id = ( + f"SAMBA-VULN-{date_issued.replace(' ', '-') if date_issued else 'UNKNOWN'}" + ) + cve_ids.append(synthetic_id) + + detailed_summary = issue_desc + + for cve_id in cve_ids: + details = self.get_advisory_details(cve_id) + if not details: + continue + + if details.get("summary"): + detailed_summary = details["summary"] + + if details.get("description"): + detailed_summary = f"{detailed_summary}\n\n{details['description']}" + + if details.get("affected_versions"): + versions_details = details.get("affected_versions") + fixed_vers = details.get("fixed_versions", []) + + for pkg in self.extract_affected_packages_from_detail(versions_details, fixed_vers): + affected_packages.append(pkg) + + if details.get("mitigation"): + detailed_summary = f"{detailed_summary}\n\nMitigation: {details['mitigation']}" + + references = [] + for link in cells[5].find_all("a"): + announcement_text = link.get_text().strip() + announcement_url = link.get("href") + if announcement_url: + if not announcement_url.startswith(("http://", "https://")): + announcement_url = f"https://www.samba.org{announcement_url}" + + reference_id = None + for cve_id in cve_ids: + if cve_id in announcement_url: + reference_id = cve_id + break + + if not reference_id: + reference_id = announcement_text + + references.append(Reference(url=announcement_url, reference_id=reference_id)) + + for patch_url in patch_links: + patch_filename = patch_url.split("/")[-1] + references.append(Reference(url=patch_url, reference_id=f"Patch: {patch_filename}")) + + return AdvisoryData( + aliases=cve_ids, + summary=build_description( + summary=detailed_summary, description=f"Affected versions: {affected_releases}" + ), + references=references, + affected_packages=affected_packages, + date_published=date_published, + url="https://www.samba.org/samba/history/security.html", + ) + + def extract_affected_packages_from_detail(self, affected_versions, fixed_versions=None): + affected_packages = [] + fixed_versions = fixed_versions or [] + base_purl = PackageURL(type="generic", name="samba") + + if fixed_versions: + for version in fixed_versions: + affected_packages.append(AffectedPackage(package=base_purl, fixed_version=version)) + elif affected_versions: + version_match = re.search(r"(?:Samba|samba)\s+(\d+\.\d+\.\d+)", affected_versions) + if version_match: + affected_packages.append( + AffectedPackage( + package=base_purl, fixed_version=f"{version_match.group(1)}-fixed" + ) + ) + else: + affected_packages.append( + AffectedPackage(package=base_purl, fixed_version="unknown") + ) + + return affected_packages + + def extract_versions_from_patch_links(self, patch_links): + versions = [] + for link in patch_links: + match = re.search(r"samba-(\d+\.\d+\.\d+(?:\.\d+)?)", link) + if match: + version = match.group(1) + if version not in versions: + versions.append(version) + return versions + + +def extract_cwe_ids(issue_desc): + cwe_ids = [] + for cwe_match in re.findall(r"CWE-(\d+)", issue_desc): + try: + cwe_ids.append(int(cwe_match)) + except ValueError: + pass + return cwe_ids + + +def parse_announcement_text(text): + result = { + "subject": None, + "cve_id": None, + "affected_versions": None, + "summary": None, + "description": None, + "patches": None, + "mitigation": None, + "credits": None, + "fixed_versions": [], + } + + cve_match = re.search(r"CVE ID#:\s*(CVE-\d+-\d+)", text, re.IGNORECASE) + if cve_match: + result["cve_id"] = cve_match.group(1) + + subject_match = re.search(r"== Subject:\s*(.*?)(?=\n==\nCVE|\n==\n==)", text, re.DOTALL) + if subject_match: + subject = subject_match.group(1).strip() + subject = re.sub(r"\n==\s*", " ", subject) + subject = re.sub(r"\s+", " ", subject) + result["subject"] = subject + + versions_match = re.search(r"Versions:\s*(.*?)(?=\n\n|\n==|\n[A-Za-z]+:)", text, re.DOTALL) + if versions_match: + result["affected_versions"] = versions_match.group(1).strip() + + summary_match = re.search(r"Summary:\s*(.*?)(?=\n\n|\n==|\n[A-Za-z]+:)", text, re.DOTALL) + if summary_match: + summary = summary_match.group(1).strip() + summary = re.sub(r"\n==\s*", " ", summary) + summary = re.sub(r"\s*==\s*", " ", summary) + result["summary"] = summary + + sections = re.split(r"={2,}\n([A-Za-z ]+)\n={2,}", text)[1:] + + for i in range(0, len(sections), 2): + if i + 1 < len(sections): + section_name = sections[i].strip().lower() + section_content = sections[i + 1].strip() + + if section_name == "description": + result["description"] = section_content + elif section_name == "patch availability": + result["patches"] = section_content + fixed_versions = re.findall(r"Samba\s+(\d+\.\d+\.\d+(?:\.\d+)?)", section_content) + if fixed_versions: + result["fixed_versions"] = fixed_versions + elif section_name == "workaround and mitigating factors": + result["mitigation"] = section_content + elif section_name == "credits": + result["credits"] = section_content + + return result diff --git a/vulnerabilities/tests/pipelines/test_samba_importer_pipeline.py b/vulnerabilities/tests/pipelines/test_samba_importer_pipeline.py new file mode 100644 index 000000000..27accf3f7 --- /dev/null +++ b/vulnerabilities/tests/pipelines/test_samba_importer_pipeline.py @@ -0,0 +1,206 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +import os +from pathlib import Path +from unittest import mock + +import pytest +from bs4 import BeautifulSoup +from packageurl import PackageURL + +from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import AffectedPackage +from vulnerabilities.importer import Reference +from vulnerabilities.pipelines.samba_importer import SambaImporterPipeline +from vulnerabilities.pipelines.samba_importer import parse_announcement_text +from vulnerabilities.tests import util_tests + +TEST_DATA = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "test_data", "samba" +) + + +def test_parse_announcement_text(): + with open(os.path.join(TEST_DATA, "CVE-2023-4154.html.txt")) as f: + announcement_text = f.read() + + result = parse_announcement_text(announcement_text) + + assert result["cve_id"] is not None + assert "CVE-2023-4154" in result["cve_id"] + assert result["subject"] is not None and "password exposure" in result["subject"].lower() + assert ( + result["affected_versions"] is not None and "samba" in result["affected_versions"].lower() + ) + + +def test_extract_versions_from_patch_links(): + importer = SambaImporterPipeline() + + patch_links = [ + "https://www.samba.org/samba/ftp/patches/security/samba-4.19.1-security-2023-10-10.patch", + "https://www.samba.org/samba/ftp/patches/security/samba-4.18.8-security-2023-10-10.patch", + "https://www.samba.org/samba/ftp/patches/security/samba-4.17.12-security-2023-10-10.patch", + ] + + extracted_versions = importer.extract_versions_from_patch_links(patch_links) + + assert len(extracted_versions) == 3 + assert all(isinstance(v, str) for v in extracted_versions) + assert all(v.count(".") >= 2 for v in extracted_versions) + + +def test_extract_affected_packages_from_detail(): + importer = SambaImporterPipeline() + importer.log = lambda msg, level=None: None + + fixed_versions = ["4.19.1", "4.18.8", "4.17.12"] + affected_versions = "All versions since Samba 4.0.0" + + packages = importer.extract_affected_packages_from_detail(affected_versions, fixed_versions) + + assert len(packages) == 3 + assert all(pkg.package.type == "generic" and pkg.package.name == "samba" for pkg in packages) + assert all(pkg.fixed_version in fixed_versions for pkg in packages) + + packages = importer.extract_affected_packages_from_detail("Samba 4.0.0", []) + + assert len(packages) == 1 + assert packages[0].package.type == "generic" + assert packages[0].package.name == "samba" + + +@mock.patch("requests.get") +def test_get_advisory_details(mock_get): + mock_response = mock.Mock() + mock_response.raise_for_status.return_value = None + + with open(os.path.join(TEST_DATA, "CVE-2023-4154.html")) as f: + mock_response.text = f.read() + + mock_get.return_value = mock_response + + importer = SambaImporterPipeline() + importer.log = lambda msg, level=None: None + importer.advisory_details_cache = {} + + details = importer.get_advisory_details("CVE-2023-4154") + + assert "cve_id" in details + assert "CVE-2023-4154" in details["cve_id"] + assert "subject" in details + assert "affected_versions" in details + assert "url" in details + + mock_get.reset_mock() + importer.get_advisory_details("CVE-2023-4154") + mock_get.assert_not_called() + + +@mock.patch("requests.get") +def test_parse_advisory_row(mock_get): + mock_response = mock.Mock() + mock_response.raise_for_status.return_value = None + + with open(os.path.join(TEST_DATA, "CVE-2023-4154.html")) as f: + mock_response.text = f.read() + + mock_get.return_value = mock_response + + row_html = """ + + October 10, 2023 + + 4.19.1 + 4.18.8 + 4.17.12 + + Password exposure to privileged users and RODCs + All versions since Samba 4.0.0 + CVE-2023-4154 + Announcement + + """ + + soup = BeautifulSoup(row_html, "html.parser") + row = soup.find("tr") + + importer = SambaImporterPipeline() + importer.log = lambda msg, level=None: None + importer.advisory_details_cache = {} + + advisory = importer.parse_advisory_row(row) + + assert advisory is not None + assert "CVE-2023-4154" in advisory.aliases + assert len(advisory.affected_packages) > 0 + assert len(advisory.references) >= 3 + assert any(ref.reference_id == "CVE-2023-4154" for ref in advisory.references) + assert any("Patch:" in ref.reference_id for ref in advisory.references) + + +@mock.patch("requests.get") +def test_fetch(mock_get): + mock_response = mock.Mock() + mock_response.raise_for_status.return_value = None + + with open(os.path.join(TEST_DATA, "security_advisories.html")) as f: + mock_response.text = f.read() + + mock_get.return_value = mock_response + + importer = SambaImporterPipeline() + importer.log = lambda msg, level=None: None + + importer.fetch() + + mock_get.assert_called_once_with("https://www.samba.org/samba/history/security.html") + assert hasattr(importer, "advisory_data") + assert hasattr(importer, "advisory_details_cache") + + +class MockResponse: + def __init__(self, text, url): + self.text = text + self.url = url + + def raise_for_status(self): + return None + + +@mock.patch("requests.get") +def test_full_pipeline_execution(mock_get): + def mock_get_response(url): + if url == "https://www.samba.org/samba/history/security.html": + with open(os.path.join(TEST_DATA, "security_advisories.html")) as f: + return MockResponse(f.read(), url) + elif "CVE-2023-4154" in url: + with open(os.path.join(TEST_DATA, "CVE-2023-4154.html")) as f: + return MockResponse(f.read(), url) + else: + with open(os.path.join(TEST_DATA, "CVE-2023-4154.html")) as f: + return MockResponse(f.read(), url) + + mock_get.side_effect = mock_get_response + + importer = SambaImporterPipeline() + importer.log = lambda msg, level=None: None + + importer.fetch() + + count = importer.advisories_count() + assert count > 0 + + advisories = list(importer.collect_advisories()) + assert len(advisories) > 0 + + assert all(len(advisory.aliases) > 0 for advisory in advisories) + assert all(advisory.affected_packages for advisory in advisories) + assert all(advisory.references for advisory in advisories) diff --git a/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html b/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html new file mode 100644 index 000000000..fb14b0ee6 --- /dev/null +++ b/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html @@ -0,0 +1,122 @@ + + + + +Samba - Security Announcement Archive + + + + +

CVE-2023-4154.html:

+ +

+

+===========================================================
+== Subject:     Samba AD DC password exposure to privileged
+==              users and RODCs
+==
+== CVE ID#:     CVE-2023-4154
+==
+== Versions:    All versions since Samba 4.0.0
+==
+== Summary:     An RODC and a user with the GET_CHANGES
+==              right can view all attributes, including
+==              secrets and passwords.
+==
+==              Additionally, the access check fails open
+==              on error conditions.
+===========================================================
+
+===========
+Description
+===========
+
+In normal operation, passwords and (most) secrets are never disclosed
+over LDAP in Active Directory.
+
+However, due to a design flaw in Samba's implementation of the DirSync
+control, Active Directory accounts authorized to do some replication,
+but not to replicate sensitive attributes, can instead replicate
+critical domain passwords and secrets.
+
+In a default installation, this means that RODC DC accounts (which
+should only be permitted to replicate some passwords) can instead
+obtain all domain secrets, including the core AD secret: the krbtgt
+password.
+
+RODCs are given this permission as part of their installation for DRS
+replication.  This vulnerability removes the RODC / DC distinction.
+
+Secondly, and just as problematically, the access check for this
+functionality did not account for error conditions - errors like
+out of memory were regarded as success.  This is sometimes described
+as "fail open".  In these error conditions, some of which (eg out of
+memory) may be influenced by a low-privileged attacker, access to the
+secret attributes could be obtained!
+
+
+==================
+Patch Availability
+==================
+
+Patches addressing both these issues have been posted to:
+
+    https://www.samba.org/samba/security/
+
+Additionally, Samba 4.19.1, 4.18.8 and 4.17.12 have been issued
+as security releases to correct the defect.  Samba administrators are
+advised to upgrade to these releases or apply the patch as soon
+as possible.
+
+==================
+CVSSv3 calculation
+==================
+
+For password disclosure to RODCs and other privileged accounts:
+CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H (7.2)
+
+For the fail open on the DirSync access check:
+CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H (7.5)
+
+=================================
+Workaround and mitigating factors
+=================================
+
+If no RODC accounts are in use in the domain, and DirSync users set
+LDAP_DIRSYNC_OBJECT_SECURITY then there is no need to give this right
+to any users.  If only privileged accounts have this right, only the
+error path vulnerability exists.
+
+Since Windows 2003 and in all versions of Samba, it has not been
+required to assign accounts this "Get Changes" / GUID_DRS_GET_CHANGES
+right to use LDAP DirSync, provided that the
+LDAP_DIRSYNC_OBJECT_SECURITY it set in the control.
+
+If any unprivileged accounts do have this right, and either no longer
+use DirSync or use LDAP_DIRSYNC_OBJECT_SECURITY, this should be
+removed.
+
+GUID_DRS_GET_CHANGES / 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 is an
+extended right set in the ntSecurityDescriptor on the NC root (the DN
+at the top of each partition).  These are for example the domain DN,
+configuration DN etc.  The domain DN is the most important.
+
+=======
+Credits
+=======
+
+Originally reported by Andrew Bartlett of Catalyst and the Samba Team
+during routine code review.
+
+Patches provided by Andrew Bartlett of Catalyst and the Samba team.
+
+==========================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+==========================================================
+
+
+
+ + diff --git a/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html.txt b/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html.txt new file mode 100644 index 000000000..317d5a8b9 --- /dev/null +++ b/vulnerabilities/tests/test_data/samba/CVE-2023-4154.html.txt @@ -0,0 +1,103 @@ +=========================================================== +== Subject: Samba AD DC password exposure to privileged +== users and RODCs +== +== CVE ID#: CVE-2023-4154 +== +== Versions: All versions since Samba 4.0.0 +== +== Summary: An RODC and a user with the GET_CHANGES +== right can view all attributes, including +== secrets and passwords. +== +== Additionally, the access check fails open +== on error conditions. +=========================================================== + +=========== +Description +=========== + +In normal operation, passwords and (most) secrets are never disclosed +over LDAP in Active Directory. + +However, due to a design flaw in Samba's implementation of the DirSync +control, Active Directory accounts authorized to do some replication, +but not to replicate sensitive attributes, can instead replicate +critical domain passwords and secrets. + +In a default installation, this means that RODC DC accounts (which +should only be permitted to replicate some passwords) can instead +obtain all domain secrets, including the core AD secret: the krbtgt +password. + +RODCs are given this permission as part of their installation for DRS +replication. This vulnerability removes the RODC / DC distinction. + +Secondly, and just as problematically, the access check for this +functionality did not account for error conditions - errors like +out of memory were regarded as success. This is sometimes described +as "fail open". In these error conditions, some of which (eg out of +memory) may be influenced by a low-privileged attacker, access to the +secret attributes could be obtained! + + +================== +Patch Availability +================== + +Patches addressing both these issues have been posted to: + + https://www.samba.org/samba/security/ + +Additionally, Samba 4.19.1, 4.18.8 and 4.17.12 have been issued +as security releases to correct the defect. Samba administrators are +advised to upgrade to these releases or apply the patch as soon +as possible. + +================== +CVSSv3 calculation +================== + +For password disclosure to RODCs and other privileged accounts: +CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H (7.2) + +For the fail open on the DirSync access check: +CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H (7.5) + +================================= +Workaround and mitigating factors +================================= + +If no RODC accounts are in use in the domain, and DirSync users set +LDAP_DIRSYNC_OBJECT_SECURITY then there is no need to give this right +to any users. If only privileged accounts have this right, only the +error path vulnerability exists. + +Since Windows 2003 and in all versions of Samba, it has not been +required to assign accounts this "Get Changes" / GUID_DRS_GET_CHANGES +right to use LDAP DirSync, provided that the +LDAP_DIRSYNC_OBJECT_SECURITY it set in the control. + +If any unprivileged accounts do have this right, and either no longer +use DirSync or use LDAP_DIRSYNC_OBJECT_SECURITY, this should be +removed. + +GUID_DRS_GET_CHANGES / 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 is an +extended right set in the ntSecurityDescriptor on the NC root (the DN +at the top of each partition). These are for example the domain DN, +configuration DN etc. The domain DN is the most important. + +======= +Credits +======= + +Originally reported by Andrew Bartlett of Catalyst and the Samba Team +during routine code review. + +Patches provided by Andrew Bartlett of Catalyst and the Samba team. + +========================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +========================================================== \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/samba/security_advisories.html b/vulnerabilities/tests/test_data/samba/security_advisories.html new file mode 100644 index 000000000..120189ede --- /dev/null +++ b/vulnerabilities/tests/test_data/samba/security_advisories.html @@ -0,0 +1,53 @@ + + + + +Samba - Security Announcement Archive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date issuedPatch linksIssue descriptionAffected releasesCVE IDAnnouncement
October 10, 2023 + 4.19.1 + 4.18.8 + 4.17.12 + Password exposure to privileged users and RODCsAll versions since Samba 4.0.0CVE-2023-4154Announcement
August 8, 2023 + 4.19.0 + 4.18.6 + 4.17.10 + Multiple security flaws in Samba Active DirectoryAll versions of Samba prior to 4.17.10, 4.18.6, and 4.19.0 + CVE-2023-3961 + CVE-2023-3962 + + Announcement + Announcement +
+ + + From 47d2131af28cde70a418cd6e4b98afb95793d561 Mon Sep 17 00:00:00 2001 From: Rishi Garg Date: Sat, 8 Mar 2025 17:23:34 +0530 Subject: [PATCH 2/3] Adds Samba Pipeline to __init__.py Signed-off-by: Rishi Garg --- vulnerabilities/importers/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py index 3f429f669..c22de38ea 100644 --- a/vulnerabilities/importers/__init__.py +++ b/vulnerabilities/importers/__init__.py @@ -42,6 +42,7 @@ from vulnerabilities.pipelines import nvd_importer from vulnerabilities.pipelines import pypa_importer from vulnerabilities.pipelines import pysec_importer +from vulnerabilities.pipelines import samba_importer IMPORTERS_REGISTRY = [ openssl.OpensslImporter, @@ -78,6 +79,7 @@ nvd_importer.NVDImporterPipeline, pysec_importer.PyPIImporterPipeline, alpine_linux_importer.AlpineLinuxImporterPipeline, + samba_importer.SambaImporterPipeline, ] IMPORTERS_REGISTRY = { From 32e9819235ac8904910e81e983c7c7217b646236 Mon Sep 17 00:00:00 2001 From: Rishi Garg Date: Sat, 8 Mar 2025 17:28:52 +0530 Subject: [PATCH 3/3] Samba advisory license update Signed-off-by: Rishi Garg --- vulnerabilities/pipelines/samba_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulnerabilities/pipelines/samba_importer.py b/vulnerabilities/pipelines/samba_importer.py index bd2dd4443..74bbf6977 100644 --- a/vulnerabilities/pipelines/samba_importer.py +++ b/vulnerabilities/pipelines/samba_importer.py @@ -34,7 +34,7 @@ class SambaImporterPipeline(VulnerableCodeBaseImporterPipeline): pipeline_id = "samba_importer" spdx_license_expression = "GPL-3.0-only" - license_url = "https://www.samba.org/samba/docs/GPL.txt" + license_url = "https://www.samba.org/samba/ms_license.html" url = "https://www.samba.org/samba/history/security.html" importer_name = "Samba Importer"