From 75326dbdb393c49a1c10fc103afe2d8b38b469b4 Mon Sep 17 00:00:00 2001 From: pirahnasa Date: Fri, 13 Dec 2024 17:15:16 +0100 Subject: [PATCH 1/5] Add version detection for cleo cve-2024-50623 --- agent/exploits/cve_2024_50623.py | 43 +++++++++++++++ agent/exploits/webexploit.py | 20 +++++-- tests/exploits/cve_2024_50623_test.py | 76 +++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 agent/exploits/cve_2024_50623.py create mode 100644 tests/exploits/cve_2024_50623_test.py diff --git a/agent/exploits/cve_2024_50623.py b/agent/exploits/cve_2024_50623.py new file mode 100644 index 0000000..009c1db --- /dev/null +++ b/agent/exploits/cve_2024_50623.py @@ -0,0 +1,43 @@ +"""Agent Asteroid implementation for CVE-2024-50623""" + +import re +from packaging import version + +from agent import definitions +from agent import exploits_registry +from agent.exploits import webexploit + +VERSION_PATTERN = re.compile( + r"(?:VLTrader|Harmony|LexiCom)/((?:[0-4](?:\.\d+){0,3})|5(?:\.[0-7](?:\.\d{1,2}){0,2})?|5\.8(?:\.0(?:\.(?:0|[1-9]|1[0-9]|2[0-1]))?)?)\s*\(" +) +MAX_VULNERABLE_VERSION = version.parse("5.8.0.21") +MIN_VULNERABLE_VERSION = version.parse("0.0.0") # No minimum version specified +VULNERABILITY_TITLE = ( + "Cleo Harmony, VLTrader, and LexiCom - Unrestricted File Upload and Download " + "Leading to Remote Code Execution" +) +VULNERABILITY_REFERENCE = "CVE-2024-50623" +VULNERABILITY_DESCRIPTION = ( + "In Cleo Harmony before 5.8.0.21, VLTrader before 5.8.0.21, and LexiCom before " + "5.8.0.21, there is an unrestricted file upload and download vulnerability. " + "Exploitation of this issue could lead to remote code execution." +) +RISK_RATING = "CRITICAL" + + +@exploits_registry.register +class CVE202450623Exploit(webexploit.WebExploit): + accept_request = definitions.Request(method="GET", path="/") + check_request = definitions.Request(method="GET", path="/") + accept_pattern = [re.compile(r"Cleo (VLTrader|Harmony|LexiCom)/[\d.]+")] + version_pattern = VERSION_PATTERN + vuln_ranges = [ + definitions.VulnRange(MIN_VULNERABLE_VERSION, MAX_VULNERABLE_VERSION) + ] + + metadata = definitions.VulnerabilityMetadata( + title=VULNERABILITY_TITLE, + description=VULNERABILITY_DESCRIPTION, + reference=VULNERABILITY_REFERENCE, + risk_rating=RISK_RATING, + ) diff --git a/agent/exploits/webexploit.py b/agent/exploits/webexploit.py index 6646c3e..bacaeb8 100644 --- a/agent/exploits/webexploit.py +++ b/agent/exploits/webexploit.py @@ -20,6 +20,7 @@ class WebExploit(definitions.Exploit): check_request: definitions.Request accept_pattern: list[re.Pattern[str]] = [] match_pattern: list[re.Pattern[str]] = [] + header_name: str vuln_ranges: list[definitions.VulnRange] = [] metadata: definitions.VulnerabilityMetadata version_pattern: re.Pattern[str] | None = None @@ -52,7 +53,10 @@ def accept(self, target: definitions.Target) -> bool: return False for pattern in self.accept_pattern: - if pattern.search(resp.text) is not None: + if ( + pattern.search(resp.text) is not None + or pattern.search(str(resp.headers)) is not None + ): return True return False @@ -86,14 +90,24 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: return vulnerabilities for pattern in self.match_pattern: - if pattern.search(resp.text) is not None: + if ( + pattern.search(resp.text) is not None + or pattern.search(str(resp.headers)) is not None + ): vulnerability = self._create_vulnerability(target) vulnerabilities.append(vulnerability) return vulnerabilities if self.vuln_ranges is not None: if self.version_pattern is not None: - if (matched := self.version_pattern.findall(resp.text)) is not None: + if ( + self.version_pattern.findall(resp.text) + ) is not None or self.version_pattern.findall( + str(resp.headers) + ) is not None: + matched = self.version_pattern.findall( + resp.text + ) or self.version_pattern.findall(str(resp.headers)) for extracted_version in matched: if isinstance(extracted_version, tuple): extracted_version = extracted_version[0] diff --git a/tests/exploits/cve_2024_50623_test.py b/tests/exploits/cve_2024_50623_test.py new file mode 100644 index 0000000..ead112b --- /dev/null +++ b/tests/exploits/cve_2024_50623_test.py @@ -0,0 +1,76 @@ +"""Unit tests for Agent Asteroid: CVE-2024-50623""" + +"""Unit tests for Agent Asteroid: CVE-2024-50623""" + +import requests_mock as req_mock +from ostorlab.agent.mixins import agent_report_vulnerability_mixin as vuln_mixin + +from agent import definitions +from agent.exploits import cve_2024_50623 + + +def testCVE202450623_whenVulnerable_reportFinding( + requests_mock: req_mock.mocker.Mocker, +) -> None: + """CVE-2024-50623 unit test: case when target is vulnerable.""" + requests_mock.get( + "http://localhost:80/", + text="Cleo VLTrader/5.8.0.20 (Build 12345)", + status_code=200, + ) + exploit_instance = cve_2024_50623.CVE202450623Exploit() + target = definitions.Target("http", "localhost", 80) + + accept = exploit_instance.accept(target) + vulnerabilities = exploit_instance.check(target) + + assert accept is True + assert len(vulnerabilities) > 0 + vulnerability = vulnerabilities[0] + assert ( + vulnerability.entry.title + == "Cleo Harmony, VLTrader, and LexiCom - Unrestricted File Upload and Download Leading to Remote Code Execution" + ) + assert vulnerability.technical_detail == ( + "http://localhost:80 is vulnerable to CVE-2024-50623, Cleo Harmony, VLTrader, and LexiCom -" + " Unrestricted File Upload and Download Leading to Remote Code Execution" + ) + assert vulnerability.risk_rating == vuln_mixin.RiskRating.CRITICAL + + +def testCVE202450623_whenSafe_reportNothing( + requests_mock: req_mock.mocker.Mocker, +) -> None: + """CVE-2024-50623 unit test: case when target is safe.""" + requests_mock.get( + "http://localhost:80/", + text="Cleo VLTrader/5.8.0.22 (Build 12345)", + status_code=200, + ) + exploit_instance = cve_2024_50623.CVE202450623Exploit() + target = definitions.Target("http", "localhost", 80) + + accept = exploit_instance.accept(target) + vulnerabilities = exploit_instance.check(target) + + assert accept is True + assert len(vulnerabilities) == 0 + + +def testCVE202450623_whenTargetNotCleoProduct_reportNothing( + requests_mock: req_mock.mocker.Mocker, +) -> None: + """CVE-2024-50623 unit test: case when target is not a Cleo product.""" + requests_mock.get( + "http://localhost:80/", + text="Not Found", + status_code=404, + ) + exploit_instance = cve_2024_50623.CVE202450623Exploit() + target = definitions.Target("http", "localhost", 80) + + accept = exploit_instance.accept(target) + vulnerabilities = exploit_instance.check(target) + + assert accept is False + assert len(vulnerabilities) == 0 From 080e523e042b71c30fb9dfdfc3f8abc76d604e8d Mon Sep 17 00:00:00 2001 From: pirahnasa Date: Fri, 13 Dec 2024 18:10:36 +0100 Subject: [PATCH 2/5] Add version detection for cleo cve-2024-50623 --- agent/exploits/cve_2024_50623.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/exploits/cve_2024_50623.py b/agent/exploits/cve_2024_50623.py index 009c1db..bcce204 100644 --- a/agent/exploits/cve_2024_50623.py +++ b/agent/exploits/cve_2024_50623.py @@ -11,7 +11,7 @@ r"(?:VLTrader|Harmony|LexiCom)/((?:[0-4](?:\.\d+){0,3})|5(?:\.[0-7](?:\.\d{1,2}){0,2})?|5\.8(?:\.0(?:\.(?:0|[1-9]|1[0-9]|2[0-1]))?)?)\s*\(" ) MAX_VULNERABLE_VERSION = version.parse("5.8.0.21") -MIN_VULNERABLE_VERSION = version.parse("0.0.0") # No minimum version specified +MIN_VULNERABLE_VERSION = version.parse("0.0.0") VULNERABILITY_TITLE = ( "Cleo Harmony, VLTrader, and LexiCom - Unrestricted File Upload and Download " "Leading to Remote Code Execution" From 2a86b1ae495944c9051f5fa74a562a52b697ed42 Mon Sep 17 00:00:00 2001 From: pirahnasa Date: Mon, 16 Dec 2024 11:38:59 +0100 Subject: [PATCH 3/5] Add version detection for cleo cve-2024-50623 --- agent/exploits/webexploit.py | 10 ++++------ tests/exploits/cve_2024_50623_test.py | 2 -- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/agent/exploits/webexploit.py b/agent/exploits/webexploit.py index bacaeb8..b8f5e5d 100644 --- a/agent/exploits/webexploit.py +++ b/agent/exploits/webexploit.py @@ -53,9 +53,8 @@ def accept(self, target: definitions.Target) -> bool: return False for pattern in self.accept_pattern: - if ( - pattern.search(resp.text) is not None - or pattern.search(str(resp.headers)) is not None + if pattern.search(resp.text) is not None or ( + len(resp.headers) > 0 and pattern.search(str(resp.headers)) is not None ): return True return False @@ -90,9 +89,8 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: return vulnerabilities for pattern in self.match_pattern: - if ( - pattern.search(resp.text) is not None - or pattern.search(str(resp.headers)) is not None + if pattern.search(resp.text) is not None or ( + len(resp.headers) > 0 and pattern.search(str(resp.headers)) is not None ): vulnerability = self._create_vulnerability(target) vulnerabilities.append(vulnerability) diff --git a/tests/exploits/cve_2024_50623_test.py b/tests/exploits/cve_2024_50623_test.py index ead112b..6f9de03 100644 --- a/tests/exploits/cve_2024_50623_test.py +++ b/tests/exploits/cve_2024_50623_test.py @@ -1,7 +1,5 @@ """Unit tests for Agent Asteroid: CVE-2024-50623""" -"""Unit tests for Agent Asteroid: CVE-2024-50623""" - import requests_mock as req_mock from ostorlab.agent.mixins import agent_report_vulnerability_mixin as vuln_mixin From 47ad50f66ffd12fc304b4624236c8d6e0a9ca87c Mon Sep 17 00:00:00 2001 From: pirahnasa Date: Mon, 16 Dec 2024 11:58:32 +0100 Subject: [PATCH 4/5] Add version detection for cleo cve-2024-50623 --- agent/exploits/webexploit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/agent/exploits/webexploit.py b/agent/exploits/webexploit.py index b8f5e5d..373bbd7 100644 --- a/agent/exploits/webexploit.py +++ b/agent/exploits/webexploit.py @@ -20,7 +20,6 @@ class WebExploit(definitions.Exploit): check_request: definitions.Request accept_pattern: list[re.Pattern[str]] = [] match_pattern: list[re.Pattern[str]] = [] - header_name: str vuln_ranges: list[definitions.VulnRange] = [] metadata: definitions.VulnerabilityMetadata version_pattern: re.Pattern[str] | None = None From 6f45a08a2c9361eddefabc83ebe7bc95ad865d62 Mon Sep 17 00:00:00 2001 From: PiranhaSa Date: Mon, 16 Dec 2024 15:01:42 +0100 Subject: [PATCH 5/5] Update agent/exploits/cve_2024_50623.py Co-authored-by: Mohamed Elyousfi <144013278+elyousfi5@users.noreply.github.com> --- agent/exploits/cve_2024_50623.py | 1 + 1 file changed, 1 insertion(+) diff --git a/agent/exploits/cve_2024_50623.py b/agent/exploits/cve_2024_50623.py index bcce204..5ff0f76 100644 --- a/agent/exploits/cve_2024_50623.py +++ b/agent/exploits/cve_2024_50623.py @@ -1,6 +1,7 @@ """Agent Asteroid implementation for CVE-2024-50623""" import re + from packaging import version from agent import definitions