Created
April 29, 2025 19:36
-
-
Save avishaifrad/f4e23a97156b1905a7ec8b962a9f2bc8 to your computer and use it in GitHub Desktop.
CVE-2025-31324-Scanner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
CVE-2025-31324 Vulnerability Scanner | |
This tool checks whether a SAP system is vulnerable to CVE-2025-31324. | |
CVE-2025-31324 is a critical vulnerability (CVSS 10) affecting SAP NetWeaver AS | |
with Visual Composer technology. | |
DISCLAIMER: This tool is provided "as is", without warranties or guarantees | |
of any kind, express or implied. | |
Version: 1.0.0 | |
""" | |
import argparse | |
import requests | |
import sys | |
import urllib3 | |
import urllib.parse | |
from datetime import datetime | |
# Suppress insecure request warnings - for testing potentially vulnerable systems | |
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) | |
# Tool version | |
__version__ = "1.0.0" | |
# Constants for vulnerability status | |
VULNERABLE = "vulnerable" | |
NOT_VULNERABLE = "not_vulnerable" | |
UNKNOWN = "unknown" | |
def print_banner(): | |
"""Print scanner banner with version information.""" | |
banner = f""" | |
============================================================ | |
CVE-2025-31324 Vulnerability Scanner v{__version__} | |
============================================================ | |
This tool will check if your SAP system is vulnerable to | |
CVE-2025-31324 (SAP Security Note 3594142) - CVSS Score 10.0 | |
Scan started at: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | |
""" | |
print(banner) | |
def parse_url(url, port=None): | |
""" | |
Parse the provided URL and return components needed for vulnerability check. | |
Args: | |
url (str): The URL to the SAP system (can be a full URL or just a hostname) | |
port (int, optional): Port number to override the one in URL if provided | |
Returns: | |
tuple: (base_url, full_url) - base URL and complete URL for vulnerability check | |
""" | |
# Add scheme if not provided | |
if not url.startswith('http://') and not url.startswith('https://'): | |
url = 'https://' + url | |
# Parse the URL to get its components | |
parsed_url = urllib.parse.urlparse(url) | |
# Set default scheme to https if not provided | |
scheme = parsed_url.scheme or 'https' | |
# Extract hostname | |
hostname = parsed_url.netloc | |
# If hostname contains port, extract it | |
if ':' in hostname: | |
hostname = hostname.split(':')[0] | |
# Determine the port to use (priority: provided port param, URL port, default based on scheme) | |
if port is not None: | |
# Use the port parameter provided by the user | |
port_to_use = port | |
elif parsed_url.port is not None: | |
# Use the port from the URL | |
port_to_use = parsed_url.port | |
else: | |
# Default port based on scheme | |
port_to_use = 443 if scheme == 'https' else 80 | |
# Create the base URL with scheme, hostname, and port | |
base_url = f"{scheme}://{hostname}:{port_to_use}" | |
# Create the full URL for the vulnerability check | |
full_url = f"{base_url}/developmentserver/metadatauploader" | |
return base_url, full_url | |
def check_vulnerability(url, port=None): | |
""" | |
Check if the target SAP system is vulnerable to CVE-2025-31324. | |
Args: | |
url (str): The URL to the SAP system | |
port (int, optional): Port number to override the one in URL if provided | |
Returns: | |
str: Status indicating if the system is vulnerable ("vulnerable", "not_vulnerable", or "unknown") | |
""" | |
# Parse the URL to get base_url and the full URL for vulnerability check | |
base_url, full_url = parse_url(url, port) | |
print(f"[*] Initiating vulnerability check against: {full_url}") | |
try: | |
# Use HEAD request to check the vulnerability with a timeout | |
response = requests.head(full_url, timeout=10, verify=False) | |
status_code = response.status_code | |
# Vulnerability check logic: | |
# If status code is 200 and no Set-Cookie header is present, system appears vulnerable | |
if status_code == 200 and 'Set-Cookie' not in response.headers: | |
print(f"[!] SAP System at {base_url} IS VULNERABLE to CVE-2025-31324.") | |
return VULNERABLE | |
elif status_code == 404: | |
print(f"[-] SAP System at {base_url} DOES NOT appear to have the Visual Composer component installed or available.") | |
return NOT_VULNERABLE | |
else: | |
print(f"[-] The SAP system at {base_url} DOES NOT appear to be vulnerable to CVE-2025-31324.") | |
return NOT_VULNERABLE | |
except requests.exceptions.RequestException as e: | |
print(f"[!] Connection error while testing vulnerability: {e}") | |
return UNKNOWN | |
def print_summary(vulnerability_status): | |
""" | |
Print a summary of the scan results. | |
Args: | |
vulnerability_status (str): Status indicating if the system is vulnerable | |
("vulnerable", "not_vulnerable", or "unknown") | |
""" | |
print("\n" + "="*60) | |
print(" SCAN SUMMARY ") | |
print("="*60) | |
if vulnerability_status == VULNERABLE: | |
print("[!] System appears VULNERABLE to CVE-2025-31324") | |
print("[+] ACTION: Apply SAP Security Note 3594142 immediately") | |
elif vulnerability_status == NOT_VULNERABLE: | |
print("[-] System does not appear to be vulnerable to CVE-2025-31324") | |
else: # UNKNOWN | |
print("[?] Could not determine if the system is vulnerable to CVE-2025-31324") | |
print("[*] ACTION: Check network connectivity and try again") | |
print("\nScan completed at: " + datetime.now().strftime("%Y-%m-%d %H:%M:%S")) | |
print("="*60) | |
def main(): | |
"""Main function to parse arguments and run the vulnerability check.""" | |
parser = argparse.ArgumentParser( | |
description=( | |
"CVE-2025-31324 Vulnerability Scanner\n\n" | |
"This tool checks if your SAP system is vulnerable to CVE-2025-31324 (CVSS 10.0 - Critical)\n\n" | |
"Example usage: python CVE-2025-31324-Scanner.py https://sap.example.com" | |
), | |
formatter_class=argparse.RawTextHelpFormatter | |
) | |
parser.add_argument( | |
"url", | |
help="URL to the SAP system (e.g., https://sap.example.com or just sap.example.com)" | |
) | |
parser.add_argument( | |
"--port", | |
type=int, | |
help="Port number of the SAP system (overrides port in URL if specified, default: 443 for https, 80 for http)", | |
required=False | |
) | |
# Parse the command line arguments | |
args = parser.parse_args() | |
# Print the banner | |
print_banner() | |
# Run the vulnerability check | |
vulnerability_status = check_vulnerability(args.url, args.port) | |
# Print summary | |
print_summary(vulnerability_status) | |
# Return appropriate exit code: | |
# 0 = not vulnerable | |
# 1 = vulnerable | |
# 2 = unknown status | |
if vulnerability_status == VULNERABLE: | |
sys.exit(1) | |
elif vulnerability_status == UNKNOWN: | |
sys.exit(2) | |
else: # NOT_VULNERABLE | |
sys.exit(0) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment