Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/CVE 2024 50623 #159

Merged
merged 5 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions agent/exploits/cve_2024_50623.py
Original file line number Diff line number Diff line change
@@ -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
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved

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")
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,
)
20 changes: 17 additions & 3 deletions agent/exploits/webexploit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
):
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
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]
Expand Down
76 changes: 76 additions & 0 deletions tests/exploits/cve_2024_50623_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""Unit tests for Agent Asteroid: CVE-2024-50623"""
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved

"""Unit tests for Agent Asteroid: CVE-2024-50623"""
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved

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(
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
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
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
assert len(vulnerabilities) > 0
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
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(
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
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
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved


def testCVE202450623_whenTargetNotCleoProduct_reportNothing(
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
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
PiranhaSa marked this conversation as resolved.
Show resolved Hide resolved
assert len(vulnerabilities) == 0