From f947f2b46c52bc453858bf4e030ec9388c29b52d Mon Sep 17 00:00:00 2001 From: rabbitali Date: Mon, 18 Sep 2023 17:31:06 +0800 Subject: [PATCH 1/1] update method of querying fixed cves by dnf plugin --- ceres/manages/vulnerability_manage.py | 80 ++++++++++++++++++++------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py index ab4b41c..ab10381 100644 --- a/ceres/manages/vulnerability_manage.py +++ b/ceres/manages/vulnerability_manage.py @@ -132,7 +132,7 @@ class VulnerabilityManage: { "check_items": items_check_log, "unfixed_cves": self._query_unfixed_cves_by_dnf_plugin() or self._query_unfixed_cves_by_dnf(), - "fixed_cves": self._query_fixed_cves(), + "fixed_cves": self._query_fixed_cves_by_dnf_plugin() or self._query_fixed_cves_by_dnf(), } ) return SUCCESS, cve_scan_result @@ -339,7 +339,7 @@ class VulnerabilityManage: return cve_info_list - def _query_fixed_cves(self) -> list: + def _query_fixed_cves_by_dnf(self) -> list: """ parse the fixed kernel vulnerability info by dnf @@ -348,7 +348,6 @@ class VulnerabilityManage: list: cve info e.g [ {"cve_id": "CVE-XXXX-XXXX","installed_rpm": "kernel-version-release.arch", "fix_way":"coldpatch"}, - {"cve_id": "CVE-XXXX-XXXX","installed_rpm": "xxxx", "fix_way": "hotpatch", "hp_status": "ACCEPTED"} ] """ @@ -380,17 +379,70 @@ class VulnerabilityManage: fixed_cves.append( {"cve_id": cve_id, "installed_rpm": self.installed_rpm_info.get(rpm_name), "fix_way": "coldpatch"} ) - fixed_cves.extend(self._query_applied_hotpatch()) return fixed_cves - def _query_applied_hotpatch(self) -> list: + def _query_fixed_cves_by_dnf_plugin(self) -> list: """ - parse kernel hotpatch info which has been applied by dnf hotpatch plugin (hotpatch) + parse the fixed kernel vulnerability info by dnf plugin Return: list: hotpatch info list. e.g [{"cve_id": "CVE-XXXX-XXXX", "fix_way": "hotpatch", "hp_status": "ACCEPTED", "installed_rpm":"xxxx"}] + """ + # Example of command execution result: + # Last metadata expiration check: 0:31:50 ago on Mon 07 Aug 2023 10:26:32 AM CST. + # CVE-2023-1981 Moderate/Sec. avahi-libs-0.8-9.oe1.x86_64 - + # CVE-2021-42574 Important/Sec. binutils-2.34-19.oe1.x86_64 - + # CVE-2023-1513 Important/Sec. kernel-4.19.90-2304.1.0.0196.oe1.x86_64 patch-kernel-4.19.90-2112... + + code, stdout, stderr = execute_shell_command("dnf hot-updateinfo list cves --installed") + if code != CommandExitCode.SUCCEED: + LOGGER.error("query unfixed cve info failed by dnf!") + LOGGER.error(stderr) + return [] + + # Example of regex matching result: + # [ + # ("CVE-2023-1513", "Important/Sec.", "kernel-4.19.90-2304.1.0.0196.oe1.x86_64", "patch-kernel-4.19.90-2112.."), + # ("CVE-2021-xxxx", "Important/Sec.", "-", "patch-redis-6.2.5-1-SGL_CVE_2023_1111_CVE_2023_1112-1-1.x86_64") + # ] + hotpatch_status = self._query_applied_hotpatch_status() + all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+|-)\s+(patch-kernel\S+|-)", stdout) + + cve_info_fixed_by_coldpatch, cve_info_fixed_by_hotpatch, hotpatch_dic = [], [], defaultdict(str) + for cve_id, _, coldpatch, hotpatch in all_cve_info: + if hotpatch == "-": + cve_info_fixed_by_coldpatch.append( + { + "cve_id": cve_id, + "installed_rpm": self.installed_rpm_info.get(coldpatch.rsplit("-", 2)[0]), + "fix_way": "coldpatch", + } + ) + else: + cve_info_fixed_by_hotpatch.append({"cve_id": cve_id, "fix_way": "hotpatch", "installed_rpm": hotpatch}) + + hotpatch_dic_key = hotpatch.rsplit("-", 2)[0] + if hotpatch_dic_key.endswith("ACC"): + hotpatch_dic[hotpatch_dic_key] = max(hotpatch, hotpatch_dic.get(hotpatch_dic_key, hotpatch)) + + for cve_info in cve_info_fixed_by_hotpatch: + hotpatch_dic_key = cve_info["installed_rpm"].rsplit("-", 2)[0] + + if hotpatch_dic_key in hotpatch_dic: + cve_info["installed_rpm"] = hotpatch_dic[hotpatch_dic_key] + cve_info["hp_status"] = hotpatch_status.get(cve_info["installed_rpm"].rsplit(".", 1)[0], "") + + return cve_info_fixed_by_coldpatch + cve_info_fixed_by_hotpatch + + def _query_applied_hotpatch_status(self) -> Dict[str, str]: + """ + query applied hotpatch with its status + + Return: + dict: key is hotpatch name, value is its status. e.g {"patch-redis-6.2.5-1-ACC-1-3": "ACTIVED"} + """ # Example of command execution result: # Last metadata expiration check: 0:28:36 ago on Mon 07 Aug 2023 10:26:32 AM CST. @@ -409,7 +461,7 @@ class VulnerabilityManage: # CVE-2023-1112 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-cli NOT-APPLIED # CVE-2023-1111 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED # CVE-2023-1112 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED - result = [] + result = {} code, stdout, stderr = execute_shell_command("dnf hotpatch --list cves") if code != CommandExitCode.SUCCEED: LOGGER.error("query applied hotpatch info failed!") @@ -426,11 +478,6 @@ class VulnerabilityManage: if not applied_hotpatch_info_list: return result - code, arch, _ = execute_shell_command("uname -m") - if code != CommandExitCode.SUCCEED: - LOGGER.debug("Failed to query host arch info!") - arch = "unknown_arch" - record_key_set = set() for cve_id, patch_name, hotpatch_status in applied_hotpatch_info_list: rpm = patch_name.split("-", 1)[0] @@ -445,14 +492,7 @@ class VulnerabilityManage: and (hotpatch_status in ("ACTIVED", "ACCEPTED")) and record_key not in record_key_set ): - result.append( - { - "cve_id": cve_id, - "installed_rpm": f"patch-{patch_name.rsplit('/',1)[0].replace('/','-')}.{arch}", - "fix_way": "hotpatch", - "hp_status": hotpatch_status, - } - ) + result[f"patch-{patch_name.rsplit('/',1)[0].replace('/','-')}"] = hotpatch_status record_key_set.add(record_key) return result -- 2.33.1.windows.1