Skip to content

Commit

Permalink
CVE-2023-35078 finder v1 (1.10) (#1570)
Browse files Browse the repository at this point in the history
Co-authored-by: noamblitz <[email protected]>
Co-authored-by: ammar92 <[email protected]>
Co-authored-by: Jan Klopper <[email protected]>
  • Loading branch information
4 people authored Aug 7, 2023
1 parent 4a46d2f commit a342c07
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 2 deletions.
3 changes: 1 addition & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ repos:
requirements-.*.txt$ |
retirejs.json$ |
^boefjes/boefjes/plugins/kat_fierce/lists |
^boefjes/tests/examples/inputs/cve-result-without-cvss.json |
^boefjes/tests/examples/inputs/cve-result-with-cvss2.json |
^boefjes/tests/examples |
^keiko/glossaries |
^keiko/templates/.*/template.tex$ |
^rocky/assets/js/vendor |
Expand Down
Empty file.
13 changes: 13 additions & 0 deletions boefjes/boefjes/plugins/kat_cve_2023_35078/boefje.json
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.
23 changes: 23 additions & 0 deletions boefjes/boefjes/plugins/kat_cve_2023_35078/main.py
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")]
86 changes: 86 additions & 0 deletions boefjes/boefjes/plugins/kat_cve_2023_35078/normalize.py
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 boefjes/boefjes/plugins/kat_cve_2023_35078/normalizer.json
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.
61 changes: 61 additions & 0 deletions boefjes/tests/examples/cve_2023_35078_not_vulnerable.html
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>
59 changes: 59 additions & 0 deletions boefjes/tests/examples/cve_2023_35078_vulnerable.html
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>
47 changes: 47 additions & 0 deletions boefjes/tests/test_cve-2023-35078.py
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)

0 comments on commit a342c07

Please sign in to comment.