Skip to content

Commit

Permalink
Add forti vuln module (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matie26 authored Jul 3, 2024
1 parent 000b889 commit 770897b
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 2 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ AGPL-3.0.
Uses https://github.com/sqlmapproject/sqlmap under the hood. Finds SQL injection vulnerabilities and is
licensed under GPL-2.0.

### `forti_vuln`
Uses slightly modified https://github.com/BishopFox/cve-2024-21762-check under the hood. Detects if Fortigate devices are vulnerable to CVE-2024-21762 and is licensed under GPL-3.0.

### `wpscan`
Uses https://github.com/wpscanteam/wpscan under the hood. Finds vulnerabilities on sites that use WordPress.
By using this module you confirm that you have read carefully the terms and conditions of the license in
Expand Down Expand Up @@ -73,3 +76,4 @@ We kindly remind you that:
* by contributing to the `dns_reaper` module you agree that the AGPL-3.0 License shall apply to your input automatically, without the need for any additional declarations to be made.
* by contributing to the `ssl_checks` module you agree that the AGPL-3.0 License shall apply to your input automatically, without the need for any additional declarations to be made.
* by contributing to the `sqlmap` module you agree that the GPL-2.0 License shall apply to your input automatically, without the need for any additional declarations to be made.
* by contributing to the `forti_vuln` module you agree that the GPL-3.0 License shall apply to your input automatically, without the need for any additional declarations to be made.
40 changes: 40 additions & 0 deletions autoreporter_addons/forti_vuln/reporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pathlib import Path
from typing import Any, Dict, List

from artemis.reporting.base.language import Language
from artemis.reporting.base.report import Report
from artemis.reporting.base.report_type import ReportType
from artemis.reporting.base.reporter import Reporter
from artemis.reporting.base.templating import ReportEmailTemplateFragment
from artemis.reporting.utils import get_top_level_target


class FortiVulnReporter(Reporter): # type: ignore
VULNERABLE_FORTIOS = ReportType("forti_vuln")

@staticmethod
def create_reports(task_result: Dict[str, Any], language: Language) -> List[Report]:

if task_result["headers"]["receiver"] != "forti_vuln":
return []

if not task_result["status"] == "INTERESTING":
return []

return [
Report(
top_level_target=get_top_level_target(task_result),
target=f"https://{task_result['target_string']}",
report_type=FortiVulnReporter.VULNERABLE_FORTIOS,
timestamp=task_result["created_at"],
additional_data={"vuln": task_result["result"]},
)
]

@staticmethod
def get_email_template_fragments() -> List[ReportEmailTemplateFragment]:
return [
ReportEmailTemplateFragment.from_file(
str(Path(__file__).parents[0] / "template_vulnerable_fortios.jinja2"), priority=10
),
]
14 changes: 14 additions & 0 deletions autoreporter_addons/forti_vuln/template_vulnerable_fortios.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% if "forti_vuln" in data.contains_type %}
<li>{% trans %}We have identified that the following Fortinet VPN gateways are affected by the critical CVE-2024-21762 vulnerability, which allows remote code execution without authentication:{% endtrans %}
<ul>
{% for report in data.reports %}
{% if report.report_type == "forti_vuln" %}
<li>
{{ report.target }}
{{ report_meta(report) }}
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#: autoreporter_addons/forti_vuln/template_vulnerable_fortios.jinja2:2
msgid ""
"We have identified that the following Fortinet VPN gateways are affected "
"by the critical CVE-2024-21762 vulnerability, which allows remote code "
"execution without authentication:"
msgstr ""
6 changes: 6 additions & 0 deletions autoreporter_addons/forti_vuln/translations/messages.pot
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#: autoreporter_addons/forti_vuln/template_vulnerable_fortios.jinja2:2
msgid ""
"We have identified that the following Fortinet VPN gateways are affected "
"by the critical CVE-2024-21762 vulnerability, which allows remote code "
"execution without authentication:"
msgstr ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#: autoreporter_addons/forti_vuln/template_vulnerable_fortios.jinja2:2
msgid ""
"We have identified that the following Fortinet VPN gateways are affected "
"by the critical CVE-2024-21762 vulnerability, which allows remote code "
"execution without authentication:"
msgstr ""
"Wykryto, że następujące bramy Fortinet VPN są dotknięte krytyczną "
"podatnością CVE-2024-21762, która umożliwia zdalne wykonanie kodu bez "
"uwierzytelnienia:"
17 changes: 15 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ services:
restart: always
command: "python3 -m artemis.modules.karton_dns_reaper"

