-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CVE-2023-35078 finder v1 (1.10) (#1570)
Co-authored-by: noamblitz <[email protected]> Co-authored-by: ammar92 <[email protected]> Co-authored-by: Jan Klopper <[email protected]>
- Loading branch information
1 parent
4a46d2f
commit a342c07
Showing
12 changed files
with
300 additions
and
2 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
Empty file.
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,13 @@ | ||
{ | ||
"id": "CVE_2023_35078", | ||
"name": "CVE_2023_35078", | ||
"description": "Use NFIR script to find CVE-2023-35078", | ||
"consumes": [ | ||
"Website" | ||
], | ||
"produces": [ | ||
"Finding", | ||
"CVEFindingType" | ||
], | ||
"scan_level": 2 | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
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,23 @@ | ||
from typing import List, Tuple, Union | ||
from urllib.parse import urljoin | ||
|
||
import requests | ||
|
||
from boefjes.job_models import BoefjeMeta | ||
|
||
ENDPOINT_PATH = "/mifs/c/windows/api/v2/device/registration" | ||
|
||
|
||
def run(boefje_meta: BoefjeMeta) -> List[Tuple[set, Union[str, bytes]]]: | ||
input_ = boefje_meta.arguments["input"] # input is website | ||
hostname = input_["hostname"]["name"] | ||
service = input_["ip_service"]["service"]["name"] | ||
website = f"{service}://{hostname}" | ||
|
||
full_url = urljoin(website, ENDPOINT_PATH) | ||
response = requests.get(full_url, verify=False, allow_redirects=False) | ||
|
||
if response.status_code == 200: | ||
return [({response.headers.get("content-type")}, response.content)] | ||
else: | ||
return [(set(), "Ivanti Endpoint Manager Mobile (EPMM), formerly MobileIron Core not found")] |
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,86 @@ | ||
from typing import Iterable, List, Tuple, Union | ||
|
||
from boefjes.job_models import NormalizerMeta | ||
from octopoes.models import OOI, Reference | ||
from octopoes.models.ooi.findings import CVEFindingType, Finding | ||
from octopoes.models.ooi.software import Software, SoftwareInstance | ||
from packaging import version | ||
|
||
VULNERABLE_RANGES: List[Tuple[str, str]] = [("0", "11.8.1.1"), ("11.9.0.0", "11.9.1.1"), ("11.10.0.0", "11.10.0.2")] | ||
|
||
|
||
def extract_js_version(html_content: str) -> Union[version.Version, bool]: | ||
telltale = "/mifs/scripts/auth.js?" | ||
telltale_position = html_content.find(telltale) | ||
if telltale_position == -1: | ||
return False | ||
version_end = html_content.find('"', telltale_position) | ||
if version_end == -1: | ||
return False | ||
version_string = html_content[telltale_position + len(telltale) : version_end] | ||
if not version_string: | ||
return False | ||
return version.parse(" ".join(strip_vsp_and_build(version_string))) | ||
|
||
|
||
def extract_css_version(html_content: str) -> Union[version.Version, bool]: | ||
telltale = "/mifs/css/windowsAllAuth.css?" | ||
telltale_position = html_content.find(telltale) | ||
if telltale_position == -1: | ||
return False | ||
version_end = html_content.find('"', telltale_position) | ||
if version_end == -1: | ||
return False | ||
version_string = html_content[telltale_position + len(telltale) : version_end] | ||
if not version_string: | ||
return False | ||
return version.parse(" ".join(strip_vsp_and_build(version_string))) | ||
|
||
|
||
def strip_vsp_and_build(url: str) -> Iterable[str]: | ||
url_parts = url.split() | ||
for part in url_parts: | ||
if str(part).lower() == "vsp": | ||
continue | ||
if str(part).lower() == "build": | ||
break | ||
yield part | ||
|
||
|
||
def is_vulnerable_version( | ||
vulnerable_ranges: List[Tuple[version.Version, version.Version]], detected_version: version.Version | ||
) -> bool: | ||
return any(start <= detected_version < end for start, end in vulnerable_ranges) | ||
|
||
|
||
def run(normalizer_meta: NormalizerMeta, raw: bytes) -> Iterable[OOI]: | ||
ooi = Reference.from_str(normalizer_meta.raw_data.boefje_meta.input_ooi) | ||
html = raw.decode() | ||
js_detected_version = extract_js_version(html) | ||
css_detected_version = extract_css_version(html) | ||
if not js_detected_version and not css_detected_version: | ||
return | ||
|
||
if js_detected_version: | ||
software = Software(name="Ivanti EPMM", version=str(js_detected_version)) | ||
else: | ||
software = Software(name="Ivanti EPMM", version=str(css_detected_version)) | ||
software_instance = SoftwareInstance(ooi=ooi, software=software.reference) | ||
yield software | ||
yield software_instance | ||
if js_detected_version: | ||
vulnerable = is_vulnerable_version( | ||
[(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES], js_detected_version | ||
) | ||
else: | ||
# The CSS version only included the first two parts of the version number so we don't know the patch level | ||
vulnerable = css_detected_version < version.parse("11.8") | ||
if vulnerable: | ||
finding_type = CVEFindingType(id="CVE-2023-35078") | ||
finding = Finding( | ||
finding_type=finding_type.reference, | ||
ooi=software_instance.reference, | ||
description="Software is most likely vulnerable to CVE-2023-35078", | ||
) | ||
yield finding_type | ||
yield finding |
10 changes: 10 additions & 0 deletions
10
boefjes/boefjes/plugins/kat_cve_2023_35078/normalizer.json
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,10 @@ | ||
{ | ||
"id": "kat_CVE_2023_35078_normalize", | ||
"consumes": [ | ||
"CVE_2023_35078" | ||
], | ||
"produces": [ | ||
"Finding", | ||
"CVEFindingType" | ||
] | ||
} |
Empty file.
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,61 @@ | ||
<!DOCTYPE html> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="referrer" content="strict-origin-when-cross-origin" /> | ||
<title>Workplace Sign In</title> | ||
<script type="text/javascript" src="/mifs/scripts/auth.js?VSP 11.10.0.3 Build 2 "></script> | ||
<link href="https://example.com/mifs/css/windowsAllAuth.css?11.10" rel="stylesheet" /> | ||
</head> | ||
<body onload="onLoad();"> | ||
<div class="container" > | ||
<p class="windowsPhoneData" > | ||
<img src="/mifs/whitelabel/mobileiron/img/brand-med.svg" width="400" height="90"/> | ||
</p> | ||
|
||
<form id="form" action="/mifs/c/wp/EnrollmentServer/Authentication.svc" method="POST"> | ||
<h1 class="windowsText">Sign in to your Ivanti account</h1> | ||
<p id="error" class="hidden"></p> | ||
|
||
<p> | ||
<label for="login">Email address</label><br/> | ||
<input id="login" name="login" type="text" value="" autocomplete="on" /> | ||
</p> | ||
|
||
|
||
<p class="textBox"> | ||
<label for="password">Password</label><br/> | ||
<input id="password" name="password" type="password" value="" autocomplete="off" /> | ||
</p> | ||
|
||
|
||
|
||
|
||
<button type="submit" id="signIn" class="button btn-new btn-new-default"> | ||
Sign in | ||
</button> | ||
|
||
<input name="app" type="hidden" value="" /> | ||
<input name="errorCode" id="errorCode" type="hidden" value=""/> | ||
<input name="backOffDelay" id="backOffDelay" type="hidden" value=""/> | ||
</form> | ||
|
||
<div class="windowsText"> | ||
<img src="/mifs/whitelabel/mobileiron/img/brand-med.svg" | ||
alt="Ivanti Logo" style="width: 150pt; height: 43pt;" /> | ||
<p class="description">Ivanti ist führend im Bereich Enterprise Mobility Management und ermöglicht es Unternehmen auf der ganzen Welt, Mobilsysteme als primäre IT-Plattform einzusetzen.<br/><br/>Die Lösungen von Ivanti wurden speziell für Unternehmen entwickelt, die auf Mobilplattformen setzen. Sie ermöglichen Ihnen das Absichern und Verwalten all Ihrer Mobilgeräte und -anwendungen, die auf den führenden Mobilgeräteplattformen laufen, darunter Windows und Windows Phone.</p> | ||
</div> | ||
|
||
</div> | ||
</body> | ||
</html> |
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,59 @@ | ||
<!DOCTYPE html> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<title>Workplace Sign In</title> | ||
<script type="text/javascript" src="/mifs/scripts/auth.js?VSP 10.8.0.0 Build 34 "></script> | ||
<link href="/mifs/css/windowsAllAuth.css?10.8" rel="stylesheet" /> | ||
</head> | ||
<body onload="onLoad();"> | ||
<div class="container" > | ||
<p class="windowsPhoneData" > | ||
<img src="/mifs/whitelabel/mobileiron/img/brand-med.svg" width="400" height="90"/> | ||
</p> | ||
|
||
<form id="form" action="/mifs/c/wp/EnrollmentServer/Authentication.svc" method="POST"> | ||
<h1 class="windowsText">Sign in to your MobileIron account</h1> | ||
<p id="error" class="hidden"></p> | ||
|
||
<p> | ||
<label for="login">Email address</label><br/> | ||
<input id="login" name="login" type="text" value="" autocomplete="on" /> | ||
</p> | ||
|
||
|
||
<p class="textBox"> | ||
<label for="password">Password</label><br/> | ||
<input id="password" name="password" type="password" value="" autocomplete="off" /> | ||
</p> | ||
|
||
|
||
|
||
|
||
<button type="submit" id="signIn" class="button btn-new btn-new-default"> | ||
Sign in | ||
</button> | ||
|
||
<input name="app" type="hidden" value="" /> | ||
<input name="errorCode" id="errorCode" type="hidden" value=""/> | ||
<input name="backOffDelay" id="backOffDelay" type="hidden" value=""/> | ||
</form> | ||
|
||
<div class="windowsText"> | ||
<img src="/mifs/whitelabel/mobileiron/img/brand-med.svg" | ||
alt="MobileIron Logo" style="width: 150pt; height: 43pt;" /> | ||
<p class="description">The leader in enterprise mobility management, MobileIron enables organizations around the world to embrace mobility as their primary IT platform.<br/><br/>MobileIron's solutions are purpose-built for the Mobile First enterprise, allowing you to secure and manage all of your mobile devices and applications running on the leading mobile platforms, including Windows and Windows Phone.</p> | ||
</div> | ||
|
||
</div> | ||
</body> | ||
</html> |
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,47 @@ | ||
from unittest import TestCase | ||
from unittest.mock import MagicMock | ||
|
||
from boefjes.plugins.kat_cve_2023_35078.normalize import VULNERABLE_RANGES, is_vulnerable_version, run | ||
from packaging import version | ||
from tests.stubs import get_dummy_data | ||
|
||
|
||
class CVE_2023_35078Test(TestCase): | ||
maxDiff = None | ||
|
||
def test_vulnerable_version_11_8(self): | ||
detected_version = version.parse("11.8.0.0") | ||
vulnerable_ranges = [(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES] | ||
self.assertTrue(is_vulnerable_version(vulnerable_ranges, detected_version)) | ||
|
||
def test_vulnerable_version_11_9(self): | ||
detected_version = version.parse("11.9.1.0") | ||
vulnerable_ranges = [(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES] | ||
self.assertTrue(is_vulnerable_version(vulnerable_ranges, detected_version)) | ||
|
||
def test_vulnerable_version_11_10(self): | ||
detected_version = version.parse("11.10.0.1") | ||
vulnerable_ranges = [(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES] | ||
self.assertTrue(is_vulnerable_version(vulnerable_ranges, detected_version)) | ||
|
||
def test_patched_version_11_9(self): | ||
detected_version = version.parse("11.9.2.0") | ||
vulnerable_ranges = [(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES] | ||
self.assertFalse(is_vulnerable_version(vulnerable_ranges, detected_version)) | ||
|
||
def test_equal_to_patched_version_11_9(self): | ||
detected_version = version.parse("11.9.1.1") | ||
vulnerable_ranges = [(version.parse(start), version.parse(end)) for start, end in VULNERABLE_RANGES] | ||
self.assertFalse(is_vulnerable_version(vulnerable_ranges, detected_version)) | ||
|
||
|
||
def test_cve_2023_35078_vulnerable(): | ||
oois = set(run(MagicMock(), get_dummy_data("cve_2023_35078_vulnerable.html"))) | ||
|
||
assert any(ooi.object_type == "Finding" for ooi in oois) | ||
|
||
|
||
def test_cve_2023_35078_not_vulnerable(): | ||
oois = set(run(MagicMock(), get_dummy_data("cve_2023_35078_not_vulnerable.html"))) | ||
|
||
assert not any(ooi.object_type == "Finding" for ooi in oois) |