karton-forti_vuln:
build:
context: Artemis-modules-extra
dockerfile: forti_vuln/Dockerfile
volumes:
- "./docker/karton.ini:/etc/karton/karton.ini"
- "${DOCKER_COMPOSE_ADDITIONAL_SHARED_DIRECTORY:-./shared}:/shared/"
depends_on: [karton-system]
env_file: .env
restart: always
command: "python3 -m artemis.modules.forti_vuln"

karton-sqlmap:
build:
context: Artemis-modules-extra
Expand Down Expand Up @@ -39,6 +51,7 @@ services:
autoreporter:
volumes:
- ./Artemis-modules-extra/extra_modules_config.py:/opt/extra_modules_config.py
- ./Artemis-modules-extra/autoreporter_addons/ssl_checks/:/opt/artemis/reporting/modules/ssl_checks/
- ./Artemis-modules-extra/autoreporter_addons/sqlmap/:/opt/artemis/reporting/modules/sqlmap/
- ./Artemis-modules-extra/autoreporter_addons/dns_reaper/:/opt/artemis/reporting/modules/dns_reaper/
- ./Artemis-modules-extra/autoreporter_addons/forti_vuln/:/opt/artemis/reporting/modules/forti_vuln/
- ./Artemis-modules-extra/autoreporter_addons/sqlmap/:/opt/artemis/reporting/modules/sqlmap/
- ./Artemis-modules-extra/autoreporter_addons/ssl_checks/:/opt/artemis/reporting/modules/ssl_checks/
5 changes: 5 additions & 0 deletions forti_vuln/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM certpl/artemis:latest

WORKDIR /opt/

COPY forti_vuln/forti_vuln.py /opt/artemis/modules/
117 changes: 117 additions & 0 deletions forti_vuln/forti_vuln.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env python3
import socket
import ssl
from typing import Optional, Tuple

from artemis.binds import Device, TaskStatus, TaskType
from artemis.config import Config
from artemis.module_base import ArtemisBase
from artemis.task_utils import get_target_host
from artemis.utils import throttle_request
from karton.core import Task

CONTROL_REQUEST = """POST /remote/VULNCHECK HTTP/1.1\r
Host: {}\r
User-Agent: {}\r
Transfer-Encoding: chunked\r
\r
0\r
\r
\r
"""

VULN_CHECK_REQUEST = """POST /remote/VULNCHECK HTTP/1.1\r
Host: {}\r
User-Agent: {}\r
Transfer-Encoding: chunked\r
\r
0000000000000000FF\r
\r
"""


class FortiVuln(ArtemisBase): # type: ignore
"""
Checks FortiOS instance for CVE-2024-21762 vulnerability
source: https://github.com/BishopFox/CVE-2024-21762-check
"""

identity = "forti_vuln"
filters = [
{"type": TaskType.DEVICE.value, "device": Device.FORTIOS.value},
]

@staticmethod
def _send_req(ssl_context: Optional[ssl.SSLContext], address: Tuple[str, int], req: bytes) -> int:
try:
s = socket.create_connection(address, timeout=5)
except Exception:
return -1

if ssl_context is not None:
ss = ssl_context.wrap_socket(s)
ss.send(req)
else:
s.send(req)

try:
if ssl_context is not None:
ss.read(2048)
else:
s.recv(2048)
return 1
except socket.timeout:
return 0

def vuln_check(self, host: str, port: int, is_ssl: bool) -> int:
ssl_context = None
if is_ssl:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

http_host = f"{host}:{port}"
self.log.info(f"forti vuln scanning {http_host}")

user_agent = "FortiOS vulnerability scanner"
if Config.Miscellaneous.CUSTOM_USER_AGENT:
user_agent = Config.Miscellaneous.CUSTOM_USER_AGENT

r1 = throttle_request(
lambda: self._send_req(ssl_context, (host, port), CONTROL_REQUEST.format(http_host, user_agent).encode())
)
if r1 in [-1, 0]:
return -1
else:
r2 = throttle_request(
lambda: self._send_req(
ssl_context, (host, port), VULN_CHECK_REQUEST.format(http_host, user_agent).encode()
)
)
if r2 == 0:
return 1
return 0

def run(self, current_task: Task) -> None:
result = []
status = TaskStatus.OK
status_reason = None

ssl = current_task.get_payload("ssl")
host = get_target_host(current_task)
port = current_task.get_payload("port")
check = self.vuln_check(host, port, ssl)

if check == -1:
status = TaskStatus.ERROR
status_reason = "Could not send control request"
elif check == 1:
result.append("CVE-2024-21762")
status = TaskStatus.INTERESTING
status_reason = "Detected CVE-2024-21762 vulnerability"

self.db.save_task_result(task=current_task, status=status, status_reason=status_reason, data=result)


if __name__ == "__main__":
FortiVuln().loop()

0 comments on commit 770897b

Please sign in to comment